Tutorial de Vue

Componentes de ficheiro único do Vue 3 com props tipadas, defineModel ligação bidirecional e passagem de v-bind="$attrs" .

O que vai construir

Um pequeno formulário de contacto — campo com etiqueta, botão de envio, v-model ligação, comportamento real de teclado e leitor de ecrã — primeiro simples, depois estilizado, em cerca de 10 minutos.

Antes de começar

Precisa de git, Node 22 ou posterior e pnpm 10 ou posterior. Qualquer projeto Vue 3 serve — Nuxt, Vite ou Vue simples.

Passo 1 — Obter o código

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

Os componentes são ficheiros planos em components/ — Button.vue, TextInput.vue — cada um com o seu teste, a sua story e a sua documentação ao lado. Copie os ficheiros de que precisa, ou traga o repositório.

Passo 2 — O seu primeiro componente

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

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

Renderiza <button class="button" type="button">. As props correspondem às dos outros frameworks: type, disabled, pressed, label, mais passagem de atributos para tudo o resto.

Passo 3 — Componha um pequeno formulário

<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 recebe o label como a sua própria prop em vez de um componente de etiqueta aninhado — passe-a uma vez, em Fielde TextInputcorrespondente de label fornece o nome acessível.

Verificado em 2026-08-29: um rascunho anterior aninhava um componente Label dentro de Field, o que renderizava duas etiquetas (uma vazia) porque Field já renderiza a sua própria a partir da entrada label prop — descoberto ao compilar o excerto exato. A rota A rota composta do formulário de contacto é o mesmo padrão, exercitado com testes e2e e axe reais.

TextInput usa defineModel, pelo que um simples v-model funciona logo.

Verifique o seu trabalho: execute a aplicação e o formulário parece simples — exatamente como pretendido: o estilo ainda está por vir. Prima Tab: o foco percorre cada controlo, a etiqueta é anunciada e o envio funciona. O comportamento está feito; o aspeto é seu e é o passo seguinte.

Passo 4 — Estilize-o

Estilize os ganchos de classe — .button, .text-input, .label, .field — na sua folha de estilos, ou ligue um tema pronto em index.html / nuxt.config:

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

Passo 5 — Veja tudo a funcionar

A aplicação de exemplo Nuxt é o catálogo completo estilizado e demonstrado, com Playwright e2e e uma linha de base 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

Passos seguintes

Dúvidas pelo caminho? A página de ajuda está cheia de respostas — e se algum passo puder ser mais claro, diga-nos e melhoraremos o tutorial com todo o gosto.