Repository navigation
3.4 Styling and Theming
Relevant source files
The following files were used as context for generating this wiki page:
The styling and theming system of VariantScope provides a responsive, accessible design system built on CSS custom properties (design tokens), modular layout rules, component styles, runtime dark mode toggling, and automated WCAG AA contrast validation.
Sources: src/styles/tokens.css:1-58, src/styles/base.css:1-94, src/styles/components.css:1-345, src/ui/theme.js:1-29, tests/unit/contrast.test.js:1-81
The design token architecture (src/styles/tokens.css) defines global variables for colors, typography, layout radii, shadows, and semantic variant pills. Theme-switching is handled natively through CSS selector scoping ([data-theme='dark']), altering variables dynamically without mutating class names across components.
-
Surfaces and Backgrounds:
--bg,--surface,--surface-2, and--viewer-bgdefine the background depth hierarchy for cards, panels, and 3D viewers. -
Typography:
--textand--text-mutedmaintain readable contrast tiers across light and dark backgrounds. -
Semantic Variants:
--accent(pathogenic),--benign, and--vusprovide clinical classification colours. -
Pills and Banners: Tinted backgrounds paired with dark/light text tokens (
--pill-pathogenic-bg,--pill-pathogenic-text,--banner-info-bg, etc.) guarantee text contrast exceeds WCAG AA thresholds.
:root {
--bg: #f4f7fa;
--surface: #ffffff;
--surface-2: #eaf0f5;
--text: #0f1b2d;
--text-muted: #4b5b70;
--border: #d5dee8;
--primary: #0b1f3a;
--accent-ui: #12486b;
--secondary: #14b8a6;
--accent: #ff6b6b;
--benign: #22c55e;
--vus: #94a3b8;
color-scheme: light;
}Sources: src/styles/tokens.css:1-58
The base stylesheet (src/styles/base.css) establishes global box-sizing resets, typography scaling, root flex layout constraints, and accessibility utilities.
-
Box Sizing: Enforces
box-sizing: border-boxglobally on all elements and pseudo-elements. -
Body Frame: Configures a minimum height of
100vh, flex column direction, and tabular numeric font variants (font-variant-numeric: tabular-nums) to align data tables and numeric columns cleanly. -
Accessibility Enhancements:
-
[hidden]attribute enforcement withdisplay: none !importantthat overrides conflicting layout classessrc/base.css:19-22. - Focus visibility rings using
:focus-visiblestyled with--secondaryoutline and offsetsrc/base.css:51-54. - Screen-reader utilities (
.visually-hiddenand.skip-link) for keyboard navigationsrc/base.css:56-77. - Reduced-motion query media handling that strips transitions and animations when
prefers-reduced-motion: reduceis activesrc/base.css:89-94.
-
Sources: src/styles/base.css:1-94
The component stylesheet (src/styles/components.css) encapsulates modular UI elements including top-bar navigation, search inputs, interactive filter chips, buttons, card grids, stat cards, and dynamic panel skeletons.
-
Top Bar and Search: Flexbox-based header
.topbarfeaturing a navy-to-teal gradient, responsive brand button (.brand-button), and a fluid search input container (.search) src/styles/components.css:4-42. -
Interactive Chips and Buttons: Styled
.chipand.buttonelements with hover state transitions and[aria-pressed='true']states for filter toggles src/styles/components.css:87-150. -
Layout Grids:
.layout-gridestablishes a responsive two-column layout (3fr / 2fr) for primary visualizations and sidebar widgets, wrapping gracefully on smaller viewports src/styles/components.css:222-228. -
Panel Skeletons and Shimmer: Asynchronous loading states use
.panel-skeletonwith animated linear gradient.shimmerkeyframes simulating data fetching latencies src/styles/components.css:298-323.
Sources: src/styles/components.css:1-345
Dark mode switching is managed by src/ui/theme.js, which synchronizes user preferences between DOM attributes, localStorage (via cache helpers), and system media queries.
-
Initialization (
initTheme): Reads any saved preference fromcacheGet('theme'). If none exists, evaluateswindow.matchMedia('(prefers-color-scheme: dark)')src/ui/theme.js:12-16. -
Application (
apply): Setsdocument.documentElement.dataset.theme = themeand dispatches a custom window eventvs:themecarrying the active theme name. This allows canvases (3D protein viewers and Chart.js lollipops) to redraw themselves with updated color variables src/ui/theme.js:5-9. -
Toggle Action (
toggleTheme): Flips between'dark'and'light'and persists the choice viacacheSet('theme', next, null)src/ui/theme.js:19-23.
---
title: Theme Initialization and Event Flow
---
graph TD
A["initTheme(button)"] --> B["initialTheme()"]
B --> C{"cacheGet('theme')?"}
C -- "Yes" --> D["Use Saved Theme"]
C -- "No" --> E["matchMedia('(prefers-color-scheme: dark)')"]
D --> F["apply(theme)"]
E --> F
F --> G["document.documentElement.dataset.theme = theme"]
F --> H["window.dispatchEvent(vs:theme)"]
H --> I["Canvases / Charts Redraw"]
J["User Clicks Button"] --> K["toggleTheme()"]
K --> F
K --> L["cacheSet('theme', next, null)"]
style subZ fill:none,stroke:none
Sources: src/ui/theme.js:1-29 Sources: src/ui/theme.js:1-29
To guarantee WCAG AA accessibility compliance, tests/unit/contrast.test.js parses the CSS token files directly, computes relative luminance and contrast ratios, and asserts that all text/background pairs meet or exceed the 4.5:1 minimum threshold for both light and dark themes.
-
Token Parsing: Reads src/styles/tokens.css and extracts hex colour declarations for
:rootand[data-theme='dark']tests/unit/contrast.test.js:13-21. - Luminance Calculation: Implements the WCAG relative luminance formula converting 8-bit RGB channels to linear space tests/unit/contrast.test.js:24-30.
-
Contrast Evaluation: Validates UI pairs (such as
textonbg,text-mutedonsurface, pill text/background combinations, and warning/error banner pairings) against the 4.5:1 ratio constraint tests/unit/contrast.test.js:38-63. -
Header & Chip Verification: Tests white text readability across the navy-to-teal linear gradient in
components.cssand ensures active chips maintain required contrast in both modes tests/unit/contrast.test.js:65-81.
---
title: Contrast Testing Pipeline
---
graph TD
A["src/styles/tokens.css"] --> B["tokens(selector) Parser"]
C["src/styles/components.css"] --> D["Header Gradient Extractor"]
B --> E["Light and Dark Token Objects"]
E --> F["PAIRS Matrix Iteration"]
F --> G["luminance(hex) Calculation"]
G --> H["contrast(a, b) Ratio Computation"]
H --> I["Vitest Expectation: >= 4.5:1"]
D --> H
style subZ fill:none,stroke:none
Sources: tests/unit/contrast.test.js:1-81 Sources: tests/unit/contrast.test.js:1-81
Content imported from DeepWiki.