Token sind Design-Vorgaben, die in menschen- und maschinenlesbare Daten übersetzt werden. Sie dienen als zentrale Vorgaben, um digitale Angebote einheitlich zu gestalten. Sie sind ein Kommunikationsmittel, eine gemeinsame Sprache zwischen Design und technischer Umsetzung, um präzise Informationen über die Erstellung von Benutzeroberflächen zu vermitteln.
Tokens bestehen aus Werten, die zum Aufbau eines systematischen Designs benötigt werden, z. B. aus Abständen für Platzierungen, Farben für Zustände, Typografie, Mikro-Animationen und vielem mehr. Sie können alles abbilden, was ein definiertes Design hat, etwa eine Farbe als RGBa-Wert, deren Deckkraft als Zahl, oder die Animationsgeschwindigkeit eines Elementes zwischen zwei Zuständen als Bézierkurve.
Bitte beachten Sie, dass das Token-Konzept zurzeit in Überarbeitung ist und in einem zukünftigen Release so geliefert wird, dass die Regeln automatisch in die Erstellung der CSS-Dateien übernommen werden können.
Die Design-Token-Systematik im DESY
Das Design-Token-System lebt von seiner Vorhersehbarkeit und Flexibilität. Die Systematik besteht darin, für alle denkbaren Szenarien und Kontexte einen auf den konkreten Anwendungszweck fokussierten Satz von Token zu haben und nicht eine beliebige Menge an Stylings ohne Struktur.
Tokens stellen zwar die meisten Informationen zur Implementierung und Darstellung einer UI-Komponente bereit; das Token-System ist dabei aber nur eine Ressource im Angebot von DESY und keine vollständige Wissensbasis und soll neben der eigentlichen Design- und Code-Dokumentation verwendet werden. Design-Tokens sind unmittelbar in unsere Komponentenbibliothek integriert. Teams können diese aber auch direkt in ihren Produkten benutzen, wenn sie keine strikte DESY-Implementierung verwenden.
Was ist ein Design-Token?
Design-Tokens repräsentieren die kleinen, sich wiederholenden Designentscheidungen, die den visuellen Stil eines Design-Systems ausmachen. Damit ersetzen sie statische Werte, wie z. B. RGBa-Werte für Farben, oder rem-Angaben für Schriftgrade durch selbsterklärende Namen. Ein Token besteht immer aus einem Token-Namen und einem zugehörigen Wert.
Beispiel: Das Token "$ref-color-blue-100" hat den Wert "45, 111, 158, 1".
Durch diesen Design-Token wird dem Farbwert "45, 111, 158, 1" der Name "…blue-100" zugewiesen. Dieser Token kann nun als Variable überall dort verwendet werden, wo dieser exakte Blauwert gefragt wird. In diesem Fall ist der Wert des Tokens eine Farbe. Der Wert könnte allerdings auch eine Schriftart, ein Abstand oder sogar ein anderes Token sein.
Beispiel: Das Design-Token "$sys-color-lightmode-text-interactive-default" hat den Wert "$ref-color-blue-100".
Technisch betrachtet sind Design-Tokens also aufeinander aufbauende CSS-Variablen, die über mehrere Token-Typen hinweg systematisch das UI-Design strukturieren und damit ein in sich konsistentes Ökosystem aufbauen. Wir verwenden grundsätzlich Tokens statt hartcodierten Werten und skalieren damit die komplexen Variationen, die von den digitalen Angeboten des Zolls benötigt werden. Durch diesen Aufbau können wir übergreifende Gestaltungsmuster definieren und nachhaltig iterieren, unabhängig von der Design-Dokumentation einer Komponente.
Token-Typen
Eine klare Terminologie ist der Schlüssel zum Verständnis der Tokens und ihrer Systematik, ihrer Verwendung und ihrer Beziehung zueinander. Jedes Token hat einen sorgfältig gewählten Namen, der einer festgelegten Namenskonvention folgt und seinen Zweck und seinen Umfang ablesbar macht. Tokens lassen sich an den ersten Zeichen ihrer Namen in vier Typen unterteilen: Reference-, System-, Context- und Component-Tokens.
Token-Typen
Basiswert & Alias
Basiswerte sind Angaben, die einer CSS-Eigenschaft (Property) zugewiesen werden. Nach dem Auflösen aller Token-Variablen sind Basiswerte die hartcodierten Angaben die die jeweilige CSS-Eigenschaft verlangt. Beispiele für Basiswerte:
Eigenschaft
Basiswert
font-size
1rem (16px)
font-weight
700
background-color
45, 111, 158, .05 (#f5f8fa)
margin-top
1.5rem (24px)
Ein Token, das auf einen anderes Token verweist, anstatt auf einen Basiswert nennt man Alias-Token.
Reference-Tokens (REF)
In diesem ersten Token-Typ werden alle Basiswerte jeweils einem Reference-Tokens als Wert zugewiesen und in die folgenden Kategorien unterteilt.
Komplette Farbpalette mit gleichmäßigen Helligkeitsabstufungen der genutzten Grundfarben.
Hellblau, Blau, Dunkelblau, Grün, Gelb, … , jeweils in 10 Helligkeitsabstufungen.
Opacity
Sammlung an ausgewählten Deckkräften als Dezimalzahl. Um diese Reference-Tokens nach Bedarf erweitern zu können wird der Wert der Deckkraft in den Titel übernommen.
Die entstehenden Reference-Tokens müssen losgelöst von ihrer Nutzung eine Skalierung im Token-Namen tragen. Diese Skalierungen können je nach CSS-Eigenschaft unterschiedlich sein.
Kategorie
CSS-Eigenschaft / Unterkategorie
Skala
Typografie
font-size
-sm, -md, -lg, … -3xl
font-weight
-rg, -md, -bd
text-decoration
-none, -upper, -lower
Color
blue (color)
-10, -20, … -100
green (color)
-10, -20, … -100
white (color)
-00, -10, -20, … -100
Space
size (height/width)
-1, -2, … -13
icon (height/width)
-sm, -md
Border
border-style
-none, -solid, -dotted, -dashed
Damit gibt es für jeden Basiswert ein entsprechendes Reference-Token. Jeder weitere Token-Typ besteht demnach aus Alias-Tokens, d. h. sie verweisen auf bereits bestehende Tokens.
System Token (SYS)
Ein System-Token definiert den Zweck, den ein Referenz-Token in der Benutzeroberfläche erfüllt. System-Tokens können global angewendet werden und sind nicht ausschließlich für bestimmte Komponenten oder Kontexte vorgesehen. System-Tokens werden deshalb auch in die oben genannten Kategorien eingeteilt und um einen allgemeingültigen, zweckgebundenen Namen erweitert.
Auf Ebene der System-Tokens können Farbschemata definiert werden. Je nach Systemeinstellungen des Anwenders kann also abgefragt werden, welcher Grünton als Erfolgsfarbe genutzt werden soll. Wann immer möglich, sollten System-Tokens auf die bestehenden Referenz-Tokens verweisen (oder diese miteinander verrechnen), anstatt statische Werte zu nutzen.
Diese Token-Ebene baut auf das Gestaltgesetz der Ähnlichkeit auf. Elemente mit ähnlichem Aussehen und Verhalten werden unabhängig von ihrer Positionierung auf der Seite als zusammengehörig wahrgenommen. Sieht ein Element also aus wie ein Button und regiert auf die Interaktion wie ein Button, kann davon ausgegangen werden, dass dieses Element Button-ähnliche Eigenschaften hat, also klickbar ist.
Context-Tokens werden benutzt, um diese gestalterischen Muster für einen Kontext zu definieren. Im DESY definieren wir die folgenden Kontexte:
Kontext
Beschreibung
Anwendungsbeispiele
Gemeinsamkeiten
Action
Button-ähnliche Ausgestaltung Interaktionsdesign
Buttons, Icon-Buttons, Buttons in Eingabefeldern (input file, Datepicker), …
Alle Abstands-Tokens die zur Definition des Grids benötigt werden
Seitenabstände, Stege, Breakpoints, …
-
Der Wert eines Context-Tokens kann sowohl ein System-Token als auch ein Reference-Token sein. Innerhalb eines Kontexts können Tokens aus unterschiedlichen Kategorien verwendet werden. So entsteht für jeden Kontext ein umfangreiches Set an Design-Tokens, das nur für eine abgegrenzte Gruppe an Komponenten (oder Elemente dieser Komponenten) genutzt wird.
Context-Tokens erleichtern zukünftige Iterationen des Design Systems, da die Ausgestaltung mehrerer Elemente von nur einem Token definiert wird. Ändert man zum Beispiel im Kontext "Forms" den Eckenradius von Formularelementen, so wirkt sich das auf alle Formularelemente aus, die diesen Token nutzen (input, textarea, select, Datepicker, …).
Component-Token (COMP)
Für die Design-Dokumentation einer Komponente werden ausschließlich Component-Tokens benutzt. Im Gegensatz zu den anderen Token-Typen repräsentieren sie die Elemente und Werte, die diese Komponente ausmachen. Component-Tokens haben einen eindeutigen und einzigartigen Einsatz, der im Name des Tokens beschrieben ist.
Wann immer möglich, sollten Component-Tokens auf die bestehenden Referenz-, System- und Context-Tokens verweisen (oder diese miteinander verrechnen), anstatt statische Werte zu nutzen; passende Alias-Tokens sind Reference-Tokens immer vorzuziehen. Beispiel für die Werte, die Component-Tokens zugewiesen werden können:
Jeder Component-Token besteht aus mehreren Token-Items, die zusammen den Einsatz des Tokens beschreiben. Getrennt werden diese Token-Items immer mit einem “-”.
Die Token-Items folgen einer klaren Abfolge von unterschiedlichen Token-Item-Types. Für jeden Type gibt es jeweils eine Reihe von Begriffen, die als Token-Item zur Verfügung stehen. Diese Abfolge muss nicht zwingend eingehalten werden, sorgt aber für Konsistenz in der Bezeichnung der Tokens und wird daher empfohlen.
Item-Types eines Component-Tokens
(*) = Pflichtelement im Component-Token
Beispiele:
Manchmal kann es vorkommen, dass keine CSS-Property benötigt wird, weil die Category selbst schon aussagekräftig genug ist. Im folgenden Beispiel soll eine Label-Farbe bestimmt werden. Für die Farbe eines Labels kann nur die CSS-Propertyfont-color in Frage kommen, weshalb wir nicht …-label-color-fontcolor-… schreiben, sondern mit …-label-color-… schon einen treffenden Token definiert haben:
Es kann auch sein, dass man gar keine Category bestimmen muss, weil das Design-Element keiner Category eindeutig zugeordnet werden kann:
Wenn die Category selbst bereits alles notwendige definiert, dann benötigt man ebenso keine Properties und Modifier.
Eine andere Ausnahme bilden CSS-Properties, die sich zwar mit der Bezeichnung der Category decken, aber nicht die einzig mögliche Lösung darstellen.
Im folgenden Beispiel doppelt sich das Token-Item “border” im Token-Namen, weil es sowohl eine Category namens “border” gibt als auch eine CSS-Property. Gäbe es neben der CSS-Property “border” keine andere Möglichkeit einen Rahmen darzustellen, dann könnten wir uns diese Dopplung im Token-Namen sparen. Da wir innerhalb der ”border” Category aber neben der ”border” Property auch noch ”outline” und ”box-shadow” haben, die den Rahmen des gleichen Containers definieren können, müssen wir hier redundante Begriffe benutzen.
Auch wenn es abseits der ersten drei Token-Items Unterschiede zwischen Component-Tokens geben kann, so folgen sie doch immer der gleichen Reihenfolge:
Im ersten Schritt wird deklariert, um welches Token-Level es sich handelt; hier “comp”, weil wir Component-Tokens definieren.
Danach identifizieren wir das Objekt, das wir definieren wollen: Die Komponente selbst und ein spezifisches Element innerhalb dieser Komponente.
Wenn wir genau wissen, was (Komponente & Element) wir ansprechen wollen, dann geben wir dem Component-Token mit, um welche Token-Category es sich handelt. Diese Categories spielen in den Token-Level REF und SYS eine strukturierende Rolle. Hier helfen sie nur noch, Tokens zu gruppieren.
Innerhalb jeder Category gibt es eine Reihe von CSS-Properties, die genutzt werden können. Beispiel: font-color oder background-color sind Teil der Token-Category color.
Modifiers werden benötigt, um die unterschiedlichen Werte zu definieren, die je nach Variante / Hierarchie / State / Breakpoint / … an der gleichen Stelle in der Webcomponent zum Einsatz kommen können.
Es kann durchaus vorkommen, dass mehr als ein Modifier benötigt wird. Bitte hierbei die Reihenfolge der Modifier beachten (siehe Token-Items im Detail - 6. Modifer)
Token-Items im Detail
(*) = Pflichtelement im Component-Token
1. Token-Level *
Hier die vollständige Liste aller Begriffe, die als Token-Level eingesetzt werden können. Es dürfen keine anderen Token-Level genutzt werden.
ref
Erstes Token-Level: Reference-Tokens zeigen direkt auf die Basiswerte des DESY.
sys
Zweites Token-Level: Auf der System-Ebene definieren wir allgemeingültige Tokens.
ctx
Drittes Token-Level: Context-Tokens definieren Gemeinsamkeiten zwischen Komponenten, Oberflächen oder Interaktionsverhalten, sodass diese nicht für jede Komponente neu definiert werden müssen.
comp
Letztes Token-Level: Jede Komponente erhält Component-Tokens für alle Werte, die wir als Token definieren können und in Zukunft ergänzen müssen. Ziel ist es, keine festen Werte in die *.scss Datei einer Webcomponent zu schreiben, sondern nur Component-Tokens darin zu platzieren.
2. Component *
Hier nutzen wir die technische Bezeichnung unserer Webcomponents. Webcomponents, die aus zwei Worten bestehen, müssen hier klein- und zusammengeschrieben werden (e.g. sessiontimer statt Session Timer). Es dürfen nur Begriffe hinzugefügt werden, wenn es dafür tatsächlich auch eine Komponente gibt.
accordion
alert
anchor
anchorlist
breadcrumb
button
card
footer
header
modal
pagination
pill
progressbar
progressnav
sessiontimer
subnavigation
toast
…
3. Design-Element / -Item *
Zur genauen Identifikation eines Elements innerhalb einer Webcomponent orientieren wir uns an den folgenden Begriffen. Wenn Begriffe wie “wrapper” oder “container” ein Objekt gut beschreiben, dann nutzen wir diesen Begriff dafür. Diese Liste muss flexibel bleiben, da Webcomponents unterschiedlich umfangreich sein können. Bei Bedarf und Prüfung auf Notwendigkeit können neue Begriffe hinzugefügt werden.
actionbar
arrow
bg
bgimg
border
bottom
Button
buttoncontainer
collapse
container
divider
header
headline
icon
ie
(interactive
element)
img
indicator
item
itembody
itemfooter
itemheader
label
link
list
logo
marker
microcopy
modal
number
outline
overlay
popover
progressbar
progresscontainer
radius
row
text
validation
wrapper
…
Bei großen Komponenten könnten auch zwei aufeinanderfolgende Begriffe genutzt werden, um das Element eindeutiger zu identifizieren.
4. Category
Es ist recht einfach einen Component-Token in die richtige Category einzuordnen, wenn man weiß, für welche CSS-Property er vorgesehen ist. So umfasst die Category “typo” zum Beispiel alle CSS-Properties, die für die Ausgestaltung des Schriftbildes zuständig sind. Ausgenommen davon sind Properties, die zwar das Schriftbild beeinflussen können, aber einer anderen Category eindeutiger zugeordnet werden können. Welche Category für welche Property genutzt wird lässt sich aus der Kategorisierung der Reference-Tokens ableiten. Es dürfen keine weiteren Begriffe genutzt werden.
Hier eine umfangreiche, wenn auch nicht vollständige Liste an CSS-Properties, aufgeteilt nach Categories:
Zur genau Identifikation eines Elements innerhalb einer Webcomponent orientieren wir uns an den folgenden Begriffen. Wenn Begriffe wie “wrapper” oder “container” ein Objekt gut beschreiben, dann sollen diese Begriffe dafür benutzt werden. Da Webcomponents unterschiedlich umfangreich sein können muss auch diese Liste flexibel bleiben. Bei Bedarf können neue Begriffe hinzugefügt werden, bei der die dahinterstehende CSS-Property eindeutig ist.
align
bg
bgimg
border
box-shadow
breakpoint
duration
ease
filter
fontsize
fontweight
height
icon
letterspacing
lineheight
margin
margintop
marginright
marginbottom
marginleft
maxheight
maxwidth
minheight
minwidth
opacity
offset
outline
padding
paddingtop
paddingright
paddingbottom
paddingleft
radius
rotation
style
textdeco
texttransform
width
…
6. Modifier
Im letzten Typ der Token-Items gibt es eine weitere kleine Unterteilung in vier untergeordnete Typen:
6.1. Varianten
Hier können je nach Komponente verschiedene Begriffe für Varianten genutzt werden. Häufig vorkommende Varianten sind hier gelistet. Bei Bedarf können neue Begriffe hinzugefügt werden.
Status
info
success
warning
error
highlight
…
Hierarchy
primary
secondary
tertiary
…
Custom
…
6.2. State
Hier können je nach Komponente verschiedene Begriffe für Varianten genutzt werden. Häufig vorkommende Varianten sind hier gelistet. Hier dürfen keine neuen Begriffe hinzugefügt werden, da sich diese mit den SYS- und CTX-Tokens decken.
default
hover
focus
disabled
readonly
visited
active
current
checked
selected
toggled
6.3. Breakpoint
Wenn kein Breakpoint-Modifier gesetzt ist, dann ist dieser Token über alle Breakpoints gültig. Das “bp” im Namen steht für Breakpoint. Hier dürfen keine neuen Breakpoints hinzugefügt werden, da diese feststehen.
bpxs
Token-Suffix für Werte, die ab dem Breakpoint Extra-Small aufwärts gelten. 0-36 rem / 0-576 px Wichtig: Wenn es keine Veränderungen über die Breakpoints / Media Queries gibt, dann muss dieser Suffix nicht gesetzt werden. Sobald es aber auch nur eine Änderung über irgendeinen Breakpoint gibt, dann muss dieser kleinste Breakpoint als Ausgangswert für die Komponente definiert werden (Mobile first!).
bpsm
Token-Suffix für Werte, die ab dem Breakpoint Small aufwärts gelten. 36-48 rem / 576-768 px
bpmd
Token-Suffix für Werte, die ab dem Breakpoint Medium aufwärts gelten. 48-62 rem / 768-992 px
bplg
Token-Suffix für Werte, die ab dem Breakpoint Large aufwärts gelten. 62-75 rem / 992-1200 px
bpxl
Token-Suffix für Werte, die ab dem Breakpoint Extra-Large aufwärts gelten. 75-87,5 rem / 1200-1400 px
bpxxl
Token-Suffix für Werte, die ab dem Breakpoint Extra-Extra-Large aufwärts gelten. >87,5 rem / >1400 px
Struktur einer <component>.js-Datei
Die Struktur dieser Datei hat eine direkte Auswirkung auf den Namen des Tokens. Um den Token so zu erstellen wie oben beschrieben muss die Datei folgendem Aufbau folgen.
Der Rahmen einer jeden *.js Datei, die Component-Tokens definieren, sieht wie folgt aus:
comp:{ <ComponentName>:{ … }, }
comp:{ button:{ … }, }
Darin können nun einzelne Design-Elemente angesprochen werden:
Sollte es für die angesprochene CSS-Property je nach Komponenten-Variante / Hierarchie / State / Breakpoint usw. andere Werte geben, so müssen diese in Form von Modifiers angelegt werden.
Für alle Labels und Texte die wir definieren, wollen wir ein vollständiges Set an Typo-Tokens definieren. So können wir das gesamte Schriftbild der Seite bei Bedarf allein über die Design-Tokens ändern.
Wenn wir unterschiedliche Angaben für Breakpoints machen müssen, dann definieren wir diese als letzte Modifier-Instanz im Token. Im Beispiel eine Veränderung im Padding beim Breakpoint: