Gå til innholdet

Design tokens

Alle verdier er CSS-variabler i tokens.css, både farger, avstander og skriftstørrelser.

import "@fristil/designsystem/tokens.css"
.min-komponent {
color: var(--fs-color-accent-fill);
padding: var(--fs-spacing-4);
font-size: var(--font-size-m);
}

Ett fargelag, ikke to. En farge er et punkt i en matrise av familie, altså hva den betyr, og rolle, altså hva den gjør. Navnet er --fs-color-<familie>-<rolle>.

Hver familie har de samme rollene. Det er strukturen som gjør at de matcher: et fareområde og et merkevareområde ser ut som søsken fordi de er bygd av de samme rollene på de samme lyshetene.

FamilieTil
accentLenker, primærknapp, fokus, valgt tilstand
visitedBesøkte lenker
brand1, brand2, brand3Flater, seksjoner og kategorier. De betyr ikke noe i seg selv
neutralSiden, brødteksten, kantene
dangerFeil, sletting, avslag
warningKrever oppmerksomhet
successFullført, godkjent

Ni roller, like for hver familie. Tekst og kant har tre trinn hver, som speiler hverandre.

RolleTilLøfte
surfaceTonet flate: et merke, et varsel, en seksjoningen
border-subtleDekorativ strek, som mellom to raderingen
borderRammen rundt et felt eller en flate3,1:1 mot siden, mot raised og mot egen surface
border-strongFeltrammen når musa er over, og en tabellstrekfølger av border, som den ligger utenfor
fillFylt flate: en knapp, en avkryssingsboks som er huket av3,1:1 mot siden og mot raised
contentTeksten oppå fill4,6:1 mot fill
text-subtleDempet tekst: hjelpetekst, plassholdere4,6:1 mot siden, mot et kort og mot raised
textFamiliens farge som tekst, og knappen ved hoverde samme tre, og mot egen surface
text-strongBrødtekst, overskrifter og lenka ved hoverde samme tre

Den nøytrale familien har to roller i tillegg, fordi den bærer siden selv:

TokenTilLøfte
--fs-color-neutral-canvasSidenhver tekstrolle i hver familie holder mot den
--fs-color-neutral-raisedEn flate som ligger over et kortdet samme

Tekst må holde mot alle tre lagene, altså siden, neutral-surface og neutral-raised. Ellers blir et kort på et kort uleselig uten at noe sier fra.

Hver rad er en familie, hver rute en rolle, i rekkefølgen over:

Kuløren er din, lysheten er rollens. Lyshetene er ikke valgt, de er regnet fram mot et sveip rundt hele fargesirkelen på den høyeste metningen sRGB kan vise. Derfor holder løftene uansett hvilken merkefarge du gir, og det finnes ikke noe justeringspass som flytter fargen din etterpå.

Skriver du dine egne verdier, er løftene dine å holde. fristil sjekk-tema tema.css sier hvilken celle som ryker og hvorfor.

TokenTil
--fs-color-disabled-surface, --fs-color-disabled-textKontroller som er slått av. Unntatt kontrastkravet i WCAG 1.4.3, og med vilje dempet: en kontroll som er av skal se av
--fs-color-overlayFlaten bak en modal
--fs-shadow-overlaySkyggen under et panel som ligger over siden
--fs-focus-ringHele ringen rundt det som har fokus, som kortform til outline. Endrer du den, endrer du fokusringen i hele systemet
--fs-icon-search, --fs-icon-check, --fs-icon-dash, --fs-icon-calendar, --fs-icon-clockIkoner tegnet inn i en bakgrunn

Ikonene følger ikke matrisen. Et ikon som er tegnet inn i en bakgrunn kan ikke lese en CSS-variabel: streken er malt inn i selve bildet. De har derfor en mørk og en lys utgave, og snur med temaet. Bruker du dem selv, sett dem som background-image.

disabled eller neutral? De ser like ut, men kravene er ulike. disabled er for kontroller som er slått av. neutral er for dempet informasjon brukeren skal lese eller trykke på, og holder løftet sitt. Er elementet slått av, bruk disabled.

Én skala, --fs-spacing-*, til alt spatialt: padding, margin, gap, width, height. Fire piksler som grunnenhet, som Tailwind, så --fs-spacing-4 tilsvarer p-4.

VariabelVerdiTailwind
--fs-spacing-px1pxingen
--fs-spacing-0-50.125rem0.5
--fs-spacing-10.25rem1
--fs-spacing-20.5rem2
--fs-spacing-30.75rem3
--fs-spacing-41rem4
--fs-spacing-51.25rem5
--fs-spacing-61.5rem6
--fs-spacing-71.75rem7
--fs-spacing-82rem8
--fs-spacing-102.5rem10
--fs-spacing-123rem12
--fs-spacing-164rem16

Egen rytme framfor numerisk skala, så navnet sier hvor stor teksten er i forhold til brødteksten.

--font-size-m er brødteksten. --font-size-reference er 16px, grunnstørrelsen rem-verdiene regnes fra.

