Theme toggle
A dark mode toggle is usually where styling libraries start shipping runtime: a provider at the root, context, a re-render on every switch. With Salty CSS both themes are compiled into one stylesheet, keyed off a data- attribute. The toggle is an attribute flip — the browser does the rest through the native variable cascade.
Declare the tokens
The palette goes in as static atoms. The themed values are molecules in a conditional group: the same token names in both themes, different atoms behind them.
import { defineVariables } from "@salty-css/core/factories";
export default defineVariables({
// Atoms — the fixed palette.
colors: {
white: "#ffffff",
ink: "#111111",
night: "#0b0d12",
mist: "#f5f5f5",
blue: { base: "#0070f3", light: "#7aa7ff" },
},
// Molecules — what components read, flipped by data-theme.
conditional: {
theme: {
light: {
bg: "{colors.white}",
text: "{colors.ink}",
accent: "{colors.blue.base}",
},
dark: {
bg: "{colors.night}",
text: "{colors.mist}",
accent: "{colors.blue.light}",
},
},
},
});Use them in a component
Any React component reads the molecules, never the atoms. That one indirection is what lets it follow the theme without being touched.
import { styled } from "@salty-css/react/styled";
export const Panel = styled("section", {
base: {
background: "{theme.bg}",
color: "{theme.text}",
borderLeft: "4px solid {theme.accent}",
padding: "2rem",
transition: "background 0.2s ease, color 0.2s ease",
},
});Flip the attribute
A conditional group has no base — with no data- on an ancestor, the {theme. tokens resolve to nothing. So the markup always ships a default, and a small inline script in the <head> swaps it for the saved choice or the OS preference before the first paint.