import { For, Show, createSignal, type JSX } from "solid-js"; import { ModuleCard, FakeCursor, IslandPill, AgentDotGrid, STATUS, ACCENT, CALM, CRITICAL, CARD_STROKE } from "./IslandMock"; import { useDemoLoop } from "./useDemoLoop"; import { Glyph, WingCapsule, type GlyphName } from "./ModuleMocks"; /** * Live demos for the breakdowns added with the 0.6–0.10 feature set: * terminal replies, the volume mixer, Capture (module + Wings), and * floating actions. Same ink chrome and status palette as the originals. */ /* ── Reply lands in the agent's own terminal ──────────────────────── */ const REPLY = "yes — and run them"; export function TerminalReplyDemo() { const [typed, setTyped] = createSignal(0); const [phase, setPhase] = createSignal< "asking" | "typing" | "sent" | "working" | "jump" >("asking"); useDemoLoop(10000, [ [0, () => (setTyped(0), setPhase("asking"))], [900, () => setPhase("typing")], ...REPLY.split("").map( (_, i) => [1000 + i * 70, () => setTyped(i + 1)] as [number, () => void] ), [2900, () => setPhase("sent")], [3300, () => setPhase("working")], [6600, () => setPhase("jump")] ]); const delivered = () => phase() === "working" || phase() === "jump"; const cursorPhase = () => phase() === "sent" || phase() === "jump" ? ("press" as const) : phase() === "typing" || phase() === "asking" ? ("idle" as const) : ("live" as const); const cursorAt = () => phase() === "jump" ? { x: 88, y: 14 } : { x: 88, y: 80 }; return (
the-nook main Jump ↗

{delivered() ? "Running the test suite…" : "Done. Want me to update the tests too?"}

{delivered() ? "" : REPLY.slice(0, typed())} ▍ Reply… Send
{/* the terminal the session actually runs in */}
tmux · the-nook:2 focused

⏺ Updated 3 files

>{" "} {REPLY}

⏺ Bash(swift test)

); } /* ── Volume mixer: every app its own level and output ─────────────── */ interface MixerApp { name: string; color: string; glyph: string; } const MIXER_APPS: MixerApp[] = [ { name: "Music", color: "#fa5c7c", glyph: "♫" }, { name: "Browser", color: "#6EA7FF", glyph: "◎" }, { name: "Meeting", color: "#6FB982", glyph: "●" }, { name: "podcast-cli", color: "#E7A762", glyph: ">_" } ]; export function MixerDemo() { const [step, setStep] = createSignal(0); useDemoLoop(9600, [ [0, () => setStep(0)], [1800, () => setStep(1)], [3800, () => setStep(2)], [5800, () => setStep(3)] ]); const level = (i: number) => { if (i === 0) return step() >= 3 ? 0.38 : 0.72; if (i === 1) return 0.55; if (i === 2) return 0.86; return 0.46; }; const muted = (i: number) => i === 1 && step() >= 1; const route = (i: number) => i === 0 && step() >= 2 ? "Headphones" : i === 2 ? "Display" : "Speakers"; return (
Volume mixer out · Speakers
{(app, i) => (
{app.glyph}
{app.name} {route(i())}
{/* live signal riding inside the level */}
{muted(i()) ? "✕" : "♪"}
)}

{ [ "every app on its own fader", "browser muted — the rest keep playing", "music routed to headphones, meeting stays on the display", "music down, nothing else moved" ][step()] }

); } /* ── Capture: the module, and the Wings while a recording runs ────── */ /** CapturePalette.recording and the NookPalette paper/ink pair. */ const RECORDING_RED = "rgb(242,69,69)"; const PAPER = "#f1ead9"; const INK = "#0d0d0f"; function CaptureChip(props: { glyph: GlyphName; label: string; menu?: boolean; pressed?: boolean; }) { return ( {props.label} ); } /** CaptureAudioToggles: paper capsule when on, faint when off. */ function AudioToggles(props: { system: boolean; mic: boolean }) { const toggle = (on: boolean, glyph: GlyphName, label: string) => ( {label} ); return (
{toggle(props.system, props.system ? "speaker" : "speakerOff", "System audio")} {toggle(props.mic, props.mic ? "mic" : "micOff", "Microphone")}
); } function RowLabel(props: { glyph: GlyphName; label: string }) { return (

{props.label}

); } export function CaptureDemo() { const [phase, setPhase] = createSignal<"idle" | "press" | "rec" | "paused" | "saved">("idle"); const [secs, setSecs] = createSignal(0); const [mic, setMic] = createSignal(true); const [wingPress, setWingPress] = createSignal<"" | "mic" | "pause" | "stop">(""); useDemoLoop(12400, [ [0, () => (setPhase("idle"), setSecs(0), setMic(true), setWingPress(""))], [1500, () => setPhase("press")], [1800, () => setPhase("rec")], ...[1, 2, 3, 4, 5].map((s) => [1800 + s * 1000, () => setSecs(s)] as [number, () => void]), [4300, () => setWingPress("mic")], [4550, () => (setMic(false), setWingPress(""))], [7100, () => setWingPress("pause")], [7350, () => (setPhase("paused"), setWingPress(""))], [9000, () => setWingPress("stop")], [9250, () => (setPhase("saved"), setWingPress(""))] ]); const recording = () => phase() === "rec" || phase() === "paused"; const paused = () => phase() === "paused"; /* Island row is drawn at half size; Wing controls are as tall as it. */ const wingWidth = 2 * 60 + 12; const cursor = () => { switch (wingPress()) { case "mic": return { phase: "press" as const, at: { x: 21.8, y: 7 } }; case "pause": return { phase: "press" as const, at: { x: 78.2, y: 7 } }; case "stop": return { phase: "press" as const, at: { x: 86.5, y: 7 } }; } if (phase() === "idle" || phase() === "press") return { phase: phase() === "press" ? ("press" as const) : ("idle" as const), at: { x: 50, y: 58 } }; if (phase() === "saved") return { phase: "live" as const, at: { x: 86.5, y: 7 } }; return { phase: "idle" as const, at: { x: 21.8, y: 30 } }; }; return (
{/* the Compact island, flanked by the Wings while recording */}
} />
{/* the Capture module */}
Screen Recording 2026-10-13 at 9.41.12.mov Show in Finder
} >
0:0{secs()} {paused() ? "Paused" : "Recording"}
{/* cursor plotted on a fixed 360 px frame centered over the demo */}
); } /* ── Floating actions bloom around the open island ────────────────── */ /* Tiny monochrome glyphs for the action kinds the app offers. */ const GLYPH: Record JSX.Element> = { leaf: () => ( ), bolt: () => , timer: () => ( ), speaker: () => ( ), shell: () => ( ), stack: () => ( ), link: () => ( ) }; interface FloatAction { glyph: keyof typeof GLYPH; label: string; x: number; y: number; } /* Positions mirror the app's slots: Left ·1/·2, Right ·1/·2, Bottom ·1–3. */ const ACTIONS: FloatAction[] = [ { glyph: "leaf", label: "Low Power Mode on", x: -128, y: -18 }, { glyph: "bolt", label: "Top-up to 100%", x: -128, y: 26 }, { glyph: "speaker", label: "Output → Headphones", x: 128, y: -18 }, { glyph: "stack", label: "Shortcut: Focus Time", x: 128, y: 26 }, { glyph: "timer", label: "Timer · 25 min", x: -50, y: 78 }, { glyph: "shell", label: "$ make deploy", x: 0, y: 78 }, { glyph: "link", label: "Opened dashboard", x: 50, y: 78 } ]; export function FloatingActionsDemo() { const [open, setOpen] = createSignal(false); const [pressed, setPressed] = createSignal(-1); const [lit, setLit] = createSignal([]); useDemoLoop(9600, [ [0, () => (setOpen(false), setPressed(-1), setLit([]))], [400, () => setOpen(true)], [2200, () => setPressed(0)], [2500, () => setLit([0])], [4000, () => setPressed(4)], [4300, () => setLit([0, 4])], [5800, () => setPressed(2)], [6100, () => setLit([0, 4, 2])], [8800, () => (setOpen(false), setPressed(-1))] ]); const lastLit = () => lit()[lit().length - 1]; return (
{/* the expanded island */}
{(a, i) => ( {GLYPH[a.glyph]()} )}
{/* what the last press did */}
{lastLit() !== undefined ? ACTIONS[lastLit()].label : " "}
); }