Erweitere eine Komponentenbibliothek für Designer- und Entwickler:innen

Entdecke, wie du eine Komponentenbibliothek mit Design Tokens erweiterst. Lerne die effiziente Verwaltung von Design Tokens und Komponenten für Designer- und Entwickler:innen in Figma, Storybook und Vue.

Jairus Joer

Jairus Joer

Die Texte in diesem Artikel wurden teilweise mit Hilfe künstlicher Intelligenz erarbeitet und von uns korrigiert und überarbeitet. Für die Generierung wurden folgende Dienste verwendet:

Wie wir maschinelles Lernen bei der Erstellung unserer Artikel einsetzen

Wo wir aufgehört haben

Bisher haben wir gelernt, wie man eine Komponentenbibliothek für Designer- und Entwickler:innen erstellt, indem wir eine relativ einfache Button-Komponente implementiert haben. In diesem Artikel werden wir die zuvor erarbeitete Grundlage erweitern und zeigen, wie man mit umfangreicheren Komponenten umgeht.

Um das gewünschte Ergebnis zu erzielen, bauen wir auf einigen der Ideen auf, die in Entwickeln von Designsystemen unter Berücksichtigung der Barrierefreiheit vorgestellt wurden, und implementieren Design-Token, um die Farben und das Aussehen unserer Komponenten während des Designs und der Entwicklung zu verwalten.

Neue Anforderungen

Bevor wir uns mit den Details der Design-Token befassen, fügen wir der vorherigen Anforderung unserer Button-Komponente einige neue Anforderungen hinzu. In diesem Fall soll die Button-Komponente mehrere Farbvarianten umfassen, um ihre möglichen Aktionen zu verdeutlichen.

Anforderungen der Designer:innen

  • Farben
    • Brand
    • Neutral
    • Informative
    • Successful
    • Cautionary
    • Destructive

Diese zusätzliche Anforderung erhöht die Anzahl der Varianten der Komponente auf 24. Obwohl dies immer noch innerhalb von Figma mit Multi Edit verwaltbar ist, erfordert die zunehmende Komplexität eine strukturiertere Vorgehensweise zur Handhabung der Varianten und ihres Aussehens.

Design Tokens in Figma

Design Tokens, oder Variablen in Figma genannt, helfen uns, eine konsistente Designsprache für unsere Komponenten zu definieren. Um zukünftig präziser und flexibler zu sein, werden die Tokens in zwei Gruppen aufgeteilt: primitive und semantische Tokens.

Primitive Tokens

Primitive Tokens dienen als Grundlage unserer Designsprache. Sie definieren Basisfarben und andere Einheiten, auf denen unsere Komponenten aufbauen. Um zu beginnen, füge die gewünschten Farben zur Lokalen Variablen Tabelle hinzu. In diesem Beispiel verwenden wir die Tailwind CSS Farbpalette um die Farben zu definieren.

Eine Implementierung von primitiven Tokens für die Indigo Farbpalette in Figma

Semantische Tokens

Semantische Tokens bauen auf Primitiven auf, um verständliche Tokens für unsere Layouts, Seiten und Komponenten zu erstellen. Sie referenzieren die Primitiven und dienen als Schnittstelle, um die Komponenten mit den in der Designsprache definierten Farben zu füllen.

Eine Implementierung von semantischen Tokens für die Brand Farbpalette in Figma

Zusammengefasst können rohe Werte wie #e4e4e7 als Primitive wie Indigo 600 definiert werden. Dieses Primitive wird dann von einem oder mehreren semantischen Token wie Brand referenziert. In voller Ausprägung könnte das folgende Form annehmen:

Semantic TokenPrimitive TokenRaw Value
Border/Width1
Color/Neutral/SubtlePrimitive/Zinc/200 #e4e4e7
Color/NeutralPrimitive/Zinc/950 #09090b
Color/Brand/SubtlePrimitive/Indigo/100 #e0e7ff
Color/BrandPrimitive/Indigo/600 #4f46e5
Color/Informative/SubtlePrimitive/Sky/100 #e0f2fe
Color/InformativePrimitive/Sky/600 #0284c7
Color/Successful/SubtlePrimitive/Emerald/100 #d1fae5
Color/SuccessfulPrimitive/Emerald/600 #059669
Color/Cautionary/SubtlePrimitive/Amber/100 #fef3c7
Color/CautionaryPrimitive/Amber/600 #d97706
Color/Destructive/SubtlePrimitive/Rose/100 #ffe4e6
Color/DestructivePrimitive/Rose/600 #e11d48

