Design System mit Vue-Komponenten aufbauen
AI generated
<v/>
{ }
Vue.js · Design System · UI-Kit · Tokens
Design System mit Vue-Komponenten aufbauen
Von Design-Tokens bis zur automatisierten Dokumentation

Eine Sammlung wiederverwendbarer Vue-Komponenten ist noch kein Design System. Erst Design-Tokens als einzige Wahrheitsquelle für Farben und Abstände, eine bewusst entworfene Komponenten-API und verbindliche Versionierung machen aus losen Bausteinen ein System, das Teams über Projektgrenzen hinweg konsistent nutzen können.

20 Min. Lesezeit Tokens · Theming · Storybook · npm-Paket Vue 3 · Vite · Style Dictionary

1. Was ein Design System von einer Komponentensammlung unterscheidet

Viele Teams glauben, ein Design System mit Vue-Komponenten zu besitzen, sobald sie einen Ordner mit wiederverwendbaren Buttons, Inputs und Karten haben. Tatsächlich ist das nur die sichtbare Oberfläche. Ein echtes Design System besteht aus drei Schichten: den Design-Tokens als abstrakte Designentscheidungen, den Vue-Komponenten als deren technische Umsetzung, und der Dokumentation, die beides für Design und Entwicklung nachvollziehbar macht. Fehlt eine dieser Schichten, entsteht schnell wieder Inkonsistenz zwischen Produkten.

Der eigentliche Wert eines Design Systems mit Vue-Komponenten zeigt sich, sobald mehr als ein Projekt oder Team es verwendet. Eine einzelne Anwendung braucht kein separates Paket, interne Komponenten im selben Repository reichen aus. Sobald aber mehrere Vue-Anwendungen, etwa ein Shop-Frontend und ein internes Admin-Tool, dieselbe visuelle Sprache sprechen sollen, lohnt sich die Investition in ein eigenständig versioniertes, dokumentiertes Paket erheblich.

Ein häufiger Fehler beim Aufbau eines Design Systems mit Vue ist, mit den Komponenten zu beginnen, statt mit den Tokens. Wer zuerst zehn Buttons mit hart kodierten Hex-Farben baut und danach versucht, ein Theming-System nachzurüsten, muss jede Komponente einzeln anpassen. Der umgekehrte Weg, zuerst Tokens definieren, dann Komponenten darauf aufbauen, spart diesen nachträglichen Umbau vollständig.

2. Design-Tokens als einzige Wahrheitsquelle

Design-Tokens sind benannte, plattformunabhängige Werte für Farben, Abstände, Schriftgrößen und Radien, typischerweise in JSON oder YAML definiert und über ein Tool wie Style Dictionary in verschiedene Ausgabeformate transformiert, etwa CSS-Custom-Properties für Vue-Komponenten und gleichzeitig Swift- oder Kotlin-Konstanten für native Apps. Der entscheidende Vorteil: Eine Designentscheidung wird an genau einer Stelle getroffen und propagiert automatisch in alle Plattformen.

Für ein Design System mit Vue-Komponenten werden die generierten CSS-Custom-Properties direkt in den Komponenten referenziert, nie hart kodierte Werte. Das erlaubt Theme-Wechsel zur Laufzeit, ohne eine einzige Komponente neu zu kompilieren, und macht Design-Anpassungen für Whitelabel-Projekte trivial: Ein neues Set von Token-Werten reicht aus, die Vue-Komponenten selbst bleiben unverändert.


// tokens/color.json — Source of truth for design tokens, transformed by Style Dictionary
{
  "color": {
    "brand": {
      "primary": { "value": "#16a34a" },
      "primary-dark": { "value": "#064e3b" }
    },
    "text": {
      "default": { "value": "#1e293b" },
      "muted": { "value": "#64748b" }
    },
    "surface": {
      "default": { "value": "#ffffff" },
      "elevated": { "value": "#f8fafc" }
    }
  },
  "spacing": {
    "sm": { "value": "8px" },
    "md": { "value": "16px" },
    "lg": { "value": "24px" }
  }
}

// Generated output: dist/tokens.css (consumed by every Vue component)
// :root {
//   --color-brand-primary: #16a34a;
//   --color-text-default: #1e293b;
//   --spacing-md: 16px;
// }

3. Komponenten-API bewusst entwerfen

Die Props- und Slots-Signatur einer Vue-Komponente im Design System ist ein langfristiger Vertrag, nicht ein internes Implementierungsdetail. Sobald ein Button aus dem Design System in Dutzenden Vue-Anwendungen verwendet wird, wird jede Änderung an seiner Props-Signatur zu einer Breaking-Change-Kommunikation über Teamgrenzen hinweg. Deshalb sollte die API jeder Komponente von Anfang an auf Stabilität ausgelegt sein: benannte, semantische Prop-Werte wie variant="primary" statt beliebiger CSS-Klassen von außen, und explizite Slots für Erweiterbarkeit statt zusätzlicher Props für jeden Sonderfall.

