--- name: frontend-components description: Generates and scaffolds reusable UI components with proper state management, props interfaces, lifecycle hooks, and styling encapsulation across React, Vue, Svelte, and Web Components. Use when implementing or scaffolding a reusable UI component in React, Vue, Svelte, or Web Components/Lit; when porting a design across frameworks; or when a component needs hooks, composables, reactive state, slots, or shadow-DOM encapsulation. metadata: references: - references/react-patterns.md - references/svelte-patterns.md - references/vue-patterns.md - references/web-components.md --- # Frontend Components ## Framework selection (one-line picker) | Need | Pick | |------|------| | Largest ecosystem, RSC/Next.js | React | | Low-boilerplate SFCs, Nuxt | Vue | | Smallest bundle, compiler-driven | Svelte | | Framework-agnostic / design-system primitive | Web Components (Lit) | Deep comparison: [react-patterns.md](references/react-patterns.md), [vue-patterns.md](references/vue-patterns.md), [svelte-patterns.md](references/svelte-patterns.md), [web-components.md](references/web-components.md). ## Workflow: build a new component 1. **Define props API** — name, types, required vs optional, default values, controlled-vs-uncontrolled pattern (accept optional `value` + `onChange`). 2. **Render markup** — semantic HTML first, then styling. 3. **Wire state/effects** — local state for ephemeral UI; lift to parent for shared. 4. **Add a11y** — role, aria-*, keyboard handlers, focus management. Verify with axe DevTools. 5. **Write tests** — render, interaction, a11y snapshot. 6. **Document** — Storybook story per variant + states (default, loading, error, disabled). **Checkpoint after step 4:** run `npx @axe-core/cli http://localhost:6006/iframe?id=` — fail build if any violation. **Checkpoint after step 5:** branch coverage on the component file must be >= 80% (`vitest run --coverage`). ## Reference template (React + Suspense + custom hook) ```tsx import { Suspense, use, useEffect, useId, useState } from "react"; function useDebounced(value: T, ms = 300): T { const [v, setV] = useState(value); useEffect(() => { const t = setTimeout(() => setV(value), ms); return () => clearTimeout(t); }, [value, ms]); return v; } export function SearchBox({ value, onChange, resultsPromise }: { value: string; onChange: (s: string) => void; resultsPromise: Promise; }) { const id = useId(); const debounced = useDebounced(value); return (
onChange(e.target.value)} aria-describedby={`${id}-hint`} /> Loading…

}>
); } function Results({ promise }: { promise: Promise; query: string }) { const items = use(promise); return
    {items.map((i) =>
  • {i}
  • )}
; } ``` Vue SFC, Svelte 5 runes, and Lit equivalents (same controlled-input + debounce pattern) live in [vue-patterns.md](references/vue-patterns.md), [svelte-patterns.md](references/svelte-patterns.md), and [web-components.md](references/web-components.md). ## Pre-merge gates ```bash npx size-limit # fail if component adds >5kb gzipped npx @axe-core/cli http://localhost:6006/iframe.html?id= # zero violations vitest run --coverage # branch coverage ≥80% on the component file ``` Long lists (>100 rows): use `react-window` / `vue-virtual-scroller` / `svelte-virtual-list`. Code-split modal/admin features (`React.lazy`, `defineAsyncComponent`, dynamic `import()`). ## Next Steps - **Component Library (the `component-library` skill)**: docs, testing, versioning - **CSS Architecture (the `css-architecture` skill)**: styling strategy - **Design System Creation (the `design-system-creation` skill)**: tokens + governance - **Accessibility Audit (the `accessibility-audit` skill)**: WCAG 2.2 AA - **Motion Design (the `motion-design` skill)**: purposeful animation