| name | component-generator |
| description | Generate production-ready SolidJS components with Kobalte accessibility primitives, CVA variants, and Storybook stories. Use when creating UI components for the frontend application. |
SolidJS Component Generator
Generate fully-functional SolidJS components following established architecture patterns.
Critical Constraints
Components MUST be purely presentational:
- ✅ Accept props, render UI, emit events via callbacks
- ✅ Use Kobalte primitives for accessibility where appropriate
- ✅ Support both light and dark themes
- ✅ Pass biome + TypeScript checks
- ✅ Have Storybook stories for testing
Components must NOT:
- ❌ Make API calls or import backend packages
- ❌ Contain business logic (belongs in pages/features)
- ❌ Manage application state (use props/callbacks)
Required Reading (BEFORE ANY GENERATION)
Read these files in order before writing code:
/skills/services/frontend/src/components/ui/button/button.tsx- PRIMARY REFERENCE pattern/skills/.claude/skills/component-generator/kobalte-primitives.md- Primitive catalog with import paths/skills/.claude/skills/component-generator/accessibility-guidelines.md- Props to expose per component type/skills/.claude/skills/component-generator/color-reference.md- Theme tokens (NEVER use default Tailwind colors)/skills/.claude/skills/component-generator/themed-story-pattern.md- Story pattern with Light/Dark variants
Additional references:
/skills/services/frontend/src/components/ui/badge/badge.tsx- Plain HTML + CVA pattern/skills/services/frontend/src/components/composite/search-input/search-input.tsx- Complex Kobalte Combobox
Workflow
Stage 1: Discovery
Gather these requirements:
- Component Name - PascalCase (e.g., "IconButton", "UserCard")
- Tier - Where it belongs:
primitives- Layout elements (Flex, Stack, Text)ui- Interactive components (Button, Badge, Card)composite- Combined ui components (SearchInput, IconButton)feature- Domain-specific layouts (Navbar, Footer)
- Purpose - Brief description for Kobalte matching
Stage 2: Design
Kobalte Primitive Selection:
- Read
kobalte-primitives.md - Match keywords from user's purpose description
- Suggest top matches or "none" for plain HTML
- User confirms choice
- Read
Variants:
- Color variants: primary, secondary, info, success, warning, danger, outline (based on component type)
- Size variants: sm, md, lg, xl (based on Button pattern)
- User can accept suggestions or customize
Props:
- Read
accessibility-guidelines.mdfor component type - Determine which accessibility props to expose
- Ask about additional props (icon, loading, etc.)
- Read
Stage 3: Confirm
Present summary:
I'll create {{NAME}} with:
- Tier: {{TIER}}
- Base: {{PRIMITIVE or "Plain HTML"}}
- Variants: {{COLORS}}, {{SIZES}}
- Files: index.ts, {{name}}.tsx, {{name}}.stories.tsx
Generate?
Stage 4: Generate & Validate
Pre-generation:
- Check if component already exists
- Create tier directory if needed
Generate 3 files:
{name}.tsx - Component implementation:
- Determine pattern: USE_KOBALTE (true/false), HAS_VARIANTS (true/false)
- Follow Button.tsx structure exactly
- Use color-reference.md for variant classes
- Use accessibility-guidelines.md for props
- Always spread
{...others}for HTML attribute passthrough
index.ts - Barrel export:
export { ComponentName, type ComponentNameProps } from "./component-name";{name}.stories.tsx - Themed stories:
- Follow themed-story-pattern.md exactly
- Create Light/Dark variant pairs for each variant
- Include AllVariants showcase story
Validate (must all pass before proceeding):
cd /skills/services/frontend && pnpm check # Biome
cd /skills/services/frontend && pnpm typecheck # TypeScript
cd /skills/services/frontend && pnpm test # Storybook tests
If validation fails: Fix errors properly (no workarounds), re-run validation.
Post-generation response:
✅ Generated {{NAME}} successfully!
Files: index.ts, {{name}}.tsx, {{name}}.stories.tsx
Location: /skills/services/frontend/src/components/{{tier}}/{{name}}/
Validation: ✅ Biome ✅ TypeScript ✅ Tests
Import: import { {{NAME}} } from "@/components/{{tier}}/{{name}}"
Usage: <{{NAME}} variant="primary" size="md">Content</{{NAME}}>
Component Patterns
Determine based on requirements:
| Pattern | USE_KOBALTE | HAS_VARIANTS | Example |
|---|---|---|---|
| Kobalte + CVA | true | true | Button |
| Plain HTML + CVA | false | true | Badge |
| Plain HTML only | false | false | Label |
| Kobalte only | true | false | (rare) |
Story Pattern
All stories use themed Light/Dark variants:
import { createThemedStories } from "@/components/story-helpers";
const primaryBase: Story = {
args: { variant: "primary", children: "Primary" },
};
const primaryThemed = createThemedStories({
story: primaryBase,
testMode: "both",
});
export const PrimaryLight = primaryThemed.Light;
export const PrimaryDark = primaryThemed.Dark;
testMode options: "both" | "light" | "dark" | "none"
Key Principles
- Read reference files BEFORE generation - Button.tsx is PRIMARY REFERENCE
- Follow existing patterns exactly - Don't invent new patterns
- Accessibility first - Use Kobalte, expose accessibility props
- Dark mode mandatory - Theme colors need
-darkvariants, shared colors don't - Always spread
{...others}- Enables HTML attribute passthrough - No workarounds - Fix errors properly, never use type assertions
- One component at a time - Complete and validate before proceeding
- Use
rounded-radius- Notrounded-mdorrounded-lg(badges userounded-full)
Error Handling
Component exists: Ask to overwrite or choose new name
Validation fails:
- Read error message
- Fix the actual issue (no workarounds)
- Re-run validation
- Repeat until clean
Invalid tier: Show valid options (primitives, ui, composite, feature)
Example
User: Create a Badge component
Agent: Which tier? (primitives/ui/composite/feature)
User: ui
Agent: Purpose?
User: Small label for status or categories
Agent: No direct Kobalte match. Use plain HTML?
User: Yes
Agent: Color variants? Suggested: primary, secondary, info, success, warning, danger
User: Use suggestions
Agent: Size variants? Suggested: sm, md
User: sm and md
Agent:
Creating Badge:
- Tier: ui | Base: span | Variants: 6 colors, 2 sizes
- Files: index.ts, badge.tsx, badge.stories.tsx
Generate?
User: Yes
Agent: [Reads reference files, generates, validates]
✅ Generated Badge successfully!
Location: /skills/services/frontend/src/components/ui/badge/
Validation: ✅ Biome ✅ TypeScript ✅ Tests
Import: import { Badge } from "@/components/ui/badge"
Start
Greet the user and ask what component they'd like to create.