Ein bewährtes Muster für Vue-Design-System-Komponenten ist, gestaltende Eigenschaften über streng typisierte Props zu steuern, während beliebiger Inhalt über Slots eingebracht wird. Ein Button-Komponente definiert etwa variant, size und disabled als Props mit begrenztem Wertebereich, während der eigentliche Button-Text über den Default-Slot kommt. Das verhindert, dass Konsumenten beliebige Tailwind-Klassen von außen injizieren und damit die visuelle Konsistenz unterlaufen, die das Design System eigentlich garantieren soll.


// DesignSystemButton.vue — API designed for stability, not for flexibility at any cost
<script setup lang="ts">
type Variant = 'primary' | 'secondary' | 'danger' | 'ghost';
type Size = 'sm' | 'md' | 'lg';

interface Props {
  variant?: Variant;
  size?: Size;
  disabled?: boolean;
  loading?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  variant: 'primary',
  size: 'md',
  disabled: false,
  loading: false,
});

const emit = defineEmits<{ click: [event: MouseEvent] }>();

// Only design-system-owned class names — consumers cannot inject arbitrary utility classes
const variantClass = computed(() => `ds-btn--${props.variant}`);
const sizeClass = computed(() => `ds-btn--${props.size}`);
</script>
<template>
  <button
    :class="['ds-btn', variantClass, sizeClass, { 'ds-btn--loading': loading }]"
    :disabled="disabled || loading"
    @click="emit('click', $event)"
  >
    <slot name="icon-left" />
    <slot />
    <slot name="icon-right" />
  </button>
</template>

4. Theming und Dark Mode über CSS-Variablen

Theming in einem Vue Design System sollte niemals über bedingte Props wie dark-mode="true" in jeder einzelnen Komponente gelöst werden. Der robustere Weg ist ein Wrapper-Attribut, etwa data-theme="dark" auf dem Root-Element der Anwendung, kombiniert mit CSS-Custom-Properties, die pro Theme unterschiedliche Werte annehmen. Jede Design-System-Komponente referenziert dieselben Variablennamen, unabhängig vom aktiven Theme, und muss selbst keine Kenntnis vom Theming-Mechanismus haben.

Für Whitelabel-Szenarien mit mehreren Marken funktioniert derselbe Mechanismus: Ein zusätzliches Attribut wie data-brand="acme" lädt einen anderen Satz von Token-Werten, ohne dass eine einzige Vue-Komponente angepasst werden muss. Diese Entkopplung zwischen visueller Erscheinung und Komponenten-Logik ist einer der wichtigsten Architekturentscheidungen beim Aufbau eines langlebigen Design Systems mit Vue.


/* tokens/theme.css — Same variable names, different values per theme attribute */
:root,
[data-theme="light"] {
  --color-surface-default: #ffffff;
  --color-text-default: #1e293b;
  --color-brand-primary: #16a34a;
}

[data-theme="dark"] {
  --color-surface-default: #0f172a;
  --color-text-default: #e2e8f0;
  --color-brand-primary: #4ade80;
}

/* Whitelabel: a second attribute swaps brand values independently of the theme */
[data-brand="acme"] {
  --color-brand-primary: #db2777;
}

/* Every Vue component references only the variable name, never a raw hex value */
.ds-btn--primary {
  background: var(--color-brand-primary);
  color: var(--color-surface-default);
}

5. Paketstruktur und Build-Setup

Ein Design System mit Vue-Komponenten wird üblicherweise als eigenständiges npm-Paket mit Vite als Library-Build ausgeliefert. Wichtig ist, Vue selbst als peerDependency zu deklarieren, nicht als reguläre Abhängigkeit, damit konsumierende Anwendungen ihre eigene Vue-Version mitbringen, statt eine zweite Vue-Instanz aus dem Design-System-Paket zu laden. Der Build erzeugt typischerweise sowohl ein ESM- als auch ein CommonJS-Bundle, um sowohl moderne Vite-Projekte als auch ältere Webpack-Setups zu unterstützen.

Die interne Struktur des Pakets trennt Tokens, Komponenten und Composables in eigene Unterordner mit eigenen Export-Einstiegspunkten. Das ermöglicht Tree-Shaking: Eine Anwendung, die nur den Button und das Input-Feld nutzt, muss nicht das komplette Design-System-Bundle laden, sondern importiert gezielt einzelne Komponenten über Subpath-Exports.


