name: flux-design-system description: Flux monochrome design system specification. Pure grayscale oklch tokens, pill-shaped interactive elements, rounded container panels, deep dark mode, and elevation surfaces. Use when building, modifying, or reviewing any UI component, page, or style in the Flux web app. Triggers on tasks involving colors, spacing, border radius, dark mode, theming, design tokens, component styling, or visual consistency. Also use when asked to review whether UI matches the design system.
Flux Design System
Minimalist monochrome design language for AI-native product interfaces. Pure grayscale palette, pill-shaped interactives, rounded panels, deep dark mode, oklch color space throughout.
Core Principles
- Monochrome-first — All structural elements use pure grayscale
oklch(L 0 0). Chromatic color is reserved for semantic states only (destructive, success, warning, info). - Shape = function — Fully rounded (
rounded-full) = interactive. Large radius (rounded-xl) = container. This creates instant visual grammar. - Depth via luminance — Elevation is conveyed through stacked lightness levels, not heavy shadows. Surface tokens provide three progressive tiers.
- No
dark:prefix — All color switching is handled via CSS custom properties that auto-switch between:rootand.dark. Components should never use thedark:Tailwind variant for colors. Exceptions: visual effects likemix-blend-modeor third-party integrations (e.g., Shiki syntax highlighting).
Color Tokens
All tokens use oklch with chroma 0 for perceptual grayscale. L ranges 0 (black) to 1 (white).
Light Mode (:root)
--background: oklch(1 0 0) /* pure white page */
--foreground: oklch(0.13 0 0) /* near-black text */
--primary: oklch(0.15 0 0) /* strong CTA */
--primary-foreground: oklch(0.985 0 0) /* text on primary */
--secondary: oklch(0.955 0 0) /* subtle fill */
--muted: oklch(0.955 0 0) /* subdued bg */
--muted-foreground: oklch(0.50 0 0) /* placeholder text */
--accent: oklch(0.95 0 0) /* hover/active */
--card: oklch(1 0 0) /* card bg */
--popover: oklch(1 0 0) /* floating panels */
--border: oklch(0.91 0 0) /* structural borders */
--input: oklch(0.91 0 0) /* input borders */
--ring: oklch(0.65 0 0) /* focus ring */
--surface-1: oklch(0.985 0 0) /* elevation 1 */
--surface-2: oklch(0.97 0 0) /* elevation 2 */
--surface-3: oklch(0.955 0 0) /* elevation 3 */
--radius: 0.75rem /* 12px base */
Dark Mode (.dark)
--background: oklch(0.10 0 0) /* deep black ~#0a0a0a */
--foreground: oklch(0.93 0 0) /* reduced glare */
--primary: oklch(0.93 0 0) /* bright CTA */
--primary-foreground: oklch(0.10 0 0) /* text on primary */
--secondary: oklch(0.18 0 0) /* deeper fill */
--muted: oklch(0.18 0 0) /* subdued bg */
--muted-foreground: oklch(0.58 0 0) /* subdued text (AA on muted) */
--accent: oklch(0.35 0 0) /* subtle accent */
--card: oklch(0.14 0 0) /* elevated from bg */
--popover: oklch(0.16 0 0) /* above card level */
--border: oklch(1 0 0 / 8%) /* frosted borders */
--input: oklch(1 0 0 / 12%) /* input borders */
--ring: oklch(0.50 0 0) /* focus ring */
--surface-1: oklch(0.14 0 0) /* card level */
--surface-2: oklch(0.18 0 0) /* secondary level */
--surface-3: oklch(0.22 0 0) /* accent level */
--sidebar: oklch(0.16 0 0) /* elevated nav panel */
--sidebar-border: oklch(1 0 0 / 14%) /* stable panel edge */
Dark mode elevation stack: bg 0.10 → surface-1 0.14 → sidebar/popover 0.16 → surface-2 0.18 → surface-3 0.22
Subtle Tokens (auto-switch light/dark)
These tokens replace dark: prefix patterns. They provide reduced-opacity or variant fills that auto-switch.
| Token | Light | Dark | Usage |
|---|---|---|---|
--input-subtle |
transparent | oklch(1 0 0 / 12%) |
Input/select/checkbox background fill |
--input-subtle-hover |
oklch(0.955 0 0) |
oklch(1 0 0 / 20%) |
Hover state for outline buttons, select triggers |
--input-subtle-disabled |
oklch(0.91 0 0 / 50%) |
oklch(1 0 0 / 32%) |
Disabled input/switch unchecked fill |
--muted-subtle |
oklch(0.955 0 0 / 50%) |
oklch(0.18 0 0 / 50%) |
Ghost button/badge hover |
--accent-subtle |
oklch(0.95 0 0 / 50%) |
oklch(0.22 0 0 / 50%) |
Attachment hover, subtle accent |
--destructive-muted |
oklch(0.58 0.22 27 / 10%) |
oklch(0.704 0.191 22.216 / 20%) |
Destructive button/badge/dropdown bg |
--destructive-muted-hover |
oklch(0.58 0.22 27 / 20%) |
oklch(0.704 0.191 22.216 / 30%) |
Destructive hover state |
--destructive-border |
oklch(0.58 0.22 27) |
oklch(0.704 0.191 22.216 / 50%) |
Invalid input border |
--destructive-ring |
oklch(0.58 0.22 27 / 20%) |
oklch(0.704 0.191 22.216 / 40%) |
Invalid input ring |
--overlay |
oklch(0 0 0 / 40%) |
oklch(0 0 0 / 60%) |
Dialog/sheet backdrop |
Semantic Colors (only non-grayscale tokens)
- Destructive: hue 27 (red) —
oklch(0.58 0.22 27)+ muted/border/ring tiers - Success: hue 145 (green) — base + foreground + muted tiers
- Warning: hue 85 (yellow) — base + foreground + muted tiers
- Info: hue 250 (blue) — base + foreground + muted tiers
Chart Colors (grayscale ramp)
chart-1: 0.80 → chart-2: 0.65 → chart-3: 0.50 → chart-4: 0.35 → chart-5: 0.20
Border Radius System
Base --radius: 0.75rem (12px). Tailwind derives:
| Class | Value | Assigned to |
|---|---|---|
rounded-full |
9999px | Button, Badge, Progress, ScrollArea thumb, ButtonGroup, Switch |
rounded-xl |
16px | Card, Dialog, Popover, Dropdown, HoverCard, Select, Command, Input, Textarea, InputGroup, InputOTP, Tabs list, Alert |
rounded-lg |
12px | Dropdown/Select/Command items, Tabs trigger, Accordion trigger, Nav links |
rounded-md |
10px | Tooltip, Skeleton |
rounded-sm |
8px | Checkbox (soft square) |
Rule: never use rounded-2xl for popup containers. It clips items near edges. All floating panels use rounded-xl with p-1 inner padding for list-style containers.
Rule: never use rounded-[Xpx] arbitrary values. Always use the token-derived classes above.
Typography
- Font:
"Inter Variable", sans-serif(variable font, 100-900 weights) - Base size:
text-sm(14px) on desktop,text-base(16px) on small screens - Body line-height:
text-sm/relaxed(~1.6) - Heading weight:
font-medium(500) - Smoothing:
antialiasedon body
Spacing
Buttons
| Size | Height | Padding |
|---|---|---|
xs |
h-6 | px-3 |
sm |
h-8 | px-3.5 |
default |
h-9 | px-4 |
lg |
h-10 | px-5 |
icon |
size-9 | — |
Inputs
All text inputs and select triggers: h-9 px-3 rounded-xl.
Containers
- Card:
py-4, contentpx-4,gap-4 - Popover/HoverCard:
p-2.5 gap-2.5 - Dropdown/Select/Command:
p-1(list padding) - Dialog:
p-4 gap-4
Interactions
- Press:
active:scale-[0.98]on all buttons (2% scale-down) - Transitions:
transition-[color,background-color,border-color,box-shadow] - Popup animations:
duration-100, directionalslide-in-from-*based on placement side - Focus:
focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 - Motion: always include
motion-reduce:transition-none motion-reduce:animate-none
Component Patterns
Popup containers (dropdown, select, popover, hover card, command, dialog)
bg-popover text-popover-foreground
ring-1 ring-foreground/10
shadow-lg rounded-xl
List-style get p-1. Content-style get p-2.5.
List items (inside popups)
rounded-lg px-2 py-2 text-xs
focus:bg-accent focus:text-accent-foreground
data-disabled:pointer-events-none data-disabled:opacity-50
Cards
rounded-xl bg-card ring-1 ring-border
First-child images: rounded-t-xl. Last-child: rounded-b-xl.
Sidebar
Dark mode sidebar uses an elevated panel tone (--sidebar: oklch(0.16 0 0)) with a stronger edge (--sidebar-border: oklch(1 0 0 / 14%)) to remain visibly distinct from the page background (--background: oklch(0.10 0 0)). Light mode remains oklch(0.985 0 0).
Invalid state pattern (inputs, checkboxes, switches)
aria-invalid:border-destructive-border
aria-invalid:ring-1
aria-invalid:ring-destructive-ring
Never use dark:aria-invalid:* — the tokens auto-switch.
Destructive variant pattern (buttons, badges, dropdown items)
bg-destructive-muted text-destructive
hover:bg-destructive-muted-hover
focus-visible:ring-destructive-ring
Accessibility
- All light mode text pairs pass WCAG AA 4.5:1
- Dark
muted-foregroundis set tooklch(0.58 0 0)to clear AA on muted surfaces - All animations respect
prefers-reduced-motion - Focus uses
focus-visible:(keyboard only, not mouse) - No hardcoded colors — always use design tokens
Rules
- Never use chromatic colors for structural/decorative purposes
- Never use
rounded-2xlon popup containers - Never use
dark:prefix for color-related classes — use auto-switching CSS tokens instead - Never use hardcoded Tailwind colors (e.g.,
gray-500,blue-600,indigo-700) — use semantic tokens - Always pair foreground tokens with their background counterparts
- Always include
motion-reduce:variants on animated elements - Always use
focus-visible:notfocus:for focus rings - Use
ring-1 ring-foreground/10for container borders, notborder - Chart visualizations must use the grayscale
chart-1..5ramp - Token file:
apps/web/src/index.css - Component files:
apps/web/src/components/ui/*.tsx
Extended Reference
For full token tables, contrast ratio analysis, and per-component file index, see references/tokens.md.

