# Archon UI Standards **Audience**: AI agents performing automated UI audits and refactors **Purpose**: Single source of truth for UI patterns, violations, and automated detection **Usage**: Run `/archon:archon-ui-consistency-review` to scan code against these standards --- ## 1. TAILWIND V4 ### Rules - **NO dynamic class construction** - Tailwind scans source code as plain text at build time - NEVER: `` `bg-${color}-500` ``, `` `ring-${color}-500` ``, `` `shadow-${size}` `` - Use static lookup objects instead - **Bare HSL values in CSS variables** - NO `hsl()` wrapper - Correct: `--background: 0 0% 98%;` - Wrong: `--background: hsl(0 0% 98%);` - **CSS variables allowed in arbitrary values** - Utility name must be static - Correct: `bg-[var(--accent)]` - Wrong: `` `bg-[var(--${colorName})]` `` - **Use @theme inline** to map CSS vars to Tailwind utilities - **Define @custom-variant dark** - Required for `dark:` to work in v4 ### Anti-Patterns ```tsx // ❌ Dynamic classes (NO CSS GENERATED) const color = "cyan";
// Common miss! // ❌ Inline styles for visual CSS
``` ### Good Examples ```tsx // ✅ Static lookup for discrete variants const colorClasses = { cyan: "bg-cyan-500 text-cyan-900 ring-cyan-500", purple: "bg-purple-500 text-purple-900 ring-purple-500", };
// ✅ CSS variables for dynamic values
``` ### Automated Scans ```bash # All dynamic class construction patterns grep -rn "className.*\`.*\${.*}\`" [path] --include="*.tsx" grep -rn "bg-\${.*}\|text-\${.*}\|border-\${.*}" [path] --include="*.tsx" grep -rn "ring-\${.*}\|shadow-\${.*}\|outline-\${.*}\|opacity-\${.*}" [path] --include="*.tsx" # Inline visual styles (not CSS vars) grep -rn "style={{.*backgroundColor\|color:\|padding:" [path] --include="*.tsx" ``` **Fix Pattern**: Add all properties to static variant object (checked, glow, focusRing, hover) --- ## 2. LAYOUT & RESPONSIVE ### Rules - **Responsive grids** - NEVER fixed columns without breakpoints - Use: `grid-cols-1 md:grid-cols-2 lg:grid-cols-4` - **Constrain horizontal scroll** - Parent must have `w-full` or `max-w-*` - **Add scrollbar-hide** to all `overflow-x-auto` containers - **min-w-0 on flex parents** containing scroll containers (prevents page expansion) - **Text truncation** - Always use `truncate`, `line-clamp-N`, or `break-words` - **Desktop-primary** - Optimize for desktop, add responsive breakpoints down ### Anti-Patterns ```tsx // ❌ Fixed grid (breaks mobile)
// ❌ Unconstrained scroll (page becomes horizontally scrollable)
// ❌ Flex parent without min-w-0 (page expansion)
{/* MISSING min-w-0! */}
``` ### Good Examples ```tsx // ✅ Responsive grid
// ✅ Constrained horizontal scroll
// ✅ Flex parent with scroll container
{/* min-w-0 CRITICAL */} ``` ### Automated Scans ```bash # Non-responsive grids grep -rn "grid-cols-[2-9]" [path] --include="*.tsx" | grep -v "md:\|lg:\|xl:" # Unconstrained scroll grep -rn "overflow-x-auto" [path] --include="*.tsx" # Then manually verify parent has w-full # Missing text truncation grep -rn "`, add responsive breakpoints to grids --- ## 3. THEMING ### Rules - **Every visible color needs `dark:` variant** - **Structure identical** between themes (only colors/opacity change) - **Use tokens** for both light and dark (`--bg` and redefine in `.dark`) ### Anti-Patterns ```tsx // ❌ No dark variant
// ❌ Different structure in dark mode {theme === 'dark' ? : } ``` ### Good Examples ```tsx // ✅ Both themes
``` ### Automated Scans ```bash # Colors without dark variants grep -rn "bg-.*-[0-9]" [path] --include="*.tsx" | grep -v "dark:" ``` **Fix Pattern**: Add `dark:` variant for every color, border, shadow --- ## 4. RADIX UI ### Rules - **Use Radix primitives** - NEVER native ``, `` - **Compose with asChild** - Don't wrap, attach behavior to your components - **Style via data attributes** - `[data-state="open"]`, `[data-disabled]` - **Use Portal** for overlays with proper z-index - **Support both controlled and uncontrolled modes** - All form primitives must work in both modes ### Controlled vs Uncontrolled Form Components **CRITICAL RULE**: Form primitives (Switch, Checkbox, Select, etc.) MUST support both controlled and uncontrolled modes. **Controlled Mode**: Parent manages state via `value`/`checked` prop + `onChange`/`onCheckedChange` handler **Uncontrolled Mode**: Component manages own state via `defaultValue`/`defaultChecked` ### Anti-Patterns ```tsx // ❌ Native HTML // ❌ Wrong composition // ❌ Only supports controlled mode (breaks uncontrolled usage) const Switch = ({ checked, ...props }) => { const displayIcon = checked ? iconOn : iconOff; // No internal state! return }; ``` ### Good Examples ```tsx // ✅ Radix with asChild // ✅ Radix primitives // ✅ Supports both controlled and uncontrolled modes const Switch = ({ checked, defaultChecked, onCheckedChange, ...props }) => { const isControlled = checked !== undefined; const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false); const actualChecked = isControlled ? checked : internalChecked; const handleChange = (newChecked: boolean) => { if (!isControlled) setInternalChecked(newChecked); onCheckedChange?.(newChecked); }; return }; ``` ### Automated Scans ```bash # Native HTML form elements grep -rn "\|type=\"checkbox\"" [path]` - Emerald usage: `grep -rn "emerald" [path] --include="*.tsx" --include="*.ts"` (must use "green") ### High Priority - Missing keyboard: `grep -rn "onClick.*role=\"button\"" [path]` (verify onKeyDown) - Clickable icons: `grep -rn "<[A-Z].*onClick={" [path] --include="*.tsx" | grep -v "&1 | grep "error TS"` - Line length: `grep -rn ".\{121,\}" [path] --include="*.tsx" | grep className` - Missing satisfies: `grep -rn "const.*Classes = {" [path]/primitives -A 5 | grep -v "satisfies"` - Props unused: Manual check interfaces vs usage --- ## QUICK REFERENCE ### Breakpoints - sm: 640px | md: 768px | lg: 1024px | xl: 1280px | 2xl: 1536px ### Color Variant Checklist (for primitives with colors) Every color object MUST have: - [ ] `checked` or `active` state classes - [ ] `glow` effect - [ ] `focusRing` - STATIC class like `"focus-visible:ring-cyan-500"` - [ ] `hover` state - [ ] All 6 colors: purple, blue, cyan, green, orange, pink ### Common Patterns **Horizontal Scroll (Archon Standard)** ```tsx
{items.map(i => )} ``` **Responsive Grid** ```tsx
``` **Flex + Scroll Container** ```tsx
{/* min-w-0 REQUIRED */} {/* scroll containers here */} ``` **Color Variants (Static Lookup)** ```tsx const variants = { cyan: { checked: "data-[state=checked]:bg-cyan-500/20", glow: "shadow-[0_0_15px_rgba(34,211,238,0.5)]", focusRing: "focus-visible:ring-cyan-500", // STATIC! hover: "hover:bg-cyan-500/10", }, // ... repeat for all colors }; ``` **Keyboard Support** ```tsx
(e.key === "Enter" || e.key === " ") && handler()} aria-selected={isSelected} > ``` --- ## SCORING VIOLATIONS ### Critical (-3 points each) - Dynamic class construction - Missing keyboard support on interactive - Non-responsive grids causing horizontal scroll - TypeScript errors ### High (-2 points each) - Unconstrained scroll containers - Props that do nothing - Non-functional UI logic (filter/sort/drag-drop) - Missing dark mode variants ### Medium (-1 point each) - Native HTML form elements - Hardcoded glassmorphism - Missing text truncation - Color type inconsistencies **Grading Scale:** - 0 critical violations: A (9-10/10) - 1 critical: B (7-8/10) - 2-3 critical: C (5-6/10) - 4+ critical: F (1-4/10) --- ## ADDING NEW RULES When code review finds an issue not caught by automated review: 1. **Identify which section** it belongs to (Tailwind? Layout? A11y?) 2. **Add to that section**: - Rule (what to do) - Anti-Pattern example - Good example - Automated scan (if possible) 3. **Add scan to AUTOMATED SCAN REFERENCE** 4. **Done** - Next review will catch it **Goal**: Eventually eliminate manual code reviews entirely.