mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Implement M1.5 visual design foundation: tokens, IBM Plex, theme toggle, chart themes
This commit is contained in:
+39
-2
@@ -1,5 +1,26 @@
|
||||
@import './tokens.css';
|
||||
|
||||
/*
|
||||
* IBM Plex, self-hosted via @fontsource — offline/PWA safe, never a CDN
|
||||
* (docs/architecture/09 §3.1). Sans: 400 body, 600 emphasis/headings, 300 for
|
||||
* large display only. Mono: 400 editor/code, 500 for emphasis. Keep weights
|
||||
* minimal — add one only when a surface needs it.
|
||||
*
|
||||
* The family-level import pulls every script subset (latin, latin-ext, cyrillic,
|
||||
* greek, vietnamese). We keep them all: user data — snippet names, dataset
|
||||
* values, chart labels — can be in any language, and Plex must render it rather
|
||||
* than fall back to system-ui. @font-face `unicode-range` means the browser only
|
||||
* *downloads* the subset a glyph needs, so the unused subsets cost nothing at
|
||||
* runtime; they only add to the offline precache, which is the price of working
|
||||
* internationally offline. Vite bundles the woff2 and Workbox precaches them
|
||||
* (woff2 is in the PWA globPatterns — see vite.config.ts).
|
||||
*/
|
||||
@import '@fontsource/ibm-plex-sans/300.css';
|
||||
@import '@fontsource/ibm-plex-sans/400.css';
|
||||
@import '@fontsource/ibm-plex-sans/600.css';
|
||||
@import '@fontsource/ibm-plex-mono/400.css';
|
||||
@import '@fontsource/ibm-plex-mono/500.css';
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -14,8 +35,24 @@ body,
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-text);
|
||||
background: var(--color-bg);
|
||||
/* Plex "requires space to breathe" — keep body line-height generous (doc §3.1). */
|
||||
line-height: 1.45;
|
||||
color: var(--text);
|
||||
background: var(--bg);
|
||||
/* Repaint chrome on theme flip; neutralized under reduced-motion below. */
|
||||
transition:
|
||||
background var(--dur-moderate) var(--ease),
|
||||
color var(--dur-moderate) var(--ease);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared keyboard focus ring — always visible, accessibility is non-negotiable
|
||||
* (doc §4, principle 4). Components may override the offset (e.g. inset on
|
||||
* fields) but should not remove it.
|
||||
*/
|
||||
:where(button, input, select, textarea, a, [tabindex]):focus-visible {
|
||||
outline: 2px solid var(--focus);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
||||
+116
-35
@@ -1,47 +1,128 @@
|
||||
/*
|
||||
* Design tokens. Borrowed in spirit from Syto: a single source of truth for
|
||||
* colors/spacing/typography, themable by overriding the custom properties on
|
||||
* a [data-theme] root. Concrete values are placeholders pending the design pass.
|
||||
* Design tokens — the settled values from docs/architecture/09-visual-design.md
|
||||
* (ported from visual-specimen.html). A single source of truth for type, spacing,
|
||||
* color, shape, and motion, themed by overriding the role tokens on a
|
||||
* `[data-theme]` root. Components consume these tokens ONLY — never raw hexes.
|
||||
*
|
||||
* Inspired by the IBM Design Language / Carbon (structure borrowed, color free);
|
||||
* Carbon is not a dependency — the values are transcribed. See doc §2 for the
|
||||
* deliberate divergences (square chrome, open accent/theming).
|
||||
*/
|
||||
:root {
|
||||
/* Palette */
|
||||
--color-bg: #ffffff;
|
||||
--color-surface: #f7f7fa;
|
||||
--color-border: #e2e2ea;
|
||||
--color-text: #1a1a2e;
|
||||
--color-text-muted: #6b6b80;
|
||||
--color-accent: #3b5bdb;
|
||||
--color-accent-contrast: #ffffff;
|
||||
|
||||
/* Status */
|
||||
--color-success: #2f9e44;
|
||||
--color-error: #e03131;
|
||||
--color-warning: #f08c00;
|
||||
--color-info: #1971c2;
|
||||
|
||||
/* Typography */
|
||||
--font-sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
--font-mono: ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, monospace;
|
||||
/* Type — IBM Plex (self-hosted via @fontsource, wired in main.tsx) */
|
||||
--font-sans: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, monospace;
|
||||
--font-size-base: 14px;
|
||||
|
||||
/* Spacing scale */
|
||||
--space-1: 4px;
|
||||
--space-2: 8px;
|
||||
--space-3: 12px;
|
||||
--space-4: 16px;
|
||||
/* Spacing — 8px base unit (2/4 as sub-steps) */
|
||||
--space-1: 2px;
|
||||
--space-2: 4px;
|
||||
--space-3: 8px;
|
||||
--space-4: 12px;
|
||||
--space-5: 16px;
|
||||
--space-6: 24px;
|
||||
--space-7: 32px;
|
||||
--space-8: 48px;
|
||||
--space-9: 64px;
|
||||
|
||||
/* Shape — square chrome (icons keep their own rounded geometry) */
|
||||
--radius: 0px;
|
||||
--border-width: 1px;
|
||||
|
||||
/* Layout */
|
||||
--header-height: 48px;
|
||||
--radius: 6px;
|
||||
|
||||
/* Motion — productive only; neutralized under prefers-reduced-motion in base.css */
|
||||
--dur-fast: 70ms;
|
||||
--dur-fast-2: 110ms;
|
||||
--dur-moderate: 150ms;
|
||||
--ease: cubic-bezier(0.2, 0, 0.38, 0.9);
|
||||
|
||||
/* Status — color carries meaning only (light defaults; overridden in dark) */
|
||||
--support-error: #da1e28;
|
||||
--support-success: #198038;
|
||||
--support-warning: #f1c21b;
|
||||
--support-info: #0043ce;
|
||||
--on-status: #ffffff;
|
||||
|
||||
/* Focus ring defaults to the accent. */
|
||||
--focus: var(--accent);
|
||||
}
|
||||
|
||||
[data-theme='experimental'] {
|
||||
--color-bg: #16161f;
|
||||
--color-surface: #1f1f2c;
|
||||
--color-border: #2c2c3a;
|
||||
--color-text: #e8e8f0;
|
||||
--color-text-muted: #9a9ab0;
|
||||
--color-accent: #748ffc;
|
||||
--color-accent-contrast: #0b0b12;
|
||||
/* --- Neutral roles: LIGHT theme (Carbon gray ramp) --- */
|
||||
[data-theme='light'] {
|
||||
--bg: #ffffff;
|
||||
--layer-01: #f4f4f4;
|
||||
--layer-02: #e0e0e0;
|
||||
--border: #e0e0e0;
|
||||
--border-strong: #c6c6c6;
|
||||
--text: #161616;
|
||||
--text-secondary: #525252;
|
||||
--text-placeholder: #a8a8a8;
|
||||
}
|
||||
|
||||
/* --- Neutral roles: DARK theme --- */
|
||||
[data-theme='dark'] {
|
||||
--bg: #161616;
|
||||
--layer-01: #262626;
|
||||
--layer-02: #393939;
|
||||
--border: #393939;
|
||||
--border-strong: #525252;
|
||||
--text: #f4f4f4;
|
||||
--text-secondary: #a8a8a8;
|
||||
--text-placeholder: #6f6f6f;
|
||||
--support-error: #fa4d56;
|
||||
--support-success: #42be65;
|
||||
--support-warning: #f1c21b;
|
||||
--support-info: #78a9ff;
|
||||
--on-status: #161616;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accent — the FREE, swappable layer (doc §3.3). Indigo is the default and is
|
||||
* defined on :root / [data-theme='dark'] so `--accent` always resolves even with
|
||||
* no `[data-accent]` attribute. The alternates below are opt-in; an accent
|
||||
* switcher arrives with Settings in M5. Brighter values on the dark canvas keep
|
||||
* accent-on-bg and text-on-accent contrast within AA.
|
||||
*/
|
||||
:root {
|
||||
--accent: #5b54e6;
|
||||
--accent-hover: #4a43d6;
|
||||
--accent-contrast: #ffffff;
|
||||
}
|
||||
[data-theme='dark'] {
|
||||
--accent: #8b85f0;
|
||||
--accent-hover: #a29bf5;
|
||||
--accent-contrast: #161616;
|
||||
}
|
||||
|
||||
[data-accent='teal'] {
|
||||
--accent: #0f766e;
|
||||
--accent-hover: #0c5f59;
|
||||
--accent-contrast: #ffffff;
|
||||
}
|
||||
[data-accent='amber'] {
|
||||
--accent: #b45309;
|
||||
--accent-hover: #92400e;
|
||||
--accent-contrast: #ffffff;
|
||||
}
|
||||
[data-accent='rose'] {
|
||||
--accent: #be123c;
|
||||
--accent-hover: #9f1239;
|
||||
--accent-contrast: #ffffff;
|
||||
}
|
||||
[data-theme='dark'][data-accent='teal'] {
|
||||
--accent: #2dd4bf;
|
||||
--accent-hover: #5eead4;
|
||||
--accent-contrast: #161616;
|
||||
}
|
||||
[data-theme='dark'][data-accent='amber'] {
|
||||
--accent: #fbbf24;
|
||||
--accent-hover: #fcd34d;
|
||||
--accent-contrast: #161616;
|
||||
}
|
||||
[data-theme='dark'][data-accent='rose'] {
|
||||
--accent: #fb7185;
|
||||
--accent-hover: #fda4af;
|
||||
--accent-contrast: #161616;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user