--- name: "component demo" description: "Create demonstration pages for components and hooks." license: Proprietary --- # Component Demo Skill This skill guides the creation and maintenance of components and their demo pages in the Protobox component showcase. ## When to Use This Skill Use this skill when: - Creating new custom components in `src/components/` - Creating new custom hooks in `src/hooks/` - Updating existing components or hooks - Planning feature additions that involve reusable components ## Component Development Workflow ### Phase 1: Planning - Ask About Demo Pages **IMPORTANT:** When planning to create a new component or hook, ALWAYS ask the user: > "Would you like me to create a demo page for this [component/hook] in the component showcase?" Options to present: 1. **Yes, create demo page** - Create both the component and a showcase demo 2. **Yes, standalone demo** - Create component and a standalone demo page at `/[name]-demo` 3. **Yes, playground** - Create an interactive playground with props controls (Storybook-like) 4. **No demo needed** - Just create the component/hook ### Phase 2: Component Creation Create the component in the appropriate location: - Custom components: `src/components/[ComponentName].tsx` - Custom hooks: `src/hooks/[hookName].tsx` - UI components: Use `npx shadcn-ui@latest add [component]` for shadcn components Follow component best practices from `src/components/README.md`: - Simple default usage with sensible defaults - Accept `style`, `className`, and native element props - Use composition for icons (via props, not hardcoded) - Standard heights: 16px, 20px, 40px - Support dark mode with Tailwind `dark:` variants ### Phase 3: Demo Page Creation (if requested) #### A. For Component Showcase (`/components/[name]`) 1. **Create Content Component** in `src/components/DemoShowcase/[Name]Content.tsx`: - Extract core demo functionality without page wrappers - Remove: `min-h-screen`, full-page padding, headers, back links - Keep: interactive elements, controls, examples - Use Card components to organize examples - Include usage code examples 2. **Register in Demo Registry** (`src/components/DemoShowcase/demoRegistry.tsx`): ```tsx // Add lazy import const [Name]Content = lazy(() => import('./[Name]Content')) // Add to DEMO_REGISTRY array { id: '[name]', label: '[Display Name]', section: 'Hooks' | 'Components', component: [Name]Content, description: 'Brief description', path: '/components/[name]', } ``` 3. **Add Route** in `src/App.tsx`: ```tsx // Add lazy import at top const [Name]Content = lazy(() => import('./components/DemoShowcase/[Name]Content')) // Add route inside nested routes Loading...}> <[Name]Content /> } /> ``` #### B. For Standalone Demo Page (`/[name]-demo`) 1. **Create Page Component** in `src/pages/[Name]Demo.tsx`: - Include full-page wrapper with proper styling - Add header with title and description - Organize examples using Card components - Include code examples showing usage - Add back link to home 2. **Add Route** in `src/App.tsx`: ```tsx import [Name]Demo from './pages/[Name]Demo' ``` #### C. For Component Playground (`/components/[name]-playground`) Playgrounds provide an interactive, Storybook-like environment with a canvas and props controls. 1. **Analyze Component Props:** - Read the target component's source file - Parse the TypeScript Props interface - Categorize props as controllable or complex 2. **Guide Prop Selection - Present to User:** > "I analyzed [ComponentName] and found these props: > > **Recommended for playground (controllable):** > - `variant`: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' > - `size`: 'default' | 'sm' | 'lg' | 'icon' > - `disabled`: boolean > > **Complex props (not controllable):** > - `onClick`: function > - `asChild`: boolean (affects render behavior) > - `ref`: React ref > > Which props would you like to expose in the playground?" 3. **Create Playground Content** in `src/components/DemoShowcase/[Name]PlaygroundContent.tsx`: ```tsx import PlaygroundCanvas, { PropSchema } from './PlaygroundCanvas' import { Button } from '@/components/ui/button' const propSchema: PropSchema = { variant: { type: 'select', options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'], defaultValue: 'default', }, size: { type: 'select', options: ['default', 'sm', 'lg', 'icon'], defaultValue: 'default', }, disabled: { type: 'boolean', defaultValue: false, }, children: { type: 'string', defaultValue: 'Button', }, } export default function ButtonPlaygroundContent() { return ( {(props) => } ) } ``` 4. **Register in Demo Registry** (`src/components/DemoShowcase/demoRegistry.tsx`): ```tsx // Add lazy import const [Name]PlaygroundContent = lazy(() => import('./[Name]PlaygroundContent')) // Add to DEMO_REGISTRY array { id: '[name]-playground', label: '[Name] Playground', section: 'Components', component: [Name]PlaygroundContent, description: 'Interactive playground for [Name]', path: '/components/[name]-playground', type: 'playground', } ``` 5. **Add Route** in `src/App.tsx`: ```tsx const [Name]PlaygroundContent = lazy(() => import('./components/DemoShowcase/[Name]PlaygroundContent')) Loading...}> <[Name]PlaygroundContent /> } /> ``` ### Prop Type Mapping Reference When analyzing TypeScript props, map types to Leva controls: | TypeScript Type | PropSchema Type | Notes | |-----------------|-----------------|-------| | `string` | `'string'` | Text input | | `number` | `'number'` | Slider (add min/max/step) | | `boolean` | `'boolean'` | Checkbox toggle | | `'a' \| 'b' \| 'c'` | `'select'` | Dropdown with options array | | `enum Foo { A, B }` | `'select'` | Extract enum values as options | | `React.ReactNode` | `'string'` | For simple text children | | Color strings | `'color'` | Color picker | | `() => void` | Skip | Not controllable | | Complex objects | Skip | Not controllable | | `React.Ref` | Skip | Not controllable | ### PropSchema Format ```tsx import { PropSchema } from '@/components/DemoShowcase/PlaygroundCanvas' const schema: PropSchema = { propName: { type: 'string' | 'number' | 'boolean' | 'select' | 'color', label?: string, // Custom label (defaults to propName) defaultValue?: unknown, // Initial value options?: string[], // For 'select' type min?: number, // For 'number' type max?: number, // For 'number' type step?: number, // For 'number' type } } ``` ### Phase 4: Component Updates - Check for Existing Demos **CRITICAL:** When updating an existing component or hook, ALWAYS check if demo pages exist: 1. **Search for Demo Pages:** - Check `src/components/DemoShowcase/` for `[Name]Content.tsx` or `[Name]PlaygroundContent.tsx` - Check `src/pages/` for `[Name]Demo.tsx` - Check `demoRegistry.tsx` for entries (including `type: 'playground'`) 2. **If Demo Pages Exist:** - Update them to reflect new functionality - Add examples demonstrating new features - Update code examples - Test that demos still work correctly 3. **Prompt User:** > "I found existing demo pages for this [component/hook]. I'll update them to include the new [feature/changes]." ## Demo Content Best Practices ### Structure Organize demo content with clear sections: ```tsx
{/* Example 1: Basic Usage */}
Basic Configuration details
{/* Demo content */}
{/* More examples... */} {/* Code Example */} Usage Example
      {`// Code example here`}
    
