Tutoriel Vue

Composants à fichier unique Vue 3 avec props typées, defineModel liaison bidirectionnelle et transmission de v-bind="$attrs" .

Ce que vous allez construire

Un petit formulaire de contact — champ avec étiquette, bouton d'envoi, v-model liaison, vrai comportement clavier et lecteur d'écran — d'abord nu, puis stylé, en 10 minutes environ.

Avant de commencer

Il vous faut git, Node 22 ou plus récent et pnpm 10 ou plus récent. Tout projet Vue 3 convient — Nuxt, Vite ou Vue simple.

Étape 1 — Récupérer le code

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

Les composants sont des fichiers à plat dans components/ — Button.vue, TextInput.vue — chacun avec son test, sa story et sa documentation à côté. Copiez les fichiers dont vous avez besoin, ou ramenez le dépôt.

Étape 2 — Votre premier composant

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

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

Rend <button class="button" type="button">. Les props correspondent aux autres frameworks : type, disabled, pressed, label, plus la transmission d'attributs pour tout le reste.

Étape 3 — Composer un petit formulaire

<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 prend le label comme sa propre prop plutôt qu'un composant d'étiquette imbriqué — transmettez-la une fois, sur Fieldet TextInputcorrespondant de label fournit le nom accessible.

Vérifié le 2026-08-29 : un brouillon précédent imbriquait un composant Label à l'intérieur de Field, ce qui rendait deux étiquettes (une vide) parce que Field rend déjà la sienne à partir de l'entrée label prop — découvert en compilant l'extrait exact. La route La route composée du formulaire de contact suit le même motif, éprouvé par de vrais tests e2e et axe.

TextInput utilise defineModel, donc un simple v-model fonctionne tout de suite.

Vérifiez votre travail : lancez l'application et le formulaire paraît nu — exactement comme prévu : le style reste à venir. Appuyez sur Tab: le focus traverse chaque contrôle, l'étiquette est annoncée et l'envoi fonctionne. Le comportement est fait ; l'apparence est la vôtre et c'est l'étape suivante.

Étape 4 — Le styler

Stylez les crochets de classe — .button, .text-input, .label, .field — dans votre feuille de style, ou liez un thème prêt à l'emploi dans index.html / nuxt.config:

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

Étape 5 — Voir le tout fonctionner

L'application d'exemple Nuxt est le catalogue complet stylé et démontré, avec Playwright e2e et une référence axe-core :

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

Étapes suivantes

Des questions en chemin ? La page d'aide regorge de réponses — et si une étape peut être plus claire, dites-le-nous et nous améliorerons volontiers le tutoriel.