--- name: component-library description: Build production-grade, accessible, and tested component libraries with Storybook, Chromatic, and design tokens sasmp_version: "2.0.0" bonded_agent: 03-component-architecture bond_type: PRIMARY_BOND input_validation: required_packages: - "storybook": ">=7.0.0" - "@storybook/react": ">=7.0.0" output_format: code_examples: tsx test_template: jest storybook_template: csf3 error_handling: patterns: - prop_validation - error_boundary - fallback_component observability: logging: storybook_console metrics: ["component_coverage", "a11y_score"] --- # Component Library Building Skill ## Overview Learn to build reusable, accessible, and well-documented component libraries for React applications using modern design patterns and tools. ## Learning Objectives - Design reusable component APIs - Implement accessible components (WCAG 2.1) - Create component variants and compositions - Build documentation with Storybook - Publish and maintain npm packages ## Component Design Principles ### 1. Flexible and Composable ```jsx // Good: Flexible API Title Content // Bad: Rigid API ``` ### 2. Accessible by Default ```jsx function Button({ children, onClick, disabled, ...props }) { return ( ); } ``` ## Essential Components ### Button Component ```jsx const Button = forwardRef(({ children, variant = 'primary', size = 'md', disabled = false, loading = false, leftIcon, rightIcon, ...props }, ref) => { return ( ); }); Button.displayName = 'Button'; ``` ### Input Component ```jsx const Input = forwardRef(({ label, error, helper, required, ...props }, ref) => { const id = useId(); return (
{label && ( )} {helper && {helper}} {error && {error}}
); }); ``` ### Modal Component ```jsx function Modal({ isOpen, onClose, title, children }) { const modalRef = useRef(null); useEffect(() => { if (isOpen) { const previousActiveElement = document.activeElement; modalRef.current?.focus(); return () => { previousActiveElement?.focus(); }; } }, [isOpen]); useOnClickOutside(modalRef, onClose); if (!isOpen) return null; return createPortal(
{children}
, document.body ); } ``` ### Dropdown Component ```jsx function Dropdown({ trigger, children }) { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); useOnClickOutside(dropdownRef, () => setIsOpen(false)); return (
setIsOpen(!isOpen)} role="button" aria-expanded={isOpen}> {trigger}
{isOpen && (
{children}
)}
); } function DropdownItem({ onClick, children }) { return (
{children}
); } Dropdown.Item = DropdownItem; ``` ## Compound Components Pattern ### Tabs Component ```jsx const TabsContext = createContext(); function Tabs({ children, defaultTab }) { const [activeTab, setActiveTab] = useState(defaultTab); return (
{children}
); } function TabList({ children }) { return
{children}
; } function Tab({ id, children }) { const { activeTab, setActiveTab } = useContext(TabsContext); return ( ); } function TabPanels({ children }) { return
{children}
; } function TabPanel({ id, children }) { const { activeTab } = useContext(TabsContext); if (activeTab !== id) return null; return
{children}
; } Tabs.List = TabList; Tabs.Tab = Tab; Tabs.Panels = TabPanels; Tabs.Panel = TabPanel; ``` ## Storybook Integration ### Installation ```bash npx storybook@latest init ``` ### Button Stories ```jsx // Button.stories.jsx import { Button } from './Button'; export default { title: 'Components/Button', component: Button, argTypes: { variant: { control: 'select', options: ['primary', 'secondary', 'danger'] }, size: { control: 'select', options: ['sm', 'md', 'lg'] } } }; export const Primary = { args: { variant: 'primary', children: 'Button' } }; export const WithIcons = { args: { leftIcon: , children: 'Button' } }; export const Loading = { args: { loading: true, children: 'Loading...' } }; ``` ## TypeScript Support ```typescript // Button.tsx interface ButtonProps extends React.ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'danger'; size?: 'sm' | 'md' | 'lg'; loading?: boolean; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; } const Button = forwardRef( ({ children, variant = 'primary', size = 'md', ...props }, ref) => { return ( ); } ); ``` ## Publishing to npm ### package.json Setup ```json { "name": "@yourname/component-library", "version": "1.0.0", "main": "dist/index.js", "module": "dist/index.esm.js", "types": "dist/index.d.ts", "files": ["dist"], "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" } } ``` ## Practice Projects 1. Build a complete Button component with variants 2. Create accessible Form components (Input, Select, Checkbox) 3. Implement Modal with focus trap 4. Build Dropdown with keyboard navigation 5. Create Tabs compound component 6. Implement Toast notification system 7. Build Tooltip component ## Resources - [Radix UI](https://www.radix-ui.com) - Headless UI components - [Headless UI](https://headlessui.com) - Unstyled components - [Storybook](https://storybook.js.org) - Component documentation - [React Aria](https://react-spectrum.adobe.com/react-aria/) - Accessibility --- **Difficulty**: Intermediate to Advanced **Estimated Time**: 3-4 weeks **Prerequisites**: React Fundamentals, Component Architecture