The table becomes a full oval racetrack with a center deck and pot plaque, perimeter seats as compact pills with stack-first readouts that flash on change, betting actions mounted on the felt near the viewer, your own cards dealt onto the bottom rail at community-card size, directional popups, and gated start and waiting-room polish. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
197 lines
15 KiB
Markdown
197 lines
15 KiB
Markdown
# 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.
|
||
|
||
### Poker table surface
|
||
|
||
- **Purpose**: The poker table is a diegetic game surface. The velvet felt carries the board, the dealer station, opponent arc, and the player's action console without floating control overlays.
|
||
- **Material**: Preserve the existing velvet felt gradient, dark inset rim, and restrained gold trim. The action console is a darker inset panel with the same trim language, while chips use dark, clay, and gold-trim variants for action hierarchy.
|
||
- **Primitives**: `poker-felt-table`, `poker-dealer-station`, `poker-seat-arc-*`, `poker-action-console`, `poker-hand-placard`, and `poker-chip`.
|
||
- **States**: betting and waiting console states, acting-seat highlight, folded and eliminated players, showdown result, game-complete placement, open and occupied waiting seats, and reduced-motion deal presentation.
|
||
- **Accessibility**: The cosmetic dealer station is labelled as a station and is not included in player or seat data. Action controls remain native buttons and inputs with visible focus states. Card labels continue to describe face-up and face-down cards.
|
||
- **Motion**: Cards originate visually at the dealer shoe using transform and opacity with a 60ms stagger. Reduced motion removes the deal animation while retaining static card tilts and highlight states.
|
||
- **Layout**: The felt is a flat-bottom semicircle. Opponents occupy count-aware upper arc slots, the dealer is top-center, community cards sit in the middle, and the user's console is pinned to the flat bottom edge. Fullscreen increases felt depth without moving the console out of the viewport canvas.
|
||
|
||
### Locker inventory surface
|
||
|
||
- **Purpose**: The authenticated locker is a Polaris operations surface: a dense, readable inventory rather than a literal game replica. The grid is the focal region and selection context is kept adjacent to it.
|
||
- **Palette**: Use the existing semantic neutral tokens: `bg-background` for the page, `bg-card`/`bg-muted` for framed regions, `border-border` for structure, `text-foreground` and `text-muted-foreground` for hierarchy, and `bg-primary`/`ring-ring` for active selection and primary actions. Amber utility accents are reserved for existing equipment/skin meaning; they do not become a second surface palette.
|
||
- **Typography**: Keep Geist for interface copy and Geist Mono with `tabular-nums` for coordinates, counts, dimensions, and other inventory metadata. Compact labels use the existing `text-xs` level, never ad-hoc display sizes.
|
||
- **Primitives**:
|
||
- **`locker-shell`**: one responsive page region with a compact control band and a single-column fallback below `xl`.
|
||
- **`inventory-frame`**: a strong rectangular border around the existing two-dimensional grid. The grid may scroll only inside this bounded region when its footprint exceeds the available inline size; the page itself must not gain a horizontal scrollbar.
|
||
- **`selection-rail`**: selected-item context and actions sit beside the inventory at `xl` and later, then become an inline section below the grid at narrower widths. It remains readable when no item is selected.
|
||
- **`metadata-strip`**: a compact cluster for occupancy, dimensions, and drag/drop guidance, using 4px spacing and semantic muted text.
|
||
- **`wardrobe-slot-board`**: a body-ordered rectangular board: head/face spans the top, torso and pack occupy the middle, and weapons/attachments plus sidearm finish the lower row. The primary weapon owns an indented attachment subgroup for optic, muzzle, and bipod slots. Each slot is a labeled semantic button with distinct filled and empty states; the board is driven by `WARDROBE_SLOT_LAYOUT` and never relies on a character image as its control surface.
|
||
- **States**: default, hover, focus-visible, selected, search-highlight, valid drop, invalid drop, attachment drop, empty, error, disabled, and reduced-motion. Selected items use a visible semantic ring; placement feedback stays inside the grid cells; empty and error states retain the existing user/manager-specific copy.
|
||
- **Accessibility**: Tabs remain native shadcn tab semantics. Every icon-only button has an accessible label, every meaningful thumbnail keeps descriptive alt text, draggable items retain dnd-kit keyboard attributes, and all actions keep visible `focus-visible` rings. The responsive rail must not reorder focus away from the selected item context.
|
||
- **Motion**: Preserve the existing dnd-kit activation threshold and absolute-position/ResizeObserver mechanics. Interaction polish is limited to existing shadcn color transitions, transform/opacity drag feedback, and the existing search highlight; `prefers-reduced-motion` disables highlight animation and nonessential transitions. No decorative looping motion is introduced.
|
||
- **Responsive behavior**: At 375px the shell becomes one readable column with no viewport-level horizontal overflow. Only the `inventory-frame` may expose bounded two-dimensional scrolling when required by the configured grid; the selection rail follows the grid inline, while the tab/search control cluster wraps before it can overflow. The inventory and selection rail use the side-by-side layout only at `xl` and above so the grid remains dominant and rail labels remain readable. The wardrobe slot board keeps its body order at `lg` and collapses regions to one readable column below that threshold.
|
||
|
||
### Mission card
|
||
|
||
- **Structure**: linked `Item` with `ItemHeader`, `ItemMedia`, `ItemTitle`, `ItemContent`, and `ItemDescription` primitives.
|
||
- **Variants**: `default` uses the neutral outline surface; `image` adds an optional cover image with a translucent gradient overlay. The contextual default is `image` when a cover image URL is available.
|
||
- **Metadata**: compact cards show operation/status, date/time, map, player slots, and campaign; full cards additionally show estimated duration.
|
||
- **States**: default, image, hover, focus-visible, and reduced-content/full-detail display.
|
||
- **Accessibility**: the entire card is one keyboard-reachable link; decorative cover images use empty alt text and are hidden from assistive technology.
|
||
- **Motion**: existing 200ms scale, border, and foreground transitions communicate the linked-card affordance; no decorative animation.
|
||
- **Layout**: responsive metadata wraps on narrow screens while the image layer stays absolutely positioned behind content.
|
||
|
||
### 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.
|
||
|
||
### Transfer workflow surface
|
||
|
||
- **Structure**: the account `AssignmentCard` owns current-assignment context and opens the
|
||
`RequestTransferDialog`; `/transfers` uses a `stack` of `Card` sections containing request,
|
||
approval, and escalated-resolution cards.
|
||
- **Variants**: request cards, leader approval cards, and superuser resolution cards share the
|
||
neutral card surface; status meaning is carried by the existing `Badge` variants.
|
||
- **States**: loading, empty, pending, approved, rejected, appealed, escalated, completed,
|
||
cancelled, denied, error, and success feedback.
|
||
- **Accessibility**: every dialog has a visible title and description, every textarea has a label,
|
||
rejection requires a non-empty reason, and destructive actions remain keyboard reachable with
|
||
the existing focus ring.
|
||
- **Motion**: use the existing shadcn dialog, button, and toast transitions only; no decorative
|
||
section animation. Async buttons expose their pending state and disable competing actions.
|
||
- **Layout**: the transfer list is a single document scroll region inside the authenticated shell;
|
||
cards use an intrinsic one-column-to-two-column grid and remain readable at narrow widths.
|
||
|
||
### Helpdesk ticket controls
|
||
|
||
- **Structure**: ticket list and detail surfaces use the existing `Item`, `Badge`, `Button`, and
|
||
`Dialog` primitives. The author-only edit dialog contains labeled title, category, priority, and
|
||
description controls; vote state uses one `Button` with a visible count.
|
||
- **States**: edit controls expose default, pending, success, and error states. Vote controls expose
|
||
unvoted, voted (`aria-pressed`), pending, and disabled states; canceled tickets disable voting.
|
||
- **Accessibility**: edit dialogs have a title and description, every field has an associated label,
|
||
and vote buttons announce both the action and count without relying on iconography.
|
||
- **Motion**: use existing shadcn dialog and button transitions only.
|
||
- **Layout**: controls wrap on narrow screens and never turn a card-wide navigation link into a
|
||
nested interactive target.
|
||
|
||
## 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 |
|