Verdiene er de komponentene hadde skrevet ut fra før. De ble tokens fordi en organisasjon som tar systemet i bruk gjerne har sin egen typografi, og da skal forskjellen settes ett sted framfor i tjue stilark.

TokenVerdiBrukt av
--font-weight-regular400merkelappene «(påkrevd)» og «(valgfri)» på ledetekst og feltsett
--font-weight-medium500knapp, feilmelding
--font-weight-semibold600trekkspill, varsel, avatar, merke, brødsmule, kort, dialog, feiloppsummering, feltsett, ledetekst, paginering, økttidsvarsel, tabell, faner, valggruppe
--font-weight-bold700overskrift, og stjerna som merker et påkrevd felt
--fs-line-height-default1.525 stilark: knapp, felt, tekstområde, nedtrekksliste, tabell, faner, dialog og resten av kontrollene
--fs-line-height-heading1.2overskrift
--fs-line-height-article1.6brødtekst, liste, korttekst
--fs-line-height-compact1.4hjelpetekst, feilmelding, hjelpeboble, etikett, korttittel, dialogtittel, feiloppsummeringens tittel, sambandslinja

Knappen, overskriften og avsnittet leser dem gjennom sin egen komponentvariabel, slik at et tema kan endre alle knapper uten å endre all tekst: font-weight: var(--fs-button-font-weight, var(--font-weight-medium)). De andre leser tokenet direkte. Det er et bevisst skille: en egen variabel per komponent er verdt det der man vil kunne skille dem, og ren støy der man ikke vil.

Tre linjeavstander står fortsatt som tall i stilarkene. 1 i paginering, avatar og lukkeknappen på meldingen er ikke typografi, men en måte å få et tall eller et kryss til å stå midt i en sirkel. 1.3 og 1.55 står i én komponent hver.

Alle variabelnavn finnes som en typet oppslagstabell:

import {
colorTokens,
cssTokens,
type CssToken,
} from "@fristil/designsystem/tokens"
const token: CssToken = "--fs-color-accent-fill"
element.style.setProperty(token, "red")
colorTokens["--fs-color-accent-fill"] // "#226dba"
cssTokens["--font-size-mega"] // "2.625rem"

Skriver du --fs-color-accent-fil, får du feil i editoren i stedet for en var() som stille faller tilbake til ingenting. Det samme gjelder en rolle som ikke finnes: --fs-color-accent-fill-hover er en typefeil, ikke en tom verdi.

Fargene ligger i colorTokens og darkColorTokens, resten i cssTokens. Skillet er at fargene regnes av kontrakten og derfor ikke står skrevet i kilden. CssToken dekker begge, siden fargenavnene utledes av de to aksene.

Build-time-verdier, ikke CSS-variabler, og eksporteres derfor som konstanter:

import { Breakpoints, Containers } from "@fristil/designsystem/tokens"
Breakpoints.md // "768px"
Containers.aside // "384px"

Brekkpunktene følger Tailwind: sm 640px, md 768px, lg 1024px, xl 1280px, 2xl 1536px.

Temaet er en CSS-fil, ikke en forhåndsinnstilling i JavaScript. Pakken har derfor ingen avhengighet til Tailwind i det hele tatt, og to Tailwind-versjoner kan ikke komme i konflikt: det er versjonen i appen din som leser fila.

app.css
@layer theme, base, fristil, components, utilities;
@import "tailwindcss";
@import "@fristil/designsystem/tokens.css";
@import "@fristil/designsystem/tailwind.css";

Den første linja er det viktigste. Se Tilpasning for hvorfor.

Alt temaet legger til heter fs-, som klassene ellers i systemet. Da er bg-neutral-100 fortsatt Tailwinds egen farge:

Hver celle i matrisen blir en klasse, med samme navn: bg-fs-accent-fill leser --fs-color-accent-fill.

KlasseVerdi
bg-fs-accent-fill--fs-color-accent-fill
text-fs-accent-text--fs-color-accent-text
bg-fs-danger-surface--fs-color-danger-surface
text-fs-neutral-text-subtle--fs-color-neutral-text-subtle
border-fs-neutral-border--fs-color-neutral-border
text-fs-mega--font-size-mega
max-w-fs-aside384px
shadow-fs-overlay--fs-shadow-overlay

Avstandene er koblet til skalaen: Tailwind regner p-4 som calc(var(--spacing) * 4), og --spacing er satt til --fs-spacing-1. p-4 er dermed nøyaktig --fs-spacing-4, og endrer du skalaen, følger alle Tailwind-klassene med.

Brekkpunktene er utelatt med vilje. Fristils sm til 2xl har de samme verdiene som Tailwind allerede bruker, så md: virker som før.

Klassene er ikke skrevet av hukommelsen: hver utgivelse kompilerer temaet med en ekte Tailwind og kontrollerer at hver farge i matrisen kommer ut som en klasse med tokenet sitt i seg.

Hele oppsettet, med eksempler som blandes fritt med komponentene, står på Tailwind.

Vil du endre farger, form eller størrelse, se Tilpasning.