From ui-designer
Write a comprehensive component specification — purpose, props API, all states, responsive behaviour, accessibility requirements, and usage examples.
npx claudepluginhub hpsgd/turtlestack --plugin ui-designerThis skill is limited to using the following tools:
Write a component specification for $ARGUMENTS.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Calculates TAM/SAM/SOM using top-down, bottom-up, and value theory methodologies for market sizing, revenue estimation, and startup validation.
Write a component specification for $ARGUMENTS.
Before writing, search the codebase for existing implementations of this component or similar components. Reference existing patterns. This spec must be complete enough for an engineer to implement without follow-up questions.
Search for existing components that overlap with this request. Then make an explicit decision:
| Decision | When to use | What it means for this spec |
|---|---|---|
| Reuse | An existing component already handles this use case | Don't write a new spec. Document how to use the existing component for this scenario. Link to its spec. |
| Extend | An existing component is close but needs new variants, props, or states | Write a spec that extends the existing component. Reference the original spec. Only document what's new. |
| Create | No existing component covers this use case | Write a full spec from scratch. |
State the decision with justification: "Decision: Create — searched for existing upload components, found FileInput but it doesn't support drag-and-drop or progress indication. A new component is needed."
If the decision is Reuse, stop here — the output is a usage guide, not a new spec.
Write exactly two things:
Example:
What: A dismissible banner that communicates system-level messages to the user. When to use: For messages that affect the entire page or application (maintenance windows, billing alerts, feature announcements). Do NOT use for inline form validation (use
FormError) or transient notifications (useToast).
Document every prop in a table. Every prop must have a type, default value, and description.
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
variant | 'info' | 'success' | 'warning' | 'error' | 'info' | No | Visual style and semantic meaning |
children | ReactNode | — | Yes | Content to display |
onDismiss | () => void | undefined | No | Called when user dismisses. If omitted, banner is not dismissible |
icon | ReactNode | Auto from variant | No | Override the default icon for the variant |
Rules for prop design:
variant for visual/semantic differences. Do not use separate props like color, background, severity. One prop, one decision.false. The default state should be the absence of the modifier: disabled, not enabled; loading, not loaded.on. onClick, onDismiss, onChange — never handleClick (that is an internal implementation name).compact={true} not size="compact" | "default" when there are only two sizes.children and slot props over complex configuration objects. A component should be composable, not a god-object.For each variant, document:
| Variant | Visual treatment | Semantic meaning | When to use |
|---|---|---|---|
info | Blue background, info icon | Neutral information | General announcements, tips |
success | Green background, check icon | Positive confirmation | Completed actions, success states |
warning | Yellow background, alert icon | Caution needed | Approaching limits, deprecation notices |
error | Red background, error icon | Problem requiring action | System errors, failed operations |
Include a note on which variant to use when unsure. There should always be a default.
Document EVERY state the component can be in. Missing states are the #1 source of implementation bugs. Use this complete list and mark N/A for states that do not apply to this component:
| State | Visual treatment | Behaviour | Transitions to |
|---|---|---|---|
| Default | [Base appearance] | [Normal interaction behaviour] | Hover, Focus |
| Hover | [What changes on mouse hover] | [Cursor change, tooltips] | Default, Active |
| Focus | [Focus ring style, outline] | [Keyboard focus indicator — MUST be visible] | Default, Active |
| Active | [Pressed/clicked appearance] | [Visual feedback during press] | Default |
| Disabled | [Reduced opacity, muted colours] | [No interaction, no hover effects, cursor: not-allowed] | — |
| Loading | [Skeleton, spinner, or shimmer] | [Non-interactive during load, preserves layout dimensions] | Default, Error |
| Error | [Error styling, red border/text] | [Show error message, offer recovery action] | Default |
| Empty | [Empty state illustration or message] | [Guide user to populate — CTA if applicable] | Default |
| Selected | [Highlight, checkmark, background change] | [Indicates active selection] | Default |
| Read-only | [Similar to disabled but full contrast] | [Content is visible and copyable but not editable] | — |
Rules:
aria-disabled and prevent interaction — do not just change opacity without blocking events.Compound state combinations: For components with multiple simultaneous interaction modes (e.g., a data table with sorting + selection + inline editing), document each combination explicitly. A row can be selected AND being edited AND in a sorted column — the spec must define what each combination looks like and how transitions work between them.
Sub-component states: When a component contains sub-components with their own state (e.g., a toolbar that appears/disappears, an inline edit field), specify:
Define behaviour at each breakpoint. Use the project's breakpoint system (Tailwind defaults shown):
| Breakpoint | Width | Layout changes | Content changes |
|---|---|---|---|
| Mobile | < 640px (sm) | [Stack vertically, full-width] | [Truncate text, hide secondary actions behind menu] |
| Tablet | 640-1024px (sm-lg) | [Adjust grid columns, reduce padding] | [Show primary + secondary actions] |
| Desktop | > 1024px (lg+) | [Full layout, standard padding] | [Show all content and actions] |
Rules:
For components that render large datasets (tables, lists, grids, trees), address:
Every component must meet WCAG 2.1 AA. Specify each requirement explicitly:
For simple components, a single table is sufficient. For compound components with multiple interactive element types (e.g., a data table with sort headers, checkboxes, inline edit fields, and pagination), specify keyboard navigation per element type:
| Element type | Key | Action |
|---|---|---|
| [e.g., Sort header] | Enter / Space | [Toggle sort direction] |
| [e.g., Row checkbox] | Space | [Toggle selection] |
| [e.g., Inline edit field] | Enter | [Save edit] |
| [e.g., Inline edit field] | Escape | [Cancel edit, restore previous value] |
| [e.g., Pagination] | Enter | [Navigate to page] |
Focus management between element types must be specified: where does focus go after saving an inline edit? After selecting a row? After sorting changes the row order?
For simple components use this table instead:
| Key | Action |
|---|---|
Tab | [Where focus moves to] |
Shift+Tab | [Reverse focus movement] |
Enter / Space | [Primary activation — what happens] |
Escape | [Dismiss/close behaviour — what closes, where focus returns] |
Arrow keys | [Navigation within the component, if applicable] |
role="alert", role="dialog", role="button", etc.)aria-label, aria-labelledby, or visible text)aria-live, aria-expanded, aria-selected)aria-describedby if the label alone is insufficientThemeImage component or have dark-mode variantsprefers-reduced-motion: reduce — provide static alternativesProvide 3 examples showing different configurations:
// Basic usage
<Component variant="info">
Your trial expires in 3 days.
</Component>
// With dismiss callback
<Component variant="warning" onDismiss={() => setDismissed(true)}>
This API version is deprecated. <Link href="/migrate">Migrate now</Link>
</Component>
// Error state with action
<Component variant="error">
Payment failed. <Button variant="link" onClick={retry}>Try again</Button>
</Component>
End with explicit guidance:
| Do | Don't |
|---|---|
Use variant to communicate severity | Use custom colours outside the variant system |
| Keep content concise (1-2 sentences) | Put long-form content or multiple paragraphs inside |
| Provide a dismiss action for non-critical messages | Make error banners dismissible if the error needs resolution |
| Use one banner at a time per page section | Stack multiple banners — consolidate into one |
Present the spec as a single structured document using the sections above. If a section is not applicable to this component, include it with "N/A — [reason]" rather than omitting it. Missing sections cause implementation gaps.
/ui-designer:design-review — review the implemented component against this spec./ui-designer:accessibility-audit — audit the component for WCAG compliance after implementation.