Co-Study4Grid / frontend /src /styles /tokens.css
github-actions[bot]
Deploy 7688ef1
13d4e44
Raw
History Blame Contribute Delete
9.93 kB
/*
Copyright (c) 2025-2026, RTE (https://www.rte-france.com)
This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
you can obtain one at http://mozilla.org/MPL/2.0/.
SPDX-License-Identifier: MPL-2.0
Design tokens — single source of truth for color, spacing, type, radius.
Why this file exists: docs/proposals/ui-design-critique.md flagged 273
hex literals across 24 files (three competing palettes: Flat UI,
Bootstrap, Tailwind). All blues consolidate onto the Tailwind blue
ramp (closest fit to existing values — #1e40af and #dbeafe are
already on it).
How to consume:
- Inside .css files: color: var(--color-brand);
- Inside inline styles: color: 'var(--color-brand)'
(or import { colors } from 'styles/tokens')
How to extend: add a NEW token here before introducing a new hex
in a component. The check_code_quality.py gate ratchets down the
remaining hex-literal count after each migration.
*/
:root {
/* ----- Color: surfaces ----- */
--color-surface: #ffffff;
--color-surface-muted: #f8f9fa;
--color-surface-raised: #fcfcfc;
/* Backdrop behind the pypowsybl NAD/SLD diagram. White in light
mode; flipped dark by [data-theme="dark"] below. The diagram SVG
itself is transparent, so this token IS the diagram background. */
--color-diagram-surface: #ffffff;
/* Semi-opaque veil painted over the diagram while a new one loads
(dims the stale diagram). Translucent so the old SVG shows through. */
--color-diagram-veil: rgba(255, 255, 255, 0.85);
/* ----- Color: borders ----- */
--color-border: #cccccc;
--color-border-subtle: #eeeeee;
--color-border-strong: #999999;
/* ----- Color: text ----- */
--color-text-primary: #1f2937;
--color-text-secondary: #555555;
--color-text-tertiary: #888888;
--color-text-on-brand: #ffffff;
/* Dark ink for text sitting on a bright, solid fill (warning yellow,
notice badge, etc.). Stays dark in BOTH themes because those fills
are bright in both — unlike the *-text tokens which are tuned for
the matching *-soft background and flip light in dark mode. */
--color-text-on-bright: #1f2937;
/* ----- Color: brand (Tailwind blue ramp) ----- */
--color-brand: #1e40af; /* blue-800 — primary links + active CTAs */
--color-brand-strong: #1d4ed8; /* blue-700 — hover / pressed */
--color-brand-soft: #dbeafe; /* blue-100 — selection bg, hint pills */
--color-brand-mid: #3b82f6; /* blue-500 — fills (slider, range bar) */
/* ----- Color: state — success ----- */
--color-success: #28a745;
--color-success-strong: #2e7d32;
--color-success-soft: #d1fae5;
--color-success-text: #065f46;
/* ----- Color: state — warning ----- */
--color-warning: #ffc107;
--color-warning-strong: #f0ad4e;
--color-warning-soft: #fff3cd;
--color-warning-border: #ffeeba;
--color-warning-text: #856404;
/* ----- Color: state — danger ----- */
--color-danger: #dc3545;
--color-danger-strong: #b91c1c;
--color-danger-soft: #f8d7da;
--color-danger-text: #c62828;
/* ----- Color: accent + chrome ----- */
--color-accent: #8e44ad; /* save/secondary action */
--color-accent-soft: #f3e8ff; /* PST tap-edit row bg */
--color-accent-border: #c084fc; /* PST tap-edit row border */
--color-accent-text: #6b21a8; /* PST tap-edit row text */
--color-chrome: #2c3e50; /* header / dark backgrounds */
--color-chrome-soft: #7f8c8d; /* settings cog, neutral chrome */
--color-disabled: #95a5a6; /* disabled buttons */
/* ----- Color: info (cyan — distinct from brand blue) -----
Used by curtailment edit rows and metric badges where the
intent is "informational" rather than "primary action". */
--color-info: #0284c7;
--color-info-soft: #e0f2fe;
--color-info-border: #7dd3fc;
--color-info-text: #075985;
/* ----- Spacing (4 / 8 grid) ----- */
--space-0: 0;
--space-half: 2px; /* tight cases (badge padding, inline gaps) */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-7: 32px;
/* ----- Type sizes ----- */
--text-xs: 11px;
--text-sm: 12px;
--text-md: 14px;
--text-lg: 16px;
--text-xl: 20px;
--text-xxl: 24px;
/* ----- Radii ----- */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
/* ----- Diagram-signal colors (domain-specific, not semantic state) -----
Used by NAD/SLD highlight CSS in App.css. These are visual signals
for grid concepts (contingency, action target, overload, breaker)
and intentionally bright/saturated to read on top of the diagram. */
--signal-overload: #ff8c00;
--signal-contingency: #ffe033;
--signal-action-target: #ff4081;
--signal-action-target-strong: #ec407a;
--signal-action-target-darker: #ad1457;
--signal-action-target-soft: #fce4ec;
--signal-breaker: #ce93d8;
--signal-delta-positive: #ff9800;
--signal-delta-negative: #2196f3;
--signal-delta-neutral: #999999;
/* ----- SLD interactive topology-edit highlight -----
The interactive SLD-edit feature (useSldTopologyEdit + SldEditPanel)
stages switch toggles + injection (load / generator) active-power
retunes in the frontend and visually marks the pending element.
Distinct hues from action / contingency / overload so a toggled
switch on an overloaded line still reads as both. */
--signal-edit-open: #d81b60;
--signal-edit-closed: #1976d2;
--signal-edit-injection: #00897b;
/* ----- Action-overview pin palette -----
Severity buckets for Remedial Action overview pins
(utils/svg/actionPin{Data,Render}.ts + ActionOverviewDiagram.tsx).
Three triplets per bucket: base, dimmed (rejected / filtered-out),
highlighted (selected on hover). The TS mirror in tokens.ts is the
runtime source of truth because pin fills are written to raw SVG
`fill="…"` attributes via setAttribute, which doesn't reliably
resolve var() across older browsers. CSS variables here are kept
in sync for any future CSS-only consumers. */
--pin-green: #28a745;
--pin-orange: #f0ad4e;
--pin-red: #dc3545;
--pin-grey: #9ca3af;
--pin-green-dimmed: #a3c9ab;
--pin-orange-dimmed: #dcd0b8;
--pin-red-dimmed: #d4a5ab;
--pin-grey-dimmed: #c8cdd2;
--pin-green-highlighted: #1e9e3a;
--pin-orange-highlighted: #e89e20;
--pin-red-highlighted: #c82333;
--pin-grey-highlighted: #7b8a96;
--pin-glyph-bg: #ffffff; /* white inner circle behind label */
--pin-glyph-text: #1f2937; /* label text (= text-primary) */
--pin-stroke-neutral: #6b7280; /* unsimulated pin outline */
--pin-gold: #eab308; /* selected-pin star fill + outline */
--pin-gold-dark: #a16207; /* selected-pin star stroke */
--pin-cross-fill: #ef4444; /* rejected-pin cross fill */
--pin-cross-stroke: #b91c1c; /* rejected-pin cross stroke */
/* Vite template carryover — visible only during the first paint
before body { background-color: var(--color-surface) } takes over.
Kept as a token so the dark-mode initial-paint color has a name. */
--color-surface-dark: #242424;
}
/* ===== Dark theme =====
Engaged via `<html data-theme="dark">`, set by useTheme + the
pre-mount script in index.html. Only chrome tokens flip — domain
signals (overload / contingency / action-target / pin palette)
stay identical because pypowsybl SVGs render on a light backdrop
and the colors encode semantic state. The diagram <svg> container
keeps `colors.surface` here = light grey-blue so flow arrows /
delta colors keep their meaning. */
[data-theme="dark"] {
/* Surfaces — app shell is dark; the diagram backdrop goes near-black
(see --color-diagram-surface) so voltage-coded lines pop. */
--color-surface: #1b1f24; /* base app background */
--color-surface-muted: #232830; /* sidebar / cards */
--color-surface-raised: #2a3038; /* hover / raised tiles */
--color-diagram-surface: #0c0f13; /* near-black diagram backdrop */
--color-diagram-veil: rgba(12, 15, 19, 0.78);
/* Borders */
--color-border: #3a4049;
--color-border-subtle: #2d333b;
--color-border-strong: #555c66;
/* Text — high-contrast on the dark surfaces above. */
--color-text-primary: #e6e8eb;
--color-text-secondary: #b5bac1;
--color-text-tertiary: #8b9098;
--color-text-on-brand: #ffffff;
/* Brand — lift the Tailwind blue one step so it stays vivid on dark. */
--color-brand: #3b82f6; /* blue-500 — primary CTAs */
--color-brand-strong: #60a5fa; /* blue-400 — hover */
--color-brand-soft: #1e3a8a; /* blue-900 — selection bg */
--color-brand-mid: #60a5fa; /* slider / range fills */
/* Success / Warning / Danger / Info — keep hue, deepen the soft
backgrounds so badge text stays readable on dark cards. */
--color-success: #22c55e;
--color-success-strong: #16a34a;
--color-success-soft: #14532d;
--color-success-text: #bbf7d0;
--color-warning: #facc15;
--color-warning-strong: #eab308;
--color-warning-soft: #422006;
--color-warning-border: #713f12;
--color-warning-text: #fde68a;
--color-danger: #ef4444;
--color-danger-strong: #dc2626;
--color-danger-soft: #4c1d1d;
--color-danger-text: #fecaca;
--color-accent: #c084fc; /* save/secondary action */
--color-accent-soft: #3b1f5c;
--color-accent-border: #7e22ce;
--color-accent-text: #e9d5ff;
--color-chrome: #0f1419; /* header background */
--color-chrome-soft: #4a5159; /* settings cog */
--color-disabled: #4b5563;
--color-info: #38bdf8;
--color-info-soft: #0c3445;
--color-info-border: #075985;
--color-info-text: #bae6fd;
}