Snažil jsem se dát do kupy novou architekturu pro barvy resp. design tokeny, která by byla dobře škálovatelná a jednoduše přebarvitelná pro jednotlivé instance či embedy.
—
Základem je palette, což jsou definice základních barev pro daný theme. Jednalo by se vždy o soubor v /src/themes/{instance}.css, tedy např. /src/themes/www.volebnikalkulacka.cz.css. Jde o obyčejné CSS proměnné, takže je případně možné je definovat/přepsat i na úrovni mimo design systém.
:root {
--palette-primary: blue;
--palette-secondary: red;
--palette-neutral: gray;
--palette-yellow: yellow;
}
Pak nastupují definice design tokenů v Tailwindu. Design tokeny přiřazují jednotlivým barvám sémantický význam.
Struktura názvu design tokenů je (pro barvy) je --color-{element}-{varianta}-{stav}, např .--color-bg-primary nebo --color-fill-neutral-hover. Kromě toho jsou definovány ještě kombinace {element}-on-{token}, např. --color-text-on-bg-secondary.
Hodnoty tokenů jsou pomocí OKLCH odvozeny z palette barev. Zároveň ale vždy upřednostňují CSS proměnnou, pokud je definovaná, pokud si tedy budu chtít s barvami víc vyhrát a nějakou si přepsat, budu to moci udělat.
Kromě toho jsou pomocí CSS funkce light-dark() rovnou definovány barvy pro dark mode.
Tedy /src/styles.css bude vypadat nějak následovně:
@theme {
--color-bg-primary: light-dark(
var(
--bg-primary-light,
oklch(from var(--palette-primary) calc(l + 0.1) calc(l - 0.2) h)
),
var(
--bg-primary-dark,
oklch(from var(--palette-primary) calc(l - 0.4) calc(l - 0.2) h)
)
);
--color-text-on-bg-primary: light-dark(
var(
--text-on-bg-primary-light,
oklch(from var(--palette-primary) calc(l - 0.8) calc(l - 0.2) h)
),
var(
--text-on-bg-primary-dark,
oklch(from var(--palette-primary) calc(l + 0.8) calc(l - 0.2) h)
)
);
}
Například pro outlined tlačítko by to pak fungovalo nějak takhle:
border-primary
text-primary
hover:border-fill-hover
hover:bg-fill-hover
hover:text-text-on-fill-hover
active:border-fill-active
active:bg-fill-active
active:text-text-on-fill-active
Ano, bohužel někdy to tam bude repetitivní jako text-text, což ale bohužel v Tailwindu jinak nejde, když je třeba odlišit dvě barvy pro různé elementy (např. border-primary je jiná barva než bg-primary apod.).
Jinak záměrně do toho, zatím, nepasuji další vrstvu, která by šla už na úroveň konkrétních komponent. Pokud zjistíme, že to potřebujeme, tak se to může přidat později. Pak by tedy vzniklo i něco jako --color-button-bg-primary-hover apod.
—
Co si od tohoto řešení slibuju:
- bude to velmi jednoduše themable pouhou definicí dvou, tří barev, s čímž si poradí i ne-designer
- bude to konzistentní napříč komponentami, protože ty budou využívat výhradně sémantické design tokeny a nebude třeba přemýšlet, jako barvu má mít zrovna border input na focus apod.
- budeme konečně dark-mode ready
Berte to jako první kick-off, ale doufám, že si to sedne a bude to fungovat. Těším se na feedback.