// vite.config.js — Library build for the design system package
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import dts from 'vite-plugin-dts';

export default defineConfig({
  plugins: [vue(), dts({ include: ['src'] })],
  build: {
    lib: {
      entry: {
        index: 'src/index.ts',
        button: 'src/components/Button/index.ts',
        input: 'src/components/Input/index.ts',
      },
      formats: ['es', 'cjs'],
    },
    rollupOptions: {
      // Vue must never be bundled into the design system itself
      external: ['vue'],
      output: { globals: { vue: 'Vue' } },
    },
  },
});

// package.json — vue declared as peer dependency, never a direct one
// "peerDependencies": { "vue": "^3.4.0" }

6. Versionierung und Breaking-Change-Kommunikation

Semantic Versioning ist für ein Design System mit Vue-Komponenten nicht optional, weil Dutzende konsumierende Anwendungen sich auf stabile Major-Versionen verlassen müssen. Jede Änderung an Props, Slots oder dem visuellen Erscheinungsbild einer Komponente muss klassifiziert werden: Ein neues optionales Prop ist ein Minor-Release, eine geänderte Prop-Semantik oder ein entfernter Slot ist ein Major-Release. Changesets oder ein vergleichbares Tool automatisiert diese Klassifizierung und generiert daraus einen konsistenten Changelog.

Bei Major-Releases eines Vue-Design-Systems empfiehlt sich eine Übergangsphase mit Codemods, die konsumierende Anwendungen automatisiert auf die neue API migrieren, statt jedes Team manuell durch die Breaking Changes zu führen. Ohne diese Investition bleiben Teams häufig auf veralteten Major-Versionen hängen, weil die manuelle Migration zu aufwendig erscheint, was langfristig die Fragmentierung zurückbringt, die das Design System eigentlich verhindern sollte.


#!/usr/bin/env bash
# Publishing a new design system version with automated changelog generation
set -euo pipefail

# Changesets reads the pending change files and determines the version bump
npx changeset version

# Classify: patch = bugfix, minor = new optional prop, major = removed slot/prop
npm run build
npm run test
npm run test:visual -- --ci

npx changeset publish
echo "[OK] Published new design system version with generated changelog"

7. Dokumentation mit Storybook automatisieren

Ohne lebendige Dokumentation verliert ein Design System mit Vue-Komponenten schnell an Akzeptanz, weil Entwickler lieber eine eigene Komponente bauen, als die Props einer undokumentierten bestehenden Komponente im Quellcode nachzuschlagen. Storybook ist für Vue-Design-Systeme der De-facto-Standard, weil es jede Komponente isoliert rendert, alle Props über Controls interaktiv veränderbar macht und Variant-Kombinationen automatisch aus TypeScript-Typen ableiten kann.

Wichtig ist, Storybook nicht nur als Showcase, sondern als Testinstrument zu nutzen: Visuelle Regressionstests über Chromatic oder Playwright erkennen unbeabsichtigte optische Änderungen an Design-System-Komponenten, bevor sie in Produktion in Dutzenden Anwendungen sichtbar werden. Die Dokumentation sollte zudem Verwendungsrichtlinien enthalten, nicht nur technische Props, etwa wann variant="danger" angemessen ist und wann nicht.

8. Governance: Beiträge und Akzeptanzkriterien

Ein Design System mit Vue-Komponenten ohne klaren Beitragsprozess wird entweder zum Flaschenhals, weil ein einzelnes Team jede Änderung reviewen muss, oder zum Wildwuchs, weil jedes Team eigene Komponenten ins gemeinsame Paket schiebt. Ein funktionierendes Governance-Modell definiert explizite Akzeptanzkriterien: Eine neue Komponente braucht Design-Abnahme, Barrierefreiheitsprüfung, Storybook-Dokumentation und mindestens zwei unabhängige konsumierende Anwendungen, bevor sie ins Kernpaket aufgenommen wird.

Viele erfolgreiche Design-System-Teams etablieren zusätzlich einen Office-Hour-Rhythmus oder ein RFC-Verfahren für größere API-Änderungen, sodass konsumierende Teams frühzeitig Einfluss nehmen können, statt erst bei der Migration von einem Breaking Change überrascht zu werden. Diese organisatorische Disziplin ist am Ende oft wichtiger für den langfristigen Erfolg als jede einzelne technische Entscheidung bei den Vue-Komponenten selbst.

9. Design-System-Ansätze im Vergleich

Es gibt unterschiedliche Reifegrade, ein Design System mit Vue-Komponenten zu betreiben, von der einfachen Komponentensammlung im Monorepo bis zum vollständig eigenständigen, unabhängig versionierten Produkt mit eigenem Team.

