diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..a021a98 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,131 @@ +# Polaris Task Force Design System + +## 1. Atmosphere & Identity + +Polaris is a dark operations console: focused, quiet, and information-dense without feeling cramped. The signature is a neutral charcoal surface hierarchy with restrained white controls and small, purposeful state accents. + +## 2. Color + +### Palette + +| Role | Token | Usage | +|------|-------|-------| +| Surface / page | `bg-background` | Frontend page background | +| Surface / card | `bg-card` | Elevated content sections | +| Text / primary | `text-foreground` | Headings and primary labels | +| Text / secondary | `text-muted-foreground` | Descriptions and supporting copy | +| Interactive / primary | `bg-primary`, `text-primary-foreground` | Primary actions and checked controls | +| Interactive / focus | `ring-ring` | Keyboard focus indicators | +| Border | `border-border` | Card and control boundaries | +| Status / error | `text-destructive` | Inline validation and failure copy | +| Status / success | `text-emerald-500` | Existing save confirmations | + +### Rules + +- Use semantic Tailwind tokens backed by `src/app/(frontend)/styles.css`; do not add raw colors in frontend components. +- Preserve the dark neutral palette and use accent color only for interactive state. + +## 3. Typography + +### Scale + +| Level | Token | Usage | +|-------|-------|-------| +| Page title | `text-lg font-semibold` | Route heading | +| Card title | `font-semibold` | Section heading | +| Body | inherited `text-base` | Primary content | +| Supporting | `text-sm text-muted-foreground` | Descriptions and helper text | +| Compact | `text-xs` | Secondary metadata only | + +### Font Stack + +- Primary: Geist, sans-serif +- Mono: Geist Mono, monospace + +## 4. Spacing & Layout + +### Base Unit + +Spacing follows Tailwind's 4px scale. Existing frontend stacks use `gap-1`, `gap-2`, `gap-3`, `gap-4`, and `gap-6`. + +### Rules + +- Use `flex flex-col gap-*` for vertical stacks; do not use `space-y-*`. +- Account content is constrained with `max-w-2xl` and uses `gap-6` between cards. +- Preference sections use `CardHeader` and `CardContent`; controls use `gap-4`. +- Preference sub-options are indented with `pl-6` and remain one readable column on narrow screens. + +## 5. Components + +### Card sections + +- **Structure**: `Card` → `CardHeader` → `CardTitle` + `CardDescription`; `CardContent` body. +- **Variants**: default dark card surface. +- **Spacing**: built-in card padding; internal control stack uses `gap-4`. +- **States**: default, focus/error states belong to child controls. +- **Accessibility**: headings and descriptions provide section context. +- **Motion**: no section-level motion. +- **Layout**: vertical stack. + +### Preference row + +- **Structure**: `label.flex.items-center.justify-between` with text on the left and a shadcn control on the right. +- **Variants**: primary setting and indented notification setting. +- **Spacing**: `gap-3` for label copy; `pl-6` for dependent settings. +- **States**: default, checked, unchecked, disabled, focus-visible. +- **Accessibility**: the label owns the control relationship; disabled dependent rows use both disabled controls and reduced-opacity presentation. +- **Motion**: shadcn control transition only. +- **Layout**: responsive cluster with a single-column text block. + +### Switch + +- **Structure**: shadcn `Switch` with an associated label and optional description. +- **Variants**: primary and dependent/disabled. +- **Spacing**: control row uses `gap-4`. +- **States**: unchecked, checked, hover, active, focus-visible, disabled. +- **Accessibility**: keyboard reachable with visible focus and native switch semantics. +- **Motion**: 100–150ms control transition. +- **Layout**: inline control at the row edge. + +### RadioGroup + +- **Structure**: shadcn `RadioGroup` with `RadioGroupItem` and `Label` pairs. +- **Variants**: two-option roster label selection. +- **Spacing**: option cluster uses `gap-4`. +- **States**: selected, unselected, hover, active, focus-visible. +- **Accessibility**: grouped options retain native radio semantics and labels. +- **Motion**: control transition only. +- **Layout**: wraps on narrow screens without horizontal overflow. + +## 6. Motion & Interaction + +### Timing + +| Type | Duration | Usage | +|------|----------|-------| +| Micro | 100–150ms | Switch and radio state feedback | +| Standard | 200–300ms | Button hover and focus transitions | + +### Rules + +- Keep motion in existing shadcn controls and buttons; do not add decorative animation to the account form. +- Preserve visible keyboard focus and `prefers-reduced-motion` behavior from the component primitives. + +## 7. Depth & Surface + +The frontend uses a mixed strategy: card borders plus the existing shadcn card shadow, with tonal changes for muted controls. New preference sections should compose the existing `Card` primitive rather than introduce custom shadows or radii. + +## 8. Accessibility Constraints & Accepted Debt + +### Constraints + +- Target WCAG 2.2 AA. +- Every interactive control must be keyboard reachable with a visible focus state. +- Dependent notification controls must expose their disabled state through the actual control, not only visual opacity. +- The form must reflow to one readable column at mobile widths without horizontal scrolling. + +### Accepted Debt + +| Item | Location | Why accepted | Owner / Exit | +|------|----------|--------------|--------------| +| Existing success color uses `text-emerald-500` | Account forms | Preserve established feedback styling in this focused redesign | Consolidate account feedback tokens in a future account UI pass |