Skip to content

Commit ec8a839

Browse files
committed
mobile friendly playground
1 parent e46a852 commit ec8a839

File tree

6 files changed

+109
-23
lines changed

6 files changed

+109
-23
lines changed

examples/playground/src/demos/ai/ChatDemo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ function ChatUI() {
156156
description="Chat with an AI agent powered by Workers AI. Messages persist across reconnections."
157157
statusIndicator={<ConnectionStatus status={connectionStatus} />}
158158
>
159-
<div className="flex flex-col h-[calc(100vh-16rem)] max-w-3xl">
159+
<div className="flex flex-col h-full max-w-3xl">
160160
{/* Messages area */}
161161
<div className="flex-1 overflow-y-auto mb-4 space-y-4">
162162
{messages.length === 0 && (

examples/playground/src/demos/ai/ToolsDemo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ function ToolsUI() {
274274
description="Server-side, client-side, and approval-required tools in action."
275275
statusIndicator={<ConnectionStatus status={connectionStatus} />}
276276
>
277-
<div className="flex flex-col h-[calc(100vh-16rem)] max-w-3xl">
277+
<div className="flex flex-col h-full max-w-3xl">
278278
{/* Tool legend */}
279279
<div className="flex flex-wrap gap-3 mb-4 px-1">
280280
<div className="flex items-center gap-1.5">

examples/playground/src/layout/DemoWrapper.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@ export function DemoWrapper({
1616
}: DemoWrapperProps) {
1717
return (
1818
<div className="h-full flex flex-col">
19-
<header className="flex items-start justify-between gap-4 p-6 border-b border-kumo-line">
20-
<div>
19+
<header className="flex items-start justify-between gap-4 p-4 md:p-6 border-b border-kumo-line">
20+
<div className="min-w-0">
2121
<Text variant="heading2">{title}</Text>
2222
<div className="mt-1">
2323
<Text variant="secondary" size="sm">
2424
{description}
2525
</Text>
2626
</div>
2727
</div>
28-
{statusIndicator}
28+
{statusIndicator && <div className="shrink-0">{statusIndicator}</div>}
2929
</header>
30-
<div className="flex-1 overflow-y-auto p-6">{children}</div>
30+
<div className="flex-1 min-h-0 overflow-y-auto p-4 md:p-6">
31+
{children}
32+
</div>
3133
</div>
3234
);
3335
}

examples/playground/src/layout/Layout.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
1+
import { useState, useCallback } from "react";
12
import { Outlet } from "react-router-dom";
3+
import { Button } from "@cloudflare/kumo";
4+
import { ListIcon } from "@phosphor-icons/react";
5+
import { PoweredByAgents } from "@cloudflare/agents-ui";
26
import { Sidebar } from "./Sidebar";
37

48
export function Layout() {
9+
const [sidebarOpen, setSidebarOpen] = useState(false);
10+
const closeSidebar = useCallback(() => setSidebarOpen(false), []);
11+
512
return (
6-
<div className="h-full flex bg-kumo-base">
7-
<Sidebar />
8-
<main className="flex-1 overflow-y-auto bg-kumo-base">
13+
<div className="h-full flex flex-col md:flex-row bg-kumo-base">
14+
{/* Mobile header */}
15+
<header className="md:hidden flex items-center justify-between px-4 py-3 border-b border-kumo-line bg-kumo-base shrink-0">
16+
<Button
17+
variant="ghost"
18+
shape="square"
19+
size="sm"
20+
icon={<ListIcon size={20} />}
21+
onClick={() => setSidebarOpen(true)}
22+
aria-label="Open navigation"
23+
/>
24+
<PoweredByAgents />
25+
<div className="w-8" />
26+
</header>
27+
28+
<Sidebar open={sidebarOpen} onClose={closeSidebar} />
29+
30+
<main className="flex-1 overflow-y-auto bg-kumo-base min-h-0">
931
<Outlet />
1032
</main>
1133
</div>

examples/playground/src/layout/Sidebar.tsx

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ import {
2525
GitMergeIcon,
2626
ShieldIcon,
2727
PaletteIcon,
28-
ArrowsClockwiseIcon
28+
ArrowsClockwiseIcon,
29+
XIcon
2930
} from "@phosphor-icons/react";
30-
import { useState } from "react";
31-
import { NavLink } from "react-router-dom";
31+
import { useState, useEffect } from "react";
32+
import { NavLink, useLocation } from "react-router-dom";
3233
import { Button, Link } from "@cloudflare/kumo";
3334
import { PoweredByAgents } from "@cloudflare/agents-ui";
3435
import { useTheme } from "../hooks/useTheme";
@@ -194,7 +195,13 @@ const navigation: NavCategory[] = [
194195
}
195196
];
196197

197-
function CategorySection({ category }: { category: NavCategory }) {
198+
function CategorySection({
199+
category,
200+
onNavigate
201+
}: {
202+
category: NavCategory;
203+
onNavigate?: () => void;
204+
}) {
198205
const [isOpen, setIsOpen] = useState(true);
199206

200207
return (
@@ -222,6 +229,7 @@ function CategorySection({ category }: { category: NavCategory }) {
222229
<NavLink
223230
key={item.path}
224231
to={item.path}
232+
onClick={onNavigate}
225233
className={({ isActive }) =>
226234
`flex items-center gap-2 px-3 py-2 text-sm rounded-md transition-colors ${
227235
isActive
@@ -293,16 +301,31 @@ function ColorThemeToggle() {
293301
);
294302
}
295303

296-
export function Sidebar() {
304+
function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
297305
return (
298-
<aside className="w-56 h-full border-r border-kumo-line bg-kumo-base flex flex-col">
299-
<div className="p-4 border-b border-kumo-line">
306+
<>
307+
<div className="p-4 border-b border-kumo-line flex items-center justify-between">
300308
<PoweredByAgents />
309+
{onNavigate && (
310+
<Button
311+
variant="ghost"
312+
shape="square"
313+
size="sm"
314+
icon={<XIcon size={18} />}
315+
onClick={onNavigate}
316+
aria-label="Close navigation"
317+
className="md:hidden"
318+
/>
319+
)}
301320
</div>
302321

303322
<nav className="flex-1 overflow-y-auto p-2">
304323
{navigation.map((category) => (
305-
<CategorySection key={category.label} category={category} />
324+
<CategorySection
325+
key={category.label}
326+
category={category}
327+
onNavigate={onNavigate}
328+
/>
306329
))}
307330
</nav>
308331

@@ -322,6 +345,45 @@ export function Sidebar() {
322345
</Link>
323346
</div>
324347
</div>
325-
</aside>
348+
</>
349+
);
350+
}
351+
352+
interface SidebarProps {
353+
open: boolean;
354+
onClose: () => void;
355+
}
356+
357+
export function Sidebar({ open, onClose }: SidebarProps) {
358+
const location = useLocation();
359+
360+
useEffect(() => {
361+
onClose();
362+
}, [location.pathname, onClose]);
363+
364+
return (
365+
<>
366+
{/* Desktop: static sidebar */}
367+
<aside className="hidden md:flex w-56 h-full border-r border-kumo-line bg-kumo-base flex-col shrink-0">
368+
<SidebarContent />
369+
</aside>
370+
371+
{/* Mobile: overlay drawer */}
372+
{open && (
373+
<div className="fixed inset-0 z-40 md:hidden">
374+
{/* Backdrop */}
375+
<button
376+
type="button"
377+
className="absolute inset-0 bg-black/40"
378+
onClick={onClose}
379+
aria-label="Close navigation"
380+
/>
381+
{/* Panel */}
382+
<aside className="relative w-72 max-w-[85vw] h-full bg-kumo-base flex flex-col shadow-xl">
383+
<SidebarContent onNavigate={onClose} />
384+
</aside>
385+
</div>
386+
)}
387+
</>
326388
);
327389
}

examples/playground/src/pages/Home.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ const features = [
138138
export function Home() {
139139
return (
140140
<div className="h-full flex flex-col">
141-
<header className="p-6 border-b border-kumo-line">
141+
<header className="p-4 md:p-6 border-b border-kumo-line">
142142
<Text variant="heading1">Agents SDK Playground</Text>
143143
<div className="mt-1">
144144
<Text variant="secondary" size="sm">
@@ -147,13 +147,13 @@ export function Home() {
147147
</div>
148148
</header>
149149

150-
<div className="flex-1 overflow-y-auto p-6">
150+
<div className="flex-1 overflow-y-auto p-4 md:p-6">
151151
<div className="max-w-4xl">
152152
<div className="mb-8">
153153
<Text variant="secondary">
154-
Select a feature from the sidebar to explore its capabilities.
155-
Each demo includes interactive controls, real-time event logging,
156-
and code examples you can copy.
154+
Select a feature to explore its capabilities. Each demo includes
155+
interactive controls, real-time event logging, and code examples
156+
you can copy.
157157
</Text>
158158
</div>
159159

0 commit comments

Comments
 (0)