Ansatz Konsistenz Wartungsaufwand Eignung
Copy-Paste-Komponenten Gering Niedrig pro Kopie Einzelprojekt, Prototyp
Shared Folder im Monorepo Mittel Mittel Wenige verwandte Projekte
Eigenständiges npm-Paket Hoch Erhöht, dediziertes Team sinnvoll Mehrere unabhängige Produkte
Token-getriebenes System Sehr hoch Hoch, Tooling nötig Multi-Plattform, Whitelabel

Die meisten Vue-Organisationen wachsen organisch von der Copy-Paste-Phase über den Shared Folder bis zum eigenständigen npm-Paket. Ein Token-getriebenes System mit Style Dictionary lohnt sich erst, sobald Multi-Plattform-Konsistenz oder Whitelabeling explizit gefordert sind, weil das zusätzliche Tooling einen spürbaren Wartungsaufwand mit sich bringt.

Mironsoft

Design Systeme, Vue-Komponentenbibliotheken und Frontend-Konsistenz

Ein Design System, das Teams wirklich nutzen?

Wir bauen Design-Tokens, Vue-Komponenten-API und Storybook-Dokumentation als versioniertes Paket auf, das mehrere Anwendungen konsistent versorgt und langfristig wartbar bleibt.

Tokens & Theming

Design-Tokens mit Style Dictionary und Dark-Mode-fähigem Theming aufbauen

Komponenten-API

Stabile, typisierte Vue-Komponenten mit langfristig tragbarem Vertrag

Doku & Governance

Storybook-Setup und Beitragsprozess für nachhaltige Akzeptanz

10. Zusammenfassung

Ein Design System mit Vue-Komponenten ist mehr als eine Sammlung wiederverwendbarer Bausteine. Design-Tokens als einzige Wahrheitsquelle für Farben, Abstände und Radien verhindern hart kodierte Werte in Komponenten und ermöglichen Theming ohne Neukompilierung. Die Komponenten-API sollte von Beginn an auf Stabilität ausgelegt sein, mit begrenztem Wertebereich für Props und Slots für flexible Inhalte statt beliebiger externer CSS-Injektion.

Vue als peerDependency, ein Build mit ESM- und CommonJS-Ausgabe sowie Subpath-Exports für Tree-Shaking bilden das technische Fundament. Semantic Versioning mit klarer Breaking-Change-Kommunikation, automatisierte Storybook-Dokumentation mit visuellen Regressionstests und ein definierter Governance-Prozess sind am Ende genauso entscheidend wie die Codequalität der einzelnen Vue-Komponenten.

Design System mit Vue-Komponenten — Das Wichtigste auf einen Blick

Design-Tokens

Einzige Wahrheitsquelle für Farben und Abstände, generiert über Style Dictionary in CSS-Variablen.

Komponenten-API

Begrenzte, semantische Props statt beliebiger externer CSS-Klassen, Slots für Inhalte.

Versionierung

Semantic Versioning mit Changesets, Codemods für Major-Releases erleichtern Migrationen.

Dokumentation

Storybook mit Controls, visuellen Regressionstests und Verwendungsrichtlinien.

11. FAQ: Design System mit Vue-Komponenten

1Design System vs. Komponentenbibliothek?
Design System vereint Tokens, Komponenten und Dokumentation. Eine reine Bibliothek liefert nur die technischen Bausteine.
2Ab wann lohnt sich ein eigenes Paket?
Sobald mehr als eine Vue-Anwendung dieselbe visuelle Sprache nutzt.
3Warum Design-Tokens statt Hex-Werten?
Eine Wahrheitsquelle propagiert Änderungen automatisch in alle Plattformen und Komponenten.
4Warum Vue als peerDependency?
Verhindert eine zweite Vue-Instanz aus dem Paket und damit Reaktivitätsfehler und doppeltes Bundling.
5Wie verhindert man API-Missbrauch?
Begrenzte, semantische Props statt externer CSS-Klassen, Slots für flexible Inhalte.
6Wie funktioniert Theming ohne Props?
Über ein data-theme-Attribut am Root und CSS-Custom-Properties, unabhängig von den Komponenten selbst.
7Wie Breaking Changes kommunizieren?
Semantic Versioning mit Changesets und, wo möglich, Codemods für automatisierte Migration.
8Warum Storybook als Standard?
Isolierte Rendering, interaktive Controls und visuelle Regressionstests über Chromatic oder Playwright.
9Wer darf beitragen?
Jedes Team, sofern Design-Abnahme, A11y-Prüfung, Dokumentation und mehrere Konsumenten vorliegen.
10Token-System für ein einzelnes Projekt?
Selten sinnvoll, lohnt sich erst bei Multi-Plattform- oder Whitelabel-Anforderungen.