Vue-Tutorial

Vue-3-Single-File-Komponenten mit typisierten Props, defineModel Zwei-Wege-Bindung und v-bind="$attrs" -Durchreichung.

Was du baust

Ein kleines Kontaktformular — beschriftetes Eingabefeld, Absenden-Schaltfläche, v-model -Bindung, echtes Tastatur- und Screenreader-Verhalten — zuerst nackt, dann gestaltet, in etwa 10 Minuten.

Bevor du anfängst

Du brauchst git, Node 22 oder neuer und pnpm 10 oder neuer. Jedes Vue-3-Projekt funktioniert — Nuxt, Vite oder reines Vue.

Schritt 1 — Den Code holen

git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-vue-headless
pnpm install
pnpm test        # vitest + @testing-library/vue
pnpm run storybook   # browse all 571 components

Die Komponenten sind flache Dateien in components/ — Button.vue, TextInput.vue — jede mit ihrem Test, ihrer Story und ihrer Dokumentation daneben. Kopiere die benötigten Dateien, oder hole das Repo.

Schritt 2 — Deine erste Komponente

<script setup>
import Button from "lily-design-system-vue-headless/components/Button.vue";
</script>

<template>
  <Button @click="save">Save</Button>
</template>

Rendert <button class="button" type="button">. Die Props entsprechen den anderen Frameworks: type, disabled, pressed, label, plus Attribut-Fall-through für alles andere.

Schritt 3 — Ein kleines Formular zusammensetzen

<script setup>
import { ref } from "vue";
import Form from ".../components/Form.vue";
import Field from ".../components/Field.vue";
import TextInput from ".../components/TextInput.vue";
import Button from ".../components/Button.vue";

const name = ref("");
</script>

<template>
  <Form @submit="handleSubmit">
    <Field label="Full name" required>
      <TextInput id="name" label="Full name" v-model="name" required />
    </Field>
    <Button type="submit">Save</Button>
  </Form>
</template>

Field nimmt das sichtbare label als eigene Prop statt als verschachtelte Label-Komponente — gib es einmal an, bei Fieldund TextInputvon label liefert den zugänglichen Namen.

Geprüft am 2026-08-29: ein früherer Entwurf verschachtelte eine separate Label innerhalb von Field, was zwei Labels (eines leer) rendert, weil Field bereits ein eigenes aus dem label -Prop — durch Kompilieren des exakten Snippets entdeckt. Die Die zusammengesetzte Kontaktformular-Route ist dasselbe Muster, getestet mit echten e2e- und axe-Tests.

TextInput verwendet defineModel, daher funktioniert ein einfaches v-model sofort.

Prüfe deine Arbeit: Starte die App, und das Formular sieht schlicht aus — genau wie beabsichtigt: Die Gestaltung kommt noch. Drücke Tab: Der Fokus wandert durch jedes Bedienelement, das Label wird angesagt und das Absenden funktioniert. Das Verhalten ist fertig; das Aussehen gehört dir und kommt als Nächstes.

Schritt 4 — Gestalten

Gestalte die Klassen-Hooks — .button, .text-input, .label, .field — in deinem Stylesheet, oder binde ein fertiges Theme ein in index.html / nuxt.config:

<link rel="stylesheet" href="/themes/nord.css" />

Schritt 5 — Alles in Aktion sehen

Nuxt-Beispiel-App ist der vollständige Katalog gestaltet und demonstriert, mit Playwright-e2e und einer axe-core-Baseline:

git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-vue-nuxt-examples
pnpm install && pnpm run dev

Nächste Schritte

Fragen unterwegs? Die Hilfeseite steckt voller Antworten — und wenn ein Schritt klarer sein könnte, sag es uns und wir verbessern das Tutorial gern.