Skip to content

Theming

Every colour the components paint comes from a CSS custom property with a built-in light fallback. Import the default skin once.

import "@azohra/meteo.station/styles.css";

Then wrap your markup in .meteo-root to get the token set. To change the theme, override any token on any ancestor.

.meteo-root carries the tokens and color-scheme. Components outside a .meteo-root still render with the light fallbacks. Inside one, every token can be themed.

The whole sheet ships inside @layer meteo, so your unlayered CSS always takes precedence over it without higher specificity or !important.

Each token is defined once with light-dark(), and the root sets color-scheme: light dark, so the system preference picks the theme without duplicate token blocks. A manual toggle sets data-theme="dark" (or "light") on .meteo-root. That attribute sets color-scheme in one line and overrides the system preference.

<div class="meteo-root" data-theme="dark">…</div>

Remove the attribute (or set any other value) to follow the system again. Both the light and dark values of every token are always declared, so a theme switch is instant and complete, with no partially themed state.

Every class and token the platform ships starts with meteo-, so one grep of your page finds all of them. Names under that prefix fall into three tiers.

  • Bare meteo-* names are the shared skin and the generic parts any capability may use: surfaces, ink, meteo-grid-line, meteo-tick, meteo-cursor, meteo-hit, meteo-microlabel, the freshness badge, and the value and unit spans.
  • meteo-band-* names are speed grading, and they are platform-wide on purpose. Today the station components use meteo-band-0..n, and any future capability that grades wind speeds will use the same tokens.
  • meteo-<family>-* names are scoped to a component family. The meteo-wind-* names appear only where wind is drawn: the dial, the rose, the wind history chart, vanes, and the lull–gust band. Station-level parts use station-scoped names (meteo-station-card-*, meteo-station-table-*, meteo-current-*, meteo-summary-*) because a station is a weather station rather than a wind station. The other families are meteo-air-*, meteo-sample-*, meteo-trend-*, meteo-strip-*, and meteo-sparkline-*. The Meteogram renderer already follows the same pattern (meteo-gram-*, themed on the SVG renderer page), and future capabilities will continue it (meteo-sounding-*).

The default skin paints nothing on the classes below. They exist as stable handles for your own styling, on parts the skin leaves alone. They are versioned API like every other class, and a test checks the list against both the source and the stylesheet.

ClassSeam
meteo-speed / meteo-temperature / meteo-pressureThe reading’s kind, on each text atom’s <data> element
meteo-grid-labelAxis labels in the SVG charts
meteo-tickAxis tick marks in the SVG charts
meteo-wind-gapThe dropout gap group in the wind charts
meteo-wind-vane-calmA calm hour’s vane glyph
meteo-wind-dialThe dial’s SVG root
meteo-wind-dial-bezelThe dial’s bezel ring
meteo-wind-needleThe dial’s direction needle
meteo-current-observed / meteo-current-chillThe current-conditions reading rows
meteo-current-flank-gust / meteo-current-flank-lullThe gust and lull flanks around the dial
meteo-station-card-identity / -elevation / -sourceThe station card’s header regions
meteo-station-table-time / meteo-strip-timeTime cells in the table and the strip
meteo-air-cornerThe air matrix’s corner cell
meteo-compass-fanThe compass fan’s wrapper, beside its styled state classes

You can style these classes from your own CSS or leave them alone, and the default look does not depend on them. The SVG text classes (meteo-grid-label, meteo-tick) still render styled text. Their font, size, and ink come from the chart’s base .meteo-*-svg text rule, and the class itself has no rule to replace. To restyle them, override the base rule instead of adding rules per class.

Station theme tokensEach token is one light-dark() declaration in styles.css; both arms shown, resolved from the stylesheet.light armdark armCHROME AND IDENTITY--meteo-surface#ffffff#10161d--meteo-surface-raised#f4f6f9#212d3a--meteo-ink#17232e#e7edf3--meteo-muted#62717f#95a4b3--meteo-border#dbe2e9#2b3844--meteo-grid#e5eaef#28333e--meteo-accent#0f7490#45c3e0--meteo-gaprgba(98, 113, 127, 0.5)rgba(149, 164, 179, 0.45)FRESHNESS STATES--meteo-freshness-live#12813d#34d399--meteo-freshness-aging#b45309#fbbf24--meteo-freshness-stale#bb1d1d#f87171CHART AND WIND ENCODING--meteo-wind-band-fillrgba(15, 116, 144, 0.22)rgba(69, 195, 224, 0.22)--meteo-wind-mean#0f7490#45c3e0--meteo-wind-compare#8a97a3#6b7885--meteo-wind-vane#3b4a58#b8c6d3--meteo-cursor#d97706#f5a623--meteo-wind-favorable#2e9e63#34d17b--meteo-wind-unfavorable#c98a80#a06058BAND RAMP--meteo-band-0#56a2cc#5fb2e0--meteo-band-1#2e9e63#34d17b--meteo-band-2#d9a013#eab308--meteo-band-3#e2662c#f4732c--meteo-band-4#c22727#ef4444NON-COLOUR TOKENS (LIGHT ARM WHERE TWO EXIST)--meteo-fontui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif--meteo-radius12px--meteo-shadow0 1px 2px rgb(23 35 46 / 0.06), 0 8px 24px rgb(23 35 46 / 0.05)

TokenRole
--meteo-surfaceCard and panel background
--meteo-surface-raisedRaised elements (dial face, matrix header)
--meteo-inkPrimary text and strokes
--meteo-mutedSecondary text, axis labels
--meteo-borderCard and table borders
--meteo-gridChart gridlines
--meteo-accentThe accent (ungraded traces, links, emphasis)
--meteo-gapDropout hatching in charts
--meteo-cursorThe chart inspector cursor
--meteo-freshness-live / -aging / -staleThe freshness badge states
--meteo-fontFont stack for all component text (incl. SVG)
--meteo-radiusCorner radius
--meteo-shadowCard shadow
TokenRole
--meteo-band-0 … --meteo-band-4Speed grading, calm → strong
TokenRole
--meteo-wind-band-fillThe lull–gust envelope fill
--meteo-wind-meanThe mean trace when ungraded
--meteo-wind-vaneVane glyphs in the direction row
--meteo-wind-compareThe day-over-day compare overlay trace
--meteo-wind-favorable / --meteo-wind-unfavorableThe favorable and unfavorable verdicts: the rose’s and dial’s rings, vane tints, the direction fragment, the favorable-share stat

thresholds (React) grades traces, dial arcs, and rose petals into meteo-band-0..n classes. Your CSS decides what each band means and what colour it gets. Three thresholds make four bands. Add --meteo-band-* overrides to use your own colours, and add rules for higher indices if you declare more thresholds.

  • The site’s theme toggle on the component gallery uses only this mechanism, data-theme on .meteo-root.
  • If your page also sets color-scheme globally, the root’s own declaration wins inside .meteo-root. The components stay consistent even when the page around them uses a different scheme.
  • README images are generated from these same tokens, so the docs always match the palette.