diff --git a/.ai/docs/design-tokens.md b/.ai/docs/design-tokens.md index 931d231..b302fcb 100644 --- a/.ai/docs/design-tokens.md +++ b/.ai/docs/design-tokens.md @@ -10,8 +10,9 @@ Tokens are the single source of truth for shared visual values used by Moonbase ## Source of Truth -- Core token definitions are stored in `app/assets/css/tokens.css`. -- Tailwind token mapping and scale extensions are configured in `tailwind.config.ts`. +- The design source is the **MoonBase Studio Design System** (claude.ai artifact, direction "Orbit", `tokens.json` v2). It is shared with the Moonbase Commander 7" screen (`electronics/moonbase-commander/docs/ekran-7.md`, section 2). Change values there first, then mirror them here. +- Core token definitions are stored in `app/assets/css/tokens.css` (one dark theme; `accent` = signal, `surface-container` = panel, `surface-container-high` = raised, `line`). +- Tailwind token mapping and scale extensions are configured in `tailwind.config.ts` (Space Grotesk / Space Mono / Lalezar, Orbit type scale, radius 0, size tokens `bar`, `control`, `row`, `bracket`, `key`). - Extra Tailwind behavior can be added in `tailwind/plugins/*` (for example root font sizing). --- diff --git a/.ai/docs/ui-design-rules.md b/.ai/docs/ui-design-rules.md index 15a3385..50c2034 100644 --- a/.ai/docs/ui-design-rules.md +++ b/.ai/docs/ui-design-rules.md @@ -30,7 +30,7 @@ Inconsistent UI is a defect. Visual and behavioral patterns must be uniform acro - `hover` — visible, subtle feedback - `focus` — clearly visible focus ring (never removed, only styled) - `active` / `pressed` — immediate visual response - - `disabled` — reduced opacity, no pointer events, cursor `not-allowed` + - `disabled` — `text-on-surface-dim`, dashed border, no pointer events, cursor `not-allowed` (no opacity) - Do not mix token-based values with hardcoded values within the same component. --- @@ -54,29 +54,30 @@ Tailwind is the **only** permitted styling system. All visual output must be exp - Do not use default Tailwind spacing numerics (e.g. `p-4`, `gap-2`) — they are overridden by the project scale. - `1rem = 10px` in this project due to the `root-font-size` plugin. -### Typography +### Typography (Orbit) -- Use the semantic font size scale: `text-heading-x-huge`, `text-heading-x-lg`, `text-heading-lg`, `text-heading-md`, `text-body-lg`, `text-body-md`, `text-body-sm`, `text-body-x-sm`. -- Font families: `font-roboto` for all UI text; `font-arlon` for brand/logo elements only. -- Font weights: `font-normal` (400), `font-medium` (500), `font-semibold` (600). -- Letter spacing: use `tracking-x-sm` through `tracking-xx-lg` from the defined scale. +- Families: `font-sans` (Space Grotesk) for all UI text; `font-mono` (Space Mono) for labels, units, group headings and state words, always `uppercase`; `font-brand` (Lalezar) for the MoonBase wordmark only. +- Weights: `font-light` (300) for sizes ≥ 20px (titles, large numbers), `font-normal` (400) for text, `font-bold` (700) only for state values (`text-state`). Do not use 500 or 600. +- Size scale: `text-display` (96), `text-numeric-xl` (120), `text-numeric-lg` (48), `text-title` (28), `text-numeric-md` (20), `text-body-lg` (18), `text-body-md` (16), `text-body-sm` (14), `text-body-x-sm` (12, the minimum), `text-state` (14/700), `text-label` (12 mono, 0.14em), `text-label-lg` (14 mono, 0.12em), `text-brand-logo` (28 Lalezar). +- Numbers always get `tabular-nums`. +- The inspector uses `inspectorTypography` (`title`, `valueLarge`, `value`, `body`, `label`) from `app/utils/inspector-typography.utils.ts`. Those styles do not include color. - Never hardcode `font-size`, `line-height`, or `font-family` values. -- The layer properties inspector uses the Figma Special/Standard scale instead of the Roboto body scale: `font-lalezar` with `text-special-high` (48px), `text-special-medium` (40px), `text-special-small` (36px), and `font-inter` with `text-standard-high` (24px), `text-standard-medium` (20px), `text-standard-small` (16px). Prefer `inspectorTypography` from `app/utils/inspector-typography.utils.ts`. Those styles do not include color. The rest of the studio chrome keeps `text-body-*` and `font-roboto`. -### Color Usage +### Color Usage (Orbit) -- Use semantic color tokens only. Never use Tailwind's default palette (e.g. `bg-blue-500`). -- Surface colors: `bg-surface`, `bg-surface-container`, `bg-surface-inverted`. -- Text colors: `text-on-surface`, `text-on-surface-dim`, `text-on-surface-inverted`. -- Accent: `bg-accent`, `text-accent`, `bg-accent-dim`, `text-accent-dim`. -- Semantic: `bg-info`, `bg-warning`, `bg-error`, `bg-success` (and their `-container` variants). -- Opacity modifiers are allowed: `bg-accent/80`, `text-error/30`. -- Theme is applied via `theme-light`, `theme-dark`, or `theme-blue` on `` — do not override theme-sensitive tokens per component. +- Use semantic color tokens only. Never use Tailwind's default palette (e.g. `bg-blue-500`) or hex values. +- One dark theme. `bg-surface` is the page; a block is `border border-line`, not a filled panel. `bg-surface-container` (panel) only for overlays (menus, dialogs, popovers) and hardware keys. `bg-surface-container-high` (raised) for hover rows and unlit segments. +- Text: `text-on-surface`; labels, units and disabled: `text-on-surface-dim`; on green fills: `text-on-accent`. +- `accent` is the signal green: live, active, selected, focus, corner brackets. It is a stroke, dot, segment or number — a fill only for “Start / Resume” and the on-air key. Hover/pressed: `accent-dim`. +- Semantic: `warning`, `error`, `info` (`success` equals `accent`). Every state also carries a word or icon. +- Element categories (Studio): `category-layout`, `category-interactive` (`category-interactive-fill` for hover). +- Avoid opacity modifiers and transparency; disabled is `text-on-surface-dim` plus a dashed border, not `opacity-50`. +- Active blocks get corner brackets: `BaseFrame active` or `BaseFrameBrackets`. -### Border Radius +### Border Radius (Orbit) -- Use the defined scale: `rounded-none`, `rounded-x-sm`, `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-full`. -- Do not use Tailwind's default radius values (e.g. `rounded`, `rounded-2xl`). +- No rounding: every radius token is 0. `rounded-full` only for the status dot (`BaseStatusBadge`). +- No shadows, gradients, blur or glass. The boot screen is the only exception. ### Transitions diff --git a/app/assets/css/tokens.css b/app/assets/css/tokens.css index 91abb78..9351ed0 100644 --- a/app/assets/css/tokens.css +++ b/app/assets/css/tokens.css @@ -1,180 +1,45 @@ +/* + * MoonBase — Orbit (design system "MoonBase Studio Design System", tokens.json v2). + * One dark theme. Channels are "r g b" so Tailwind can add alpha, but Orbit + * avoids transparency: prefer the solid tokens below. + * Token → design system name: + * surface → surface, surface-container → panel, surface-container-high → raised, + * line → line, on-surface → on-surface, on-surface-dim → on-surface-dim, + * accent → signal, accent-dim → signal-dim, on-accent → on-signal. + */ :root, -.theme-light { - /* Surfaces */ - --color-surface: 242 242 242; - --color-surface-container: 233 233 233; - --color-surface-inverted: 0 0 0; - - /* Content / Text */ - --color-on-surface: 5 3 21; - --color-on-surface-dim: 90 90 90; - --color-on-surface-inverted: 255 255 255; - - /* Accent */ - --color-accent: 0 114 245; - --color-accent-dim: 121 180 239; - - /* Panel categories */ - --color-category-layout: 0 201 228; - --color-category-interactive: 255 0 204; - - /* Semantic */ - --color-info: 82 128 234; - --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; -} - -.theme-dark { - /* Surfaces */ - --color-surface: 11 13 17; - --color-surface-container: 20 24 29; - --color-surface-inverted: 231 231 231; - - /* Content / Text */ - --color-on-surface: 255 255 255; - --color-on-surface-dim: 179 179 179; - --color-on-surface-inverted: 0 0 0; - - /* Accent */ - --color-accent: 59 130 246; - --color-accent-dim: 35 78 148; - - /* Panel categories */ - --color-category-layout: 0 201 228; - --color-category-interactive: 255 0 204; - - /* Semantic */ - --color-info: 82 128 234; - --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; -} - -.theme-blue { - /* Surfaces */ - --color-surface: 14 19 27; - --color-surface-container: 29 33 41; - --color-surface-inverted: 231 231 232; - - /* Content / Text */ - --color-on-surface: 255 255 255; - --color-on-surface-dim: 179 179 179; - --color-on-surface-inverted: 0 0 0; - - /* Accent */ - --color-accent: 0 201 228; - --color-accent-dim: 0 121 137; - - /* Panel categories */ - --color-category-layout: 0 201 228; - --color-category-interactive: 255 0 204; - - /* Semantic */ - --color-info: 82 128 234; - --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; -} - -html[data-theme='light'] { - /* Surfaces */ - --color-surface: 242 242 242; - --color-surface-container: 233 233 233; - --color-surface-inverted: 0 0 0; - - /* Content / Text */ - --color-on-surface: 5 3 21; - --color-on-surface-dim: 90 90 90; - --color-on-surface-inverted: 255 255 255; - - /* Accent */ - --color-accent: 0 114 245; - --color-accent-dim: 121 180 239; - - /* Panel categories */ - --color-category-layout: 0 201 228; - --color-category-interactive: 255 0 204; - - /* Semantic */ - --color-info: 82 128 234; - --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; -} - +.theme-dark, html[data-theme='dark'] { /* Surfaces */ - --color-surface: 11 13 17; - --color-surface-container: 20 24 29; - --color-surface-inverted: 231 231 231; - - /* Content / Text */ - --color-on-surface: 255 255 255; - --color-on-surface-dim: 179 179 179; - --color-on-surface-inverted: 0 0 0; - - /* Accent */ - --color-accent: 59 130 246; - --color-accent-dim: 35 78 148; - - /* Panel categories */ - --color-category-layout: 0 201 228; - --color-category-interactive: 255 0 204; - - /* Semantic */ - --color-info: 82 128 234; - --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; -} - -html[data-theme='blue'] { - /* Surfaces */ - --color-surface: 14 19 27; - --color-surface-container: 29 33 41; - --color-surface-inverted: 231 231 232; + --color-surface: 5 0 4; + --color-surface-container: 18 18 18; + --color-surface-container-high: 28 28 28; + --color-surface-inverted: 255 255 255; + --color-line: 42 42 42; /* Content / Text */ --color-on-surface: 255 255 255; - --color-on-surface-dim: 179 179 179; - --color-on-surface-inverted: 0 0 0; + --color-on-surface-dim: 138 138 138; + --color-on-surface-inverted: 5 0 4; - /* Accent */ - --color-accent: 0 201 228; - --color-accent-dim: 0 121 137; + /* Signal (accent) */ + --color-accent: 34 255 134; + --color-accent-dim: 24 184 95; + --color-on-accent: 5 0 4; - /* Panel categories */ - --color-category-layout: 0 201 228; + /* Element categories (Studio only) */ + --color-category-layout: 0 229 255; --color-category-interactive: 255 0 204; + --color-category-interactive-fill: 55 0 44; /* Semantic */ --color-info: 82 128 234; --color-info-container: 82 128 234; - --color-warning: 255 106 0; - --color-warning-container: 255 106 0; - --color-error: 220 38 38; - --color-error-container: 220 38 38; - --color-success: 132 204 22; - --color-success-container: 132 204 22; + --color-warning: 230 161 92; + --color-warning-container: 230 161 92; + --color-error: 232 93 76; + --color-error-container: 232 93 76; + --color-success: 34 255 134; + --color-success-container: 34 255 134; + --color-on-status: 5 0 4; } diff --git a/app/components/base/base-color-swatch/BaseColorSwatch.vue b/app/components/base/base-color-swatch/BaseColorSwatch.vue index 6c4ed27..d0fcea4 100644 --- a/app/components/base/base-color-swatch/BaseColorSwatch.vue +++ b/app/components/base/base-color-swatch/BaseColorSwatch.vue @@ -32,14 +32,14 @@ function onPickerChange(event: Event) {
{{ label }}