# Plan 5: UI System — Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Set up `@repo/ui` with Atomic Design folder structure, Tailwind CSS v4, shadcn/ui, base components (atoms + a molecule), and `apps/storybook` with Storybook 8. **Architecture:** `@repo/ui` uses Atomic Design (atoms/molecules/organisms/templates). Tailwind v4 uses CSS-first config (`@import "tailwindcss"` + `@theme`). shadcn/ui components land in `atoms/` by default. Storybook runs as a separate app pulling stories from the UI package via `@storybook/react-vite` with `@tailwindcss/vite` plugin. **Tech Stack:** Tailwind CSS v4, shadcn/ui, clsx, tailwind-merge, Storybook 8, @storybook/react-vite --- ### Task 1: Set up @repo/ui with Tailwind v4 + Atomic Design structure **Files:** - Modify: `packages/ui/package.json` - Modify: `packages/ui/tsconfig.json` - Create: `packages/ui/src/styles/globals.css` - Create: `packages/ui/src/lib/utils.ts` - Create: `packages/ui/src/atoms/index.ts` - Create: `packages/ui/src/molecules/index.ts` - Create: `packages/ui/src/organisms/index.ts` - Create: `packages/ui/src/templates/index.ts` - Modify: `packages/ui/src/index.ts` - [ ] **Step 1: Update packages/ui/package.json** ```json { "name": "@repo/ui", "private": true, "version": "0.0.0", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "scripts": { "build": "echo 'typechecked by consuming app bundler'", "lint": "eslint .", "test": "vitest run", "typecheck": "tsc --noEmit" }, "dependencies": { "clsx": "^2.1.0", "tailwind-merge": "^3.0.0", "react": "^19.0.0" }, "devDependencies": { "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@types/react": "^19.0.0", "tailwindcss": "^4.1.0" } } ``` - [ ] **Step 2: Create src/styles/globals.css** Tailwind v4 CSS-first config — no tailwind.config.ts needed. ```css @import "tailwindcss"; @theme { --color-background: hsl(0 0% 100%); --color-foreground: hsl(240 10% 3.9%); --color-card: hsl(0 0% 100%); --color-card-foreground: hsl(240 10% 3.9%); --color-popover: hsl(0 0% 100%); --color-popover-foreground: hsl(240 10% 3.9%); --color-primary: hsl(240 5.9% 10%); --color-primary-foreground: hsl(0 0% 98%); --color-secondary: hsl(240 4.8% 95.9%); --color-secondary-foreground: hsl(240 5.9% 10%); --color-muted: hsl(240 4.8% 95.9%); --color-muted-foreground: hsl(240 3.8% 46.1%); --color-accent: hsl(240 4.8% 95.9%); --color-accent-foreground: hsl(240 5.9% 10%); --color-destructive: hsl(0 84.2% 60.2%); --color-destructive-foreground: hsl(0 0% 98%); --color-border: hsl(240 5.9% 90%); --color-input: hsl(240 5.9% 90%); --color-ring: hsl(240 5.9% 10%); --radius-sm: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; } ``` - [ ] **Step 3: Create src/lib/utils.ts** ```typescript import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ``` - [ ] **Step 4: Create atomic design barrel files** ```typescript // packages/ui/src/atoms/index.ts // Atom components are exported from here export {}; ``` ```typescript // packages/ui/src/molecules/index.ts // Molecule components are exported from here export {}; ``` ```typescript // packages/ui/src/organisms/index.ts // Organism components are exported from here export {}; ``` ```typescript // packages/ui/src/templates/index.ts // Template components are exported from here export {}; ``` - [ ] **Step 5: Update src/index.ts** ```typescript export { cn } from "./lib/utils.js"; export * from "./atoms/index.js"; export * from "./molecules/index.js"; export * from "./organisms/index.js"; export * from "./templates/index.js"; ``` - [ ] **Step 6: Run pnpm install and commit** ```bash pnpm install git add packages/ui/ pnpm-lock.yaml git commit -m "feat(ui): set up Atomic Design structure with Tailwind v4" ``` --- ### Task 2: Add Button atom **Files:** - Create: `packages/ui/src/atoms/button/button.tsx` - Create: `packages/ui/src/atoms/button/button.stories.tsx` - Create: `packages/ui/src/atoms/button/index.ts` - Modify: `packages/ui/src/atoms/index.ts` - [ ] **Step 1: Create button.tsx** ```tsx import { forwardRef, type ButtonHTMLAttributes } from "react"; import { cn } from "../../lib/utils.js"; export interface ButtonProps extends ButtonHTMLAttributes { variant?: "default" | "secondary" | "destructive" | "outline" | "ghost"; size?: "sm" | "default" | "lg"; } const variantStyles: Record, string> = { default: "bg-primary text-primary-foreground hover:bg-primary/90", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", ghost: "hover:bg-accent hover:text-accent-foreground", }; const sizeStyles: Record, string> = { sm: "h-9 px-3 text-sm", default: "h-10 px-4 py-2", lg: "h-11 px-8 text-lg", }; export const Button = forwardRef( ({ className, variant = "default", size = "default", ...props }, ref) => { return (