``` ### Example Categories Include diverse examples: 1. **Basic** - Simple default usage 2. **Advanced** - Complex configurations 3. **Interactive** - User-controlled examples 4. **Variants** - Different visual styles or behaviors 5. **Edge Cases** - Boundary conditions 6. **Code Examples** - Implementation snippets ### Styling - Use Card components for grouping examples - Add Badge components for labeling examples - Include configuration details in muted text - Support dark mode throughout - Add visual indicators for interactive elements - Show state changes clearly ## Component Showcase Navigation The navigation is automatically generated from `demoRegistry.tsx`: - **Hooks** section: Custom React hooks - **Components** section: UI components, libraries, demos Demos are displayed in the order they appear in `DEMO_REGISTRY`. ## Testing Checklist After creating or updating component demos: - [ ] Navigate to the demo route - [ ] Verify all examples render correctly - [ ] Test interactive elements (buttons, inputs, controls) - [ ] Check dark mode appearance - [ ] Verify code examples are accurate - [ ] Test on different screen sizes - [ ] Check TypeScript compilation - [ ] Verify navigation active state ### Additional Checks for Playgrounds - [ ] Verify Leva props panel appears (top-right corner) - [ ] Test that prop changes update the component in real-time - [ ] Verify navigation collapse toggle works - [ ] Check canvas centering at different sizes - [ ] Test all prop controls (selects, inputs, toggles) ## Examples ### Example 1: Creating a New Hook with Demo ``` User: "Create a useDebounce hook" Claude: 1. Asks: "Would you like me to create a demo page for this hook in the component showcase?" 2. User selects: "Yes, create demo page" 3. Creates: - src/hooks/useDebounce.tsx (the hook) - src/components/DemoShowcase/DebounceContent.tsx (demo) - Updates demoRegistry.tsx - Updates App.tsx with route ``` ### Example 2: Updating Existing Component ``` User: "Add a 'size' prop to the Button component" Claude: 1. Searches for existing demos 2. Finds: N/A (Button is shadcn component, no custom demo) 3. Updates Button usage examples in existing demos if needed ``` ### Example 3: Updating Hook with Demo ``` User: "Add a 'delay' option to useTypewriter" Claude: 1. Updates src/hooks/useTypewriter.tsx 2. Searches and finds: src/components/DemoShowcase/TypewriterContent.tsx 3. Announces: "I found the existing TypewriterContent demo. I'll add an example showing the new delay option." 4. Adds new Card with delay example 5. Updates code example to include delay option ``` ### Example 4: Creating a Component Playground ``` User: "Create a playground for the Badge component" Claude: 1. Asks: "Would you like me to create a demo page for this component?" 2. User selects: "Yes, playground" 3. Claude reads src/components/ui/badge.tsx 4. Analyzes BadgeProps interface and presents: "I found these props: **Controllable:** - variant: 'default' | 'secondary' | 'destructive' | 'outline' - children: ReactNode (as string) **Not controllable:** - className: styling (skip) Which props would you like to expose?" 5. User selects: "variant and children" 6. Creates: - src/components/DemoShowcase/BadgePlaygroundContent.tsx - Updates demoRegistry.tsx with type: 'playground' - Updates App.tsx with route ``` ## File Locations Reference - Component showcase layout: `src/pages/ComponentShowcase.tsx` - Demo registry: `src/components/DemoShowcase/demoRegistry.tsx` - Navigation: `src/components/DemoShowcase/DemoNavigation.tsx` - Demo content: `src/components/DemoShowcase/[Name]Content.tsx` - Playground content: `src/components/DemoShowcase/[Name]PlaygroundContent.tsx` - Playground canvas: `src/components/DemoShowcase/PlaygroundCanvas.tsx` - Standalone demos: `src/pages/[Name]Demo.tsx` - Routes: `src/App.tsx` ## Key Principles 1. **Always ask** - Don't assume whether demos are wanted 2. **Always search** - Check for existing demos before updating 3. **Keep demos updated** - When components change, demos should reflect it 4. **Provide variety** - Show multiple use cases, not just basic usage 5. **Make it interactive** - Let users experiment with controls 6. **Include code** - Show implementation examples 7. **Support dark mode** - Test in both themes 8. **Organize clearly** - Use consistent structure across demos