Tutoriel Angular
Composants autonomes Angular 20 — entrées signal, détection des changements OnPush, modèles en ligne, zéro NgModules, zéro CSS.
Ce que vous allez construire
Un petit formulaire de contact — champ avec étiquette, bouton d'envoi, liaison bidirectionnelle, 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 Angular 20 convient — Angular CLI ou Analog.
Étape 1 — Récupérer le code
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-angular-headless
pnpm install
pnpm test # vitest + TestBed, all 571 components
pnpm run build-storybook
Les composants sont des fichiers à plat dans components/ —
Button.ts, TextInput.ts — chacun est un composant autonome avec un modèle en ligne, plus son spec et sa story. Le barrel
index.ts réexporte chaque composant ; pnpm build
produit un paquet au format Angular Package Format via ng-packagr.
Étape 2 — Votre premier composant
import { Component } from "@angular/core";
import { Button } from "@lilydesignsystem/angular-headless";
@Component({
selector: "app-save-bar",
standalone: true,
imports: [Button],
template: `<lily-button (click)="save()">Save</lily-button>`,
})
export class SaveBar {
save() { console.log("saved"); }
}
Chaque composant déclare un sélecteur lily-* et rend l'élément sémantique avec son crochet de classe —
<button class="button" type="button"> ici. Les entrées sont basées sur les signaux : label() pour un aria-label
pour remplacer, className() pour ajouter des classes.
Étape 3 — Composer un petit formulaire
import { Component, signal } from "@angular/core";
import { Form, Field, TextInput, Button } from "@lilydesignsystem/angular-headless";
@Component({
selector: "app-contact-form",
standalone: true,
imports: [Form, Field, TextInput, Button],
template: `
<lily-form label="Contact form" (submit)="handleSubmit($event)">
<lily-field label="Full name" [required]="true">
<lily-text-input id="name" label="Full name" [(value)]="name" />
</lily-field>
<lily-button type="submit">Save</lily-button>
</lily-form>
`,
})
export class ContactForm {
name = signal("");
}
lily-field prend l'étiquette visible comme sa propre entrée
label plutôt qu'un composant d'étiquette imbriqué — transmettez-la une fois, sur le champ, et le lily-text-inputcorrespondant de
label fournit le nom accessible. Les composants de type saisie exposent des valeurs model() donc la liaison bidirectionnelle banana-box [(value)]
fonctionne immédiatement — compatible zoneless de bout en bout.
Vérifié le 2026-08-29 : un brouillon précédent imbriquait un composant Label distinct dans lily-field, ce qui rendait deux étiquettes (une vide) parce que
lily-field rend déjà la sienne à partir de l'entrée
label — découvert en vérifiant le code source du composant.
La route composée du formulaire de contact
suit le même motif, éprouvé par de vrais tests e2e et axe.
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 styles.css, ou ajoutez un thème prêt à l'emploi au tableau styles dans
angular.json / liez-le dans index.html:
<link rel="stylesheet" href="/themes/adobe-spectrum.css" />
Étape 5 — Voir le tout fonctionner
L'application d'exemple Angular + Analog montre le catalogue complet avec un routage par fichiers et Vite :
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-angular-examples
pnpm install && pnpm run dev
Étapes suivantes
- Thèmes — changement à l'exécution avec l'assistant theme-picker d'Angular.
- Assistants de préférences — langue et taille du texte.
- Catalogue de composants — propriétés, ARIA et clavier par composant.
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.