Skip to content

Commit 027db36

Browse files
committed
feat: app layouts, sidebar
1 parent 3fa09ed commit 027db36

File tree

7 files changed

+178
-64
lines changed

7 files changed

+178
-64
lines changed

definitions/vite-cf-DO-KV-runner/src/pages/DemoPage.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
55
import { Link } from 'react-router-dom';
66
import type { DemoItem, ApiResponse } from '@shared/types';
77
import { ThemeToggle } from '@/components/ThemeToggle';
8+
import { AppLayout } from '@/components/layout/AppLayout';
89

910
export function DemoPage() {
1011
const [counter, setCounter] = useState<number>(0);
@@ -39,10 +40,11 @@ export function DemoPage() {
3940
}
4041

4142
return (
42-
<main className="min-h-screen bg-background p-6">
43-
<ThemeToggle />
44-
45-
<div className="max-w-4xl mx-auto space-y-6">
43+
<AppLayout>
44+
<main className="min-h-screen bg-background p-6">
45+
<ThemeToggle />
46+
47+
<div className="max-w-4xl mx-auto space-y-6">
4648
<header className="space-y-2">
4749
<Link to="/">
4850
<Button variant="ghost" size="sm">
@@ -99,7 +101,7 @@ export function DemoPage() {
99101
</CardContent>
100102
</Card>
101103
</div>
102-
</div>
103-
</main>
104+
</main>
105+
</AppLayout>
104106
);
105107
}

definitions/vite-cf-DO-runner/src/pages/DemoPage.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
55
import { Link } from 'react-router-dom';
66
import type { DemoItem, ApiResponse } from '@shared/types';
77
import { ThemeToggle } from '@/components/ThemeToggle';
8+
import { AppLayout } from '@/components/layout/AppLayout';
89

910
export function DemoPage() {
1011
const [counter, setCounter] = useState<number>(0);
@@ -39,10 +40,11 @@ export function DemoPage() {
3940
}
4041

4142
return (
42-
<main className="min-h-screen bg-background p-6">
43-
<ThemeToggle />
44-
45-
<div className="max-w-4xl mx-auto space-y-6">
43+
<AppLayout>
44+
<main className="min-h-screen bg-background p-6">
45+
<ThemeToggle />
46+
47+
<div className="max-w-4xl mx-auto space-y-6">
4648
<header className="space-y-2">
4749
<Link to="/">
4850
<Button variant="ghost" size="sm">
@@ -99,7 +101,7 @@ export function DemoPage() {
99101
</CardContent>
100102
</Card>
101103
</div>
102-
</div>
103-
</main>
104+
</main>
105+
</AppLayout>
104106
);
105107
}

definitions/vite-cf-DO-v2-runner/src/pages/DemoPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ThemeToggle } from '@/components/ThemeToggle'
77
import { Toaster, toast } from '@/components/ui/sonner'
88
import type { User, Chat, ChatMessage } from '@shared/types'
99
import { api } from '@/lib/api-client'
10+
import { AppLayout } from '@/components/layout/AppLayout'
1011

1112
export function DemoPage() {
1213
// Minimal state — small demo for AI to extend
@@ -78,6 +79,7 @@ export function DemoPage() {
7879
}, [selectedUserId, selectedChatId, text])
7980

8081
return (
82+
<AppLayout>
8183
<main className="min-h-screen flex flex-col items-center justify-center bg-background text-foreground p-4 overflow-hidden relative">
8284
<ThemeToggle />
8385

@@ -159,5 +161,6 @@ export function DemoPage() {
159161

160162
<Toaster richColors closeButton />
161163
</main>
164+
</AppLayout>
162165
)
163166
}

definitions/vite-cfagents-runner/src/pages/DemoPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Badge } from '@/components/ui/badge';
1212
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
1313
import { chatService, formatTime, renderToolCall, generateSessionTitle, MODELS } from '../lib/chat';
1414
import type { ChatState, SessionInfo } from '../../worker/types';
15+
import { AppLayout } from '@/components/layout/AppLayout';
1516

1617

1718
export function DemoPage() { // Don't touch this exporting, Its a named export
@@ -200,6 +201,7 @@ export function DemoPage() { // Don't touch this exporting, Its a named export
200201
};
201202

202203
return (
204+
<AppLayout>
203205
<main className="min-h-screen flex flex-col items-center justify-center bg-background text-foreground p-4 overflow-hidden">
204206
<Button
205207
onClick={() => setIsDark(!isDark)}
@@ -419,5 +421,6 @@ export function DemoPage() { // Don't touch this exporting, Its a named export
419421
</form>
420422
</Card>
421423
</main>
422-
);
424+
</AppLayout>
425+
);
423426
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from "react";
2+
import { Home, Layers, Compass, Star, Settings, LifeBuoy } from "lucide-react";
3+
import {
4+
Sidebar,
5+
SidebarContent,
6+
SidebarFooter,
7+
SidebarGroup,
8+
SidebarHeader,
9+
SidebarSeparator,
10+
SidebarInput,
11+
SidebarGroupLabel,
12+
SidebarMenu,
13+
SidebarMenuItem,
14+
SidebarMenuButton,
15+
SidebarMenuAction,
16+
SidebarMenuBadge,
17+
} from "@/components/ui/sidebar";
18+
19+
export function AppSidebar(): JSX.Element {
20+
return (
21+
<Sidebar>
22+
<SidebarHeader>
23+
<div className="flex items-center gap-2 px-2 py-1">
24+
<div className="h-6 w-6 rounded-md bg-gradient-to-br from-indigo-500 to-purple-500" />
25+
<span className="text-sm font-medium">Template</span>
26+
</div>
27+
<SidebarInput placeholder="Search" />
28+
</SidebarHeader>
29+
<SidebarContent>
30+
<SidebarGroup>
31+
<SidebarMenu>
32+
<SidebarMenuItem>
33+
<SidebarMenuButton asChild isActive>
34+
<a href="#"><Home /> <span>Home</span></a>
35+
</SidebarMenuButton>
36+
</SidebarMenuItem>
37+
<SidebarMenuItem>
38+
<SidebarMenuButton asChild>
39+
<a href="#"><Layers /> <span>Projects</span></a>
40+
</SidebarMenuButton>
41+
<SidebarMenuAction>
42+
<Star className="size-4" />
43+
</SidebarMenuAction>
44+
</SidebarMenuItem>
45+
<SidebarMenuItem>
46+
<SidebarMenuButton asChild>
47+
<a href="#"><Compass /> <span>Explore</span></a>
48+
</SidebarMenuButton>
49+
</SidebarMenuItem>
50+
</SidebarMenu>
51+
</SidebarGroup>
52+
53+
<SidebarSeparator />
54+
55+
<SidebarGroup>
56+
<SidebarGroupLabel>Quick Links</SidebarGroupLabel>
57+
<SidebarMenu>
58+
<SidebarMenuItem>
59+
<SidebarMenuButton asChild>
60+
<a href="#"><Star /> <span>Starred</span></a>
61+
</SidebarMenuButton>
62+
<SidebarMenuBadge>5</SidebarMenuBadge>
63+
</SidebarMenuItem>
64+
<SidebarMenuItem>
65+
<SidebarMenuButton asChild>
66+
<a href="#"><LifeBuoy /> <span>Support</span></a>
67+
</SidebarMenuButton>
68+
</SidebarMenuItem>
69+
<SidebarMenuItem>
70+
<SidebarMenuButton asChild>
71+
<a href="#"><Settings /> <span>Settings</span></a>
72+
</SidebarMenuButton>
73+
</SidebarMenuItem>
74+
</SidebarMenu>
75+
</SidebarGroup>
76+
</SidebarContent>
77+
<SidebarFooter>
78+
<div className="px-2 text-xs text-muted-foreground">A simple shadcn sidebar</div>
79+
</SidebarFooter>
80+
</Sidebar>
81+
);
82+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from "react";
2+
import { SidebarProvider, SidebarInset, SidebarTrigger } from "@/components/ui/sidebar";
3+
import { AppSidebar } from "@/components/app-sidebar";
4+
5+
type AppLayoutProps = {
6+
children: React.ReactNode;
7+
container?: boolean;
8+
className?: string;
9+
contentClassName?: string;
10+
};
11+
12+
export function AppLayout({ children, container = false, className, contentClassName }: AppLayoutProps): JSX.Element {
13+
return (
14+
<SidebarProvider defaultOpen={false}>
15+
<AppSidebar />
16+
<SidebarInset className={className}>
17+
<div className="absolute left-2 top-2 z-20">
18+
<SidebarTrigger />
19+
</div>
20+
{container ? (
21+
<div className={"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 md:py-10 lg:py-12" + (contentClassName ? ` ${contentClassName}` : "")}>{children}</div>
22+
) : (
23+
children
24+
)}
25+
</SidebarInset>
26+
</SidebarProvider>
27+
);
28+
}

reference/vite-reference/src/pages/HomePage.tsx

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ThemeToggle } from '@/components/ThemeToggle'
77
import { Toaster, toast } from '@/components/ui/sonner'
88
import { create } from 'zustand'
99
import { useShallow } from 'zustand/react/shallow'
10+
import { AppLayout } from '@/components/layout/AppLayout'
1011

1112
// Timer store: independent slice with a clear, minimal API, for demonstration
1213
type TimerState = {
@@ -94,61 +95,54 @@ export function HomePage() {
9495
const formatted = formatDuration(elapsedMs)
9596

9697
return (
97-
<main className="min-h-screen flex flex-col items-center justify-center bg-background text-foreground p-4 overflow-hidden relative">
98-
<ThemeToggle />
99-
100-
<div className="absolute inset-0 bg-gradient-rainbow opacity-10 dark:opacity-20" />
101-
102-
<div className="text-center space-y-8 relative z-10 animate-fade-in">
103-
<div className="flex justify-center">
104-
<div className="w-16 h-16 rounded-2xl bg-gradient-primary flex items-center justify-center shadow-primary floating">
105-
<Sparkles className="w-8 h-8 text-white rotating" />
98+
<AppLayout>
99+
<div className="min-h-screen flex flex-col items-center justify-center bg-background text-foreground p-4 overflow-hidden relative">
100+
<ThemeToggle />
101+
<div className="absolute inset-0 bg-gradient-rainbow opacity-10 dark:opacity-20 pointer-events-none" />
102+
<div className="text-center space-y-8 relative z-10 animate-fade-in">
103+
<div className="flex justify-center">
104+
<div className="w-16 h-16 rounded-2xl bg-gradient-primary flex items-center justify-center shadow-primary floating">
105+
<Sparkles className="w-8 h-8 text-white rotating" />
106+
</div>
106107
</div>
107-
</div>
108-
109-
<h1 className="text-5xl md:text-7xl font-display font-bold text-balance leading-tight">
110-
Creating your <span className="text-gradient">app</span>
111-
</h1>
112-
113-
<p className="text-lg md:text-xl text-muted-foreground max-w-xl mx-auto text-pretty">
114-
Your application would be ready soon.
115-
</p>
116-
117-
<div className="flex justify-center gap-4">
118-
<Button
119-
size="lg"
120-
onClick={onPleaseWait}
121-
className="btn-gradient px-8 py-4 text-lg font-semibold hover:-translate-y-0.5 transition-all duration-200"
122-
aria-live="polite"
123-
>
124-
Please Wait
125-
</Button>
126-
</div>
127-
128-
<div className="flex items-center justify-center gap-6 text-sm text-muted-foreground">
129-
<div>
130-
Time elapsed: <span className="font-medium tabular-nums text-foreground">{formatted}</span>
108+
<h1 className="text-5xl md:text-7xl font-display font-bold text-balance leading-tight">
109+
Creating your <span className="text-gradient">app</span>
110+
</h1>
111+
<p className="text-lg md:text-xl text-muted-foreground max-w-xl mx-auto text-pretty">
112+
Your application would be ready soon.
113+
</p>
114+
<div className="flex justify-center gap-4">
115+
<Button
116+
size="lg"
117+
onClick={onPleaseWait}
118+
className="btn-gradient px-8 py-4 text-lg font-semibold hover:-translate-y-0.5 transition-all duration-200"
119+
aria-live="polite"
120+
>
121+
Please Wait
122+
</Button>
131123
</div>
132-
<div>
133-
Coins: <span className="font-medium tabular-nums text-foreground">{count}</span>
124+
<div className="flex items-center justify-center gap-6 text-sm text-muted-foreground">
125+
<div>
126+
Time elapsed: <span className="font-medium tabular-nums text-foreground">{formatted}</span>
127+
</div>
128+
<div>
129+
Coins: <span className="font-medium tabular-nums text-foreground">{count}</span>
130+
</div>
131+
</div>
132+
<div className="flex justify-center gap-2">
133+
<Button variant="outline" size="sm" onClick={() => { resetTimer(); resetCount(); toast('Reset complete') }}>
134+
Reset
135+
</Button>
136+
<Button variant="outline" size="sm" onClick={() => { inc(); toast('Coin added') }}>
137+
Add Coin
138+
</Button>
134139
</div>
135140
</div>
136-
137-
<div className="flex justify-center gap-2">
138-
<Button variant="outline" size="sm" onClick={() => { resetTimer(); resetCount(); toast('Reset complete') }}>
139-
Reset
140-
</Button>
141-
<Button variant="outline" size="sm" onClick={() => { inc(); toast('Coin added') }}>
142-
Add Coin
143-
</Button>
144-
</div>
141+
<footer className="absolute bottom-8 text-center text-muted-foreground/80">
142+
<p>Powered by Cloudflare</p>
143+
</footer>
144+
<Toaster richColors closeButton />
145145
</div>
146-
147-
<footer className="absolute bottom-8 text-center text-muted-foreground/80">
148-
<p>Powered by Cloudflare</p>
149-
</footer>
150-
151-
<Toaster richColors closeButton />
152-
</main>
146+
</AppLayout>
153147
)
154148
}

0 commit comments

Comments
 (0)