Plugins wie variables2css exportieren die definierten Design-Token in verschiedenen Formaten für die Verwendung in unserem Projekt. Ab hier geht es in die Entwicklungsphase und wir beginnen mit der Definition der primitive und semantischen Tokens in CSS.

Design Tokens in der Entwicklung

Sobald die Design-Token in den jeweiligen Formaten exportiert und in das Projekt implementiert wurden, können wir sie in unserer Button-Komponente verwenden, um die Farben und ihre Varianten zu definieren. Eine Möglichkeit, dies zu tun, ist es, die Tokens als CSS-Variablen zu definieren.

css/primitives.css
:root {
  --primitive-amber-100: #fef3c7;
  --primitive-amber-400: #fbbf24;
  --primitive-amber-600: #d97706;
  --primitive-amber-950: #451a03;

  --primitive-emerald-100: #d1fae5;
  --primitive-emerald-400: #34d399;
  --primitive-emerald-600: #059669;
  --primitive-emerald-950: #022c22;

  --primitive-indigo-100: #e0e7ff;
  --primitive-indigo-400: #818cf8;
  --primitive-indigo-600: #4f46e5;
  --primitive-indigo-950: #1e1b4b;

  --primitive-rose-100: #ffe4e6;
  --primitive-rose-400: #fb7185;
  --primitive-rose-600: #e11d48;
  --primitive-rose-950: #4c0519;

  --primitive-sky-100: #e0f2fe;
  --primitive-sky-400: #38bdf8;
  --primitive-sky-600: #0284c7;
  --primitive-sky-950: #082f49;

  --primitive-zinc-50: #fafafa;
  --primitive-zinc-100: #f4f4f5;
  --primitive-zinc-200: #e4e4e7;
  --primitive-zinc-300: #d4d4d8;
  --primitive-zinc-400: #a1a1aa;
  --primitive-zinc-500: #71717a;
  --primitive-zinc-600: #52525b;
  --primitive-zinc-700: #3f3f46;
  --primitive-zinc-800: #27272a;
  --primitive-zinc-900: #18181b;
  --primitive-zinc-950: #09090b;
}

Um Kompatibilität zwischen Design und Entwicklung zu gewährleisten, implementieren wir die gleiche Trennung von Tokens und Naming-Konventionen. So können Design-Token sowohl in Figma als auch im Projekt verwendet und synchron gehalten werden.

css/semantics.css
:root {
  --border-width: 0.0625rem;

  --color-neutral-subtle: var(--primitive-zinc-200);
  --color-neutral: var(--primitive-zinc-950);

  --color-brand-subtle: var(--primitive-indigo-100);
  --color-brand: var(--primitive-indigo-600);

  --color-informative-subtle: var(--primitive-sky-100);
  --color-informative: var(--primitive-sky-600);

  --color-successful-subtle: var(--primitive-emerald-100);
  --color-successful: var(--primitive-emerald-600);

  --color-cautionary-subtle: var(--primitive-amber-100);
  --color-cautionary: var(--primitive-amber-600);

  --color-destructive-subtle: var(--primitive-rose-100);
  --color-destructive: var(--primitive-rose-600);
}

Programmatische Komponenten

Die Rigidität unserer Design-Token erlaubt es uns, CSS-Klassen programmatisch für alle Farben zu generieren. Anstelle der manuellen Definition von Klassen, verwenden wir SCSS um die Klassen für uns zu generieren und deren Werte mit gebundenen CSS-Variablen zu zuordnen.

Weitere Optimierungen der Stil-Generierung und der CSS-Bundle-Größe können mit Hilfe von Tools wie PurgeCSS oder Tailwind CSS Layers erreicht werden, die unbenutzte Klassen und Stile automatisch entfernen und die Menge generierter Klassen reduzieren.

Um die betreffende Komponente zu aktualisieren, definieren wir die Property color und fügen SCSS hinzu, um die notwendigen Klassen zu generieren. Dann aktualisieren wir die Komponente, um die aktualisierten Klassen und Poperties zu verwenden, und dann ist es soweit, die Dokumentation zu aktualisieren, um den Änderungen gerecht zu werden.

components/Button.vue
<script setup lang="ts">
import Icon from './Icon.vue';

defineOptions({ inheritAttrs: false });

const {
  variant = 'bold',
  color = 'brand',
  is = 'button',
  selector = false,
} = defineProps<{
  variant?: 'bold' | 'subtle' | 'outline' | 'ghost';
  color?: 'brand' | 'neutral' | 'informative' | 'successful' | 'cautionary' | 'destructive';
  is?: string;
  selector?: boolean;
}>();

</script>

<template>
  <div :class="['button', variant, color]">
    <component class="center" :is v-bind="$attrs">
      <slot />
    </component>
    <span class="separator" v-if="selector"></span>
    <button v-if="selector" class="selector">
      <Suspense>
        <Icon variant="NavArrowDown" />
      </Suspense>
    </button>
  </div>
</template>

<style scoped lang="scss">
.button {
  display: inline-flex;
  gap: 0.25rem;
  line-height: 1rem;
  padding: 0.25rem;
  align-items: center;
  border-radius: 0.75rem;
}

.bold {
  background: var(--button-color);
  color: var(--button-color-subtle);
}

.subtle {
  background: var(--button-color-subtle);
  color: var(--button-color);
}

.outline {
  box-shadow: inset 0 0 0 var(--border-width) var(--button-color-subtle);
  color: var(--button-color);
}

.ghost {
  color: var(--button-color);
}

$colors: 'brand', 'neutral', 'informative', 'successful', 'cautionary', 'destructive';

@each $color in $colors {
  .#{$color} {
    --button-color: var(--color-#{$color});
    --button-color-subtle: var(--color-#{$color}-subtle);
  }
}

.center {
  border-radius: 0.5rem;
  font-weight: 500;
  font-size: 0.875rem;
  padding: 0.75rem;
  white-space: nowrap;
  text-decoration: unset;
}

.separator {
  background: currentColor;
  height: 1.5rem;
  width: 0.0625rem;
}

.selector {
  display: flex;
  border-radius: 0.5rem;
  padding: 0.75rem;
}
</style>

Aktualisiere die Dokumentation

Properties und ihre Werte werden automatisch von Storybook’s Autodocs Feature hinzugefügt und aktualisiert. Wir können auch die Benutzbarkeit von Komponenten in Storybook verbessern, indem wir Argument-Typen für unsere Komponente festlegen, um Interaktionen zu verbessern.

Diese Argument-Typen sind Teil des meta Objekts in der Story-Definition und werden verwendet, um die Steuerungen für die Komponente in Storybook zu generieren. So können wir leicht zwischen den verschiedenen Farbvarianten der Button-Komponente wechseln.

stories/Button.stories.ts
const meta: Meta<typeof Button> = {
    // ...
    argTypes: {
        variant: {
            control: 'select',
            options: ['bold', 'subtle', 'outline', 'ghost'],
        },
        color: {
            control: 'select',
            options: ['brand', 'neutral', 'informative', 'successful', 'cautionary', 'destructive']
        },
    },
};

Nächster Artikel

In dem nächsten Artikel werden wir die Button-Komponente um Zustände erweitern. Insbesondere werden wir Interaktionszustände wie :hover, :focus, :active und :disabled behandeln und zeigen, wie man sie in Kombination mit den bereits vorhandenen Farben und Varianten umsetzt.

TL;DR

Erweitere eine Komponentenbibliothek mit Design-Token für konsistente Farbvarianten. Implementiere primitive und semantische Token in Figma und aktualisiere die Storybook-Dokumentation für verbesserte Zusammenarbeit zwischen Designer- und Entwickler:innen.