# @repo/ui -- Atomic Design Component Library ## Purpose Shared UI component library built with shadcn/ui patterns, Tailwind CSS v4, and organized by Atomic Design levels. All components have co-located Storybook stories. This package is consumed by all frontend apps (`apps/web-next`, `apps/web-tanstack`). ## Atomic Design Classification Guide | Level | Definition | Examples | Import Rules | |---|---|---|---| | Atom | Single HTML element, cannot be broken down further | Button, Input, Label, Badge, Separator, Icon | Can import: `lib/`, `styles/`. NEVER import: molecules, organisms, templates | | Molecule | 2-3 atoms composed together, single responsibility | FormField, SearchBar, Tooltip, Select, Dropdown | Can import: `atoms/`, `lib/`. NEVER import: organisms, templates | | Organism | Complex self-contained section with multiple molecules/atoms | DataTable, Dialog, Header, Sidebar, Card, Navbar | Can import: `atoms/`, `molecules/`, `lib/`. NEVER import: templates | | Template | Page-level layout shell, content-agnostic (uses children/slots) | DashboardLayout, AuthLayout, MarketingLayout | Can import: `atoms/`, `molecules/`, `organisms/`, `lib/` | | Page | Template filled with real data | **LIVES IN `apps/`, NOT IN THIS PACKAGE** | N/A | ## Import Rules Table | Level | Can import from | NEVER import from | |---|---|---| | Atoms | `lib/`, `hooks/`, `styles/` | `molecules/`, `organisms/`, `templates/` | | Molecules | `atoms/`, `lib/`, `hooks/` | `organisms/`, `templates/` | | Organisms | `atoms/`, `molecules/`, `lib/`, `hooks/` | `templates/` | | Templates | `atoms/`, `molecules/`, `organisms/`, `lib/`, `hooks/` | (nothing above -- top level) | ## Component Rules Per Level - **Atoms:** No margins or positioning (consumer controls layout). No internal state. No business logic. Accept `className` prop for composition. Use `forwardRef` for DOM elements. - **Molecules:** Single responsibility. Minimal controlled state (e.g., open/closed). Compose atoms only. Accept `className` for outer container. - **Organisms:** Can have internal state and sub-components. Can fetch context. Self-contained sections of a page. - **Templates:** Use `children` or named slots (`sidebar`, `header`, etc.) for content injection. NEVER hard-code content or data. ## File Structure ``` packages/ui/ src/ lib/ utils.ts # cn() utility (clsx + twMerge) styles/ globals.css # Tailwind v4 @theme tokens, @import "tailwindcss" atoms/ button/ button.tsx # Button component (5 variants, 3 sizes) button.stories.tsx # Storybook stories index.ts # Barrel export input/ input.tsx # Input component input.stories.tsx index.ts label/ label.tsx # Label component index.ts index.ts # Barrel: re-exports all atoms molecules/ form-field/ form-field.tsx # FormField = Label + Input + error/description form-field.stories.tsx index.ts index.ts # Barrel: re-exports all molecules organisms/ index.ts # Barrel (empty -- no organisms yet) templates/ index.ts # Barrel (empty -- no templates yet) index.ts # Package entry: re-exports cn + all levels package.json AGENTS.md ``` ## Existing Components ### Button (Atom) - **Variants:** `default`, `secondary`, `destructive`, `outline`, `ghost` - **Sizes:** `sm` (h-9), `default` (h-10), `lg` (h-11) - **Props:** Extends `ButtonHTMLAttributes` plus `variant` and `size` - **Uses:** `forwardRef`, `cn()` for class merging ### Input (Atom) - **Props:** Extends `InputHTMLAttributes` - **Uses:** `forwardRef`, `cn()` for class merging - Full styling: border, focus ring, disabled state, file input support ### Label (Atom) - **Props:** Extends `LabelHTMLAttributes` - **Uses:** `forwardRef`, `cn()` for class merging - Handles `peer-disabled` state ### FormField (Molecule) - **Props:** Extends `InputProps` plus `label` (string), `error?` (string), `description?` (string) - **Composes:** Label + Input - Auto-generates `id` from label text if not provided ## cn() Utility The `cn()` function merges Tailwind classes safely using `clsx` + `tailwind-merge`: ```typescript import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ``` Usage in components: ```tsx