UI Patterns
Required: Dark Mode Support
All UI components MUST support dark mode using Tailwind's class strategy.
// Always provide dark: variants className="bg-white dark:bg-slate-900 text-slate-900 dark:text-white"
Color System
Brand Colors (Blue) - Primary actions
-
brand-500 / brand-600
-
Primary buttons, links
-
brand-100 / dark:brand-900/30
-
Highlighted backgrounds
-
brand-700 / dark:brand-300
-
Text on brand backgrounds
System Colors (Slate) - UI chrome
-
slate-50 / dark:slate-950
-
Page backgrounds
-
slate-100 / dark:slate-800
-
Secondary/card backgrounds
-
slate-200 / dark:slate-700
-
Borders
-
slate-400
-
Muted text
-
slate-700 / dark:white
-
Primary text
Semantic Colors
-
Success: emerald-* (done, approved)
-
Warning: amber-* (pending, paused)
-
Error: red-* (failed, stopped)
Component Classes
Use pre-defined component classes for consistency:
// Buttons <button className="btn btn-primary">Create</button> <button className="btn btn-secondary">Cancel</button> <button className="btn btn-ghost">Refresh</button> <button className="btn btn-danger">Delete</button>
// Inputs <input className="input" /> <textarea className="input resize-none" />
// Select dropdowns <select className="select w-[180px]"> <option>Option</option> </select>
// Cards <div className="card p-4">Content</div>
Status Badges
Use consistent status badge pattern with icons:
const STATUS_CONFIG = { backlog: { icon: "inbox", classes: "bg-slate-100 text-slate-700 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700" }, ready: { icon: "circle-dashed", classes: "bg-slate-100 text-slate-700 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700" }, in_progress: { icon: "timer", classes: "bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800" }, pending_review: { icon: "eye", classes: "bg-amber-100 text-amber-700 border-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:border-amber-800" }, done: { icon: "check-circle", classes: "bg-emerald-100 text-emerald-700 border-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800" }, };
// Badge structure <span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium border whitespace-nowrap {classes}"> <Icon className="w-3.5 h-3.5" /> {label} </span>
Typography
// Page titles <h1 className="text-2xl font-semibold text-slate-900 dark:text-white">
// Section titles <h2 className="text-lg font-semibold text-slate-900 dark:text-white">
// Subsection headers (uppercase) <h3 className="text-xs font-bold text-slate-400 uppercase tracking-wider">
Layout Patterns
Split Pane (50/50)
<div className="flex flex-1 min-h-0 overflow-hidden rounded-lg border border-slate-200 dark:border-slate-800"> <div className="w-1/2 border-r border-slate-200 dark:border-slate-800 p-6 overflow-y-auto bg-white dark:bg-slate-900"> {/* Left panel /} </div> <div className="w-1/2 flex flex-col min-w-0"> {/ Right panel */} </div> </div>
Section Card
<div className="p-4 bg-slate-50 dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700"> <h3 className="text-sm font-medium text-slate-900 dark:text-white mb-3"> Section Title </h3> {/* Content */} </div>
Modal Pattern
<div className="fixed inset-0 z-50 flex items-center justify-center"> <div className="absolute inset-0 bg-black/50" onClick={onClose} /> <div className="relative bg-white dark:bg-slate-800 rounded-lg shadow-xl w-full max-w-lg mx-4 border border-slate-200 dark:border-slate-700"> {/* Header /} <div className="flex items-center justify-between px-6 py-4 border-b border-slate-200 dark:border-slate-700"> <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Title</h2> <button onClick={onClose}>...</button> </div> {/ Body /} <div className="px-6 py-4">...</div> {/ Footer */} <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-slate-200 dark:border-slate-700"> <button className="btn btn-secondary">Cancel</button> <button className="btn btn-primary">Submit</button> </div> </div> </div>
Spacing Guidelines
Size Usage
gap-1.5
Icon + text in badges
gap-2
Button groups
gap-3
Form fields
gap-4
Section spacing
gap-6
Major section spacing
p-4
Card padding
p-6
Modal/panel padding
Scrollbars
Use .scrollbar-thin for custom scrollbars:
<div className="overflow-y-auto scrollbar-thin">
Loading States
// Skeleton loader <div className="animate-pulse bg-slate-200 dark:bg-slate-700 rounded h-4 w-32" />
// Spinner <svg className="animate-spin h-5 w-5 text-blue-500" viewBox="0 0 24 24"> <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" /> <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" /> </svg>
Empty States
<div className="flex flex-col items-center justify-center py-12 text-center"> <Icon className="w-12 h-12 text-slate-300 dark:text-slate-600 mb-4" /> <h3 className="text-lg font-medium text-slate-900 dark:text-white mb-2"> No items found </h3> <p className="text-sm text-slate-500 dark:text-slate-400 mb-4"> Get started by creating your first item. </p> <button className="btn btn-primary">Create Item</button> </div>