webui: implement modular demo system with TypeScript and shared fixtures

Replace hand-written HTML demo pages with TypeScript demo modules and
automated infrastructure to reduce maintenance overhead and improve
developer experience with type safety and shared code.

Problems Solved:

Demo Maintenance Overhead:
- Hand-written HTML demo pages contained extensive boilerplate duplication
- No type checking for demo setup code or component data
- Manual maintenance of demo/index.html with available demos
- Difficult to share common fake data between demo pages
- No hot module replacement for demo development

Code Quality and Consistency:
- Demo setup code written in plain JavaScript without type safety
- No validation that demo data matches component interfaces
- Inconsistent styling and structure across demo pages
- Duplicated fake data declarations in each demo file

Solution Architecture:

TypeScript Demo Module System:
- Created DemoModule interface for standardized demo structure
- Demo modules export title, description, imports, and setup functions
- Full TypeScript compilation with type checking for demo code
- Dynamic import system for on-demand demo loading with Vite integration

Shared Demo Infrastructure:
- demo-framework/ with types.ts and demo-runner.ts for core functionality
- DemoRunner class handles dynamic loading, cleanup, and error handling
- Single demo-runner.html page loads any demo module dynamically
- Supports URL hash routing for direct demo links

Centralized Fake Data:
- demo-fixtures/ directory with shared TypeScript data files
- sampleToolCalls, sampleTimelineMessages, and sampleContainerState
- Type-safe imports ensure demo data matches component interfaces
- demoUtils with helper functions for consistent demo UI creation

Auto-generated Index Page:
- generate-index.ts scans for *.demo.ts files and extracts metadata
- Creates index-generated.html with links to all available demos
- Automatically includes demo titles and descriptions
- Eliminates manual maintenance of demo listing

Implementation Details:

Demo Framework:
- DemoRunner.loadDemo() uses dynamic imports with Vite ignore comments
- Automatic component import based on demo module configuration
- Support for demo-specific CSS and cleanup functions
- Error handling with detailed error display for debugging

Demo Module Structure:
- sketch-chat-input.demo.ts: Interactive chat with message history
- sketch-container-status.demo.ts: Status variations with real-time updates
- sketch-tool-calls.demo.ts: Multiple tool call examples with progressive loading
- All use shared fixtures and utilities for consistent experience

Vite Integration:
- Hot Module Replacement works for demo modules and shared fixtures
- TypeScript compilation on-the-fly for immediate feedback
- Dynamic imports work seamlessly with Vite's module system
- @vite-ignore comments prevent import analysis warnings

Testing and Validation:
- Tested demo runner loads and displays available components
- Verified component discovery and dynamic import functionality
- Confirmed shared fixture imports work correctly
- Validated auto-generated index creation and content

Files Modified:
- demo-framework/types.ts: TypeScript interfaces for demo system
- demo-framework/demo-runner.ts: Core demo loading and execution logic
- demo-fixtures/: Shared fake data (tool-calls.ts, timeline-messages.ts, container-status.ts, index.ts)
- demo-runner.html: Interactive demo browser with sidebar navigation
- generate-index.ts: Auto-generation script for demo index
- sketch-chat-input.demo.ts: Converted chat input demo to TypeScript
- sketch-container-status.demo.ts: Container status demo with variations
- sketch-tool-calls.demo.ts: Tool calls demo with interactive examples
- readme.md: Comprehensive documentation for new demo system

Benefits:
- Developers get full TypeScript type checking for demo code
- Shared fake data ensures consistency and reduces duplication
- Hot module replacement provides instant feedback during development
- Auto-generated index eliminates manual maintenance
- Modular architecture makes it easy to add new demos
- Vite integration provides fast development iteration

The new system reduces demo maintenance overhead while providing
better developer experience through TypeScript, shared code, and
automated infrastructure.

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s3d91894eb7c4a79fk
diff --git a/webui/src/web-components/demo/demo-fixtures/index.ts b/webui/src/web-components/demo/demo-fixtures/index.ts
new file mode 100644
index 0000000..9a47f8e
--- /dev/null
+++ b/webui/src/web-components/demo/demo-fixtures/index.ts
@@ -0,0 +1,104 @@
+/**
+ * Centralized exports for all demo fixtures
+ */
+
+// Tool calls
+export {
+  sampleToolCalls,
+  longBashCommand,
+  multipleToolCallGroups,
+} from "./tool-calls";
+
+// Timeline messages
+export {
+  sampleTimelineMessages,
+  longTimelineMessage,
+  mixedTimelineMessages,
+} from "./timeline-messages";
+
+// Container status
+export {
+  sampleUsage,
+  sampleContainerState,
+  lightUsageState,
+  heavyUsageState,
+} from "./container-status";
+
+// Common demo utilities
+export const demoStyles = {
+  container: `
+    max-width: 1200px;
+    margin: 20px auto;
+    padding: 20px;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+  `,
+
+  demoSection: `
+    margin: 20px 0;
+    padding: 15px;
+    border: 1px solid #e1e5e9;
+    border-radius: 8px;
+    background: #f8f9fa;
+  `,
+
+  demoHeader: `
+    font-size: 18px;
+    font-weight: 600;
+    margin-bottom: 10px;
+    color: #24292f;
+  `,
+};
+
+/**
+ * Common demo setup utilities
+ */
+export const demoUtils = {
+  /**
+   * Create a labeled demo section
+   */
+  createDemoSection(title: string, description?: string): HTMLElement {
+    const section = document.createElement("div");
+    section.style.cssText = demoStyles.demoSection;
+
+    const header = document.createElement("h3");
+    header.style.cssText = demoStyles.demoHeader;
+    header.textContent = title;
+    section.appendChild(header);
+
+    if (description) {
+      const desc = document.createElement("p");
+      desc.textContent = description;
+      desc.style.cssText = "color: #656d76; margin-bottom: 15px;";
+      section.appendChild(desc);
+    }
+
+    return section;
+  },
+
+  /**
+   * Wait for a specified number of milliseconds
+   */
+  delay(ms: number): Promise<void> {
+    return new Promise((resolve) => setTimeout(resolve, ms));
+  },
+
+  /**
+   * Create a simple button for demo interactions
+   */
+  createButton(text: string, onClick: () => void): HTMLButtonElement {
+    const button = document.createElement("button");
+    button.textContent = text;
+    button.style.cssText = `
+      padding: 8px 16px;
+      margin: 5px;
+      background: #0969da;
+      color: white;
+      border: none;
+      border-radius: 6px;
+      cursor: pointer;
+      font-size: 14px;
+    `;
+    button.addEventListener("click", onClick);
+    return button;
+  },
+};