Assistants de préférences
Sept petits paquets par framework, chacun responsable d'une tâche utilisateur de bout en bout, plus une barre qui en assemble cinq. Vous avez déjà rencontré theme-picker; voici locale-picker, text-size-picker et motion-picker (préférences), share-picker et search-picker (actions), date-time-picker (une valeur de formulaire) et picker-bar.
Ce que vous allez construire
Un panneau de réglages où les utilisateurs choisissent leur langue et la taille du texte — des choix qui s'appliquent à tout le document, persistent entre les visites et vous coûtent deux composants et quelques lignes de CSS. Environ 15 minutes.
Avant de commencer
Terminez d'abord le tutoriel du framework pour votre pile. Les exemples ci-dessous sont en Svelte ; les assistants React, Vue, Angular, HTML, Nunjucks et Blazor correspondent contrat par contrat.
La forme qu'ils partagent
- Un bouton-icône sans tête qui ouvre une liste WAI-ARIA APG (ou, pour date-time-picker, une boîte de dialogue de sélection de date) — pas de
<select>natif, pour que chaque framework obtienne le même comportement clavier et les mêmes crochets de style. - Un crochet de classe par paquet (
.locale-picker,.text-size-picker,.share-picker,.date-time-picker), zéro CSS livré. - Sûr pour le SSR : les écritures dans le DOM n'ont lieu que dans le cycle de vie mount/effect.
- Propre pour l'i18n : chaque chaîne visible par l'utilisateur est une prop.
- Disponible pour Svelte (canonique), React, Vue, Angular, élément personnalisé HTML, Nunjucks et Blazor — le même contrat dans chacun.
theme-picker, locale-picker et text-size-picker possèdent chacun une
préférence utilisateur de bout en bout (sélection, application au DOM,
localStorage persistance facultative via la prop storageKey
). share-picker et date-time-picker sont de nature différente : share-picker possède une action — il n'applique rien au document et ne persiste rien — et date-time-picker possède une
valeur de formulaire, car une date dans un formulaire est une donnée, pas une préférence.
locale-picker — langue et direction
Laisse l'utilisateur choisir une locale, puis écrit lang et
dir sur la racine du document pour que votre bibliothèque i18n, votre CSS et les technologies d'assistance la suivent toutes. Le RTL est détecté automatiquement pour l'arabe, l'hébreu et d'autres écritures de droite à gauche. Il se concentre uniquement sur la signalisation — votre bibliothèque i18n gère la traduction.
<script>
import LocalePicker from "@lilydesignsystem/svelte-locale-picker";
let locale = $state("en-US");
</script>
<LocalePicker
label="Language"
locales={["en-US", "fr", "ar", "he", "ja"]}
bind:value={locale}
storageKey="my-app-locale"
/>
Les options sont étiquetées à partir d'une table intégrée de noms de locales (remplaçable via localeLabels), chaque option porte son propre attribut
lang pour que les lecteurs d'écran prononcent « Français » en français, et les codes à tiret bas comme en_US
sont convertis sans perte vers BCP 47 et inversement en-US. Branchez
onChange (ou la valeur liée) sur i18next, Paraglide, vue-i18n ou ce que vous utilisez.
text-size-picker — taille contrôlée par le lecteur
Un gain d'accessibilité qui prend quelques minutes : l'assistant définit
data-text-size="{slug}" sur la racine du document et votre CSS associe chaque valeur à une taille.
<script>
import TextSizePicker from "@lilydesignsystem/svelte-text-size-picker";
</script>
<TextSizePicker
label="Text size"
sizes={["small", "medium", "large", "x-large"]}
storageKey="my-app-text-size"
/>
:root[data-text-size="small"] { font-size: 87.5%; }
:root[data-text-size="medium"] { font-size: 100%; }
:root[data-text-size="large"] { font-size: 112.5%; }
:root[data-text-size="x-large"] { font-size: 125%; }
Dimensionnez votre mise en page en rem et toute l'application s'adapte au choix de l'utilisateur. Les étiquettes sont formées à partir des slugs avec une majuscule initiale (« X Large ») ou remplacées avec sizeLabels.
Vérifiez votre travail : choisissez « Large » dans le sélecteur et le texte de la page grandit. Rechargez — il est toujours grand : le choix a été conservé dans
localStorage. Passez votre sélecteur de langue à l'arabe et
dir="rtl" est défini sur le document automatiquement.
share-picker — envoyer cette page
Un bouton à un seul glyphe qui ouvre la feuille de partage native de l'appareil quand elle existe, et sinon se rabat sur une liste de destinations que vous fournissez, plus une action de copie de l'URL. Il ne livre aucune URL de réseau social — quels réseaux appartiennent à votre produit est votre décision, pas celle du design system.
<script>
import SharePicker from "@lilydesignsystem/svelte-share-picker";
const targets = [
{ id: "mastodon", label: "Mastodon",
href: (url, title) => `https://mastodon.social/share?text=${encodeURIComponent(title)}%20${encodeURIComponent(url)}` },
{ id: "email", label: "Email",
href: (url, title) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(url)}`, newTab: false },
];
</script>
<SharePicker
label="Share this page"
title="An article worth reading"
{targets}
copyLabel="Copy link"
copiedLabel="Link copied"
/>
url vaut par défaut location.hrefdonc le cas courant n'a besoin d'aucun câblage. Forcez un chemin avec strategy="list" ou
strategy="native" quand vous avez besoin d'un comportement cohérent entre plateformes pour des tests ou des captures d'écran.
date-time-picker — une date, une heure, ou les deux
Un champ de texte dans lequel vous pouvez taper, plus un bouton-icône qui ouvre une boîte de dialogue de sélection de date WAI-ARIA APG. Correct pour la locale par construction — les noms des mois, les noms des jours, le premier jour de la semaine et l'horloge 12 ou 24 heures viennent tous de Intl — et la valeur est toujours une chaîne ISO triable et sans fuseau horaire : "2026-03-15" pour
mode="date", "09:30" pour
mode="time", "2026-03-15T09:30" pour
mode="datetime".
<script>
import DateTimePicker from "@lilydesignsystem/svelte-date-time-picker";
let appointment = $state("");
</script>
<DateTimePicker
inputId="appointment"
name="appointment"
label="Choose an appointment date"
locale="en-GB"
bind:value={appointment}
labels={{
previousYear: "Previous year",
previousMonth: "Previous month",
nextMonth: "Next month",
nextYear: "Next year",
confirm: "OK",
cancel: "Cancel",
}}
/>
La valeur ISO est identique à ce qu'envoie <input type="date">
donc vous pouvez échanger le contrôle natif sans toucher à votre backend.
motion-picker — respecter la réduction des animations
L'assistant définit data-motion="{slug}" sur la racine du document. Sa première valeur vient du réglage
prefers-reduced-motion du système d'exploitation du visiteur — toujours, sans indicateur d'adhésion, car le mouvement est un vrai besoin d'accessibilité (WCAG 2.3.3). Votre CSS et vos scripts décident de ce qui est supprimé.
<script>
import MotionPicker from "@lilydesignsystem/svelte-motion-picker";
</script>
<MotionPicker
label="Motion"
motions={["no-preference", "reduce"]}
storageKey="my-app-motion"
/>
:root[data-motion="reduce"] *,
:root[data-motion="reduce"] *::before,
:root[data-motion="reduce"] *::after {
animation: none !important;
transition: none !important;
scroll-behavior: auto !important;
}
search-picker — une boîte de recherche qui ne gêne pas
Un bouton-icône qui ouvre un champ de recherche. Appuyer sur Entrée, ou sur le bouton ⏎ à côté du champ, navigue par une simple requête GET vers
/?<text> (le texte est rogné et encodé en URI ; une requête vide ne mène nulle part). Ses trois noms accessibles sont obligatoires, car l'assistant ne livre pas d'anglais.
<script>
import SearchPicker from "@lilydesignsystem/svelte-search-picker";
import { goto } from "$app/navigation";
</script>
<SearchPicker
label="Search this site"
inputLabel="Search terms"
submitLabel="Search"
placeholder="Search…"
action="/search"
navigate={(href) => goto(href)}
/>
action change le chemin (/search?foo), et
navigate garde la navigation dans l'application ; sans lui, l'assistant appelle location.assign.
picker-bar — toute la ligne d'en-tête d'un coup
picker-bar rend la recherche, le thème, la locale, la taille du texte et le partage sur une ligne, avec l'ensemble complet des thèmes de référence et l'échelle de texte à sept pas déjà câblés. Chaque nom accessible arrive dans un seul objet
labels obligatoire.
<script>
import PickerBar from "@lilydesignsystem/svelte-picker-bar";
</script>
<PickerBar
labels={{
search: "Search", searchInput: "Search terms", searchSubmit: "Search",
theme: "Theme", locale: "Language", textSize: "Text size", share: "Share",
}}
themesUrl="/themes/"
locales={["en", "fr", "es"]}
shareTargets={targets}
/>
Atteignez n'importe quel sélecteur enveloppé avec searchProps,
themeProps, localeProps,
textSizeProps et shareProps.
Les infobulles sont intégrées
Chaque sélecteur affiche son étiquette dans une infobulle quand le pointeur repose sur son bouton ou que le bouton a le focus clavier. L'infobulle reste pendant que le pointeur se déplace dessus, Échap la ferme où que se trouve le focus, et elle ne s'affiche jamais tant que la fenêtre du sélecteur est ouverte. Elle porte le même texte que le nom accessible du bouton, donc rien à configurer ni à traduire deux fois ; les thèmes de référence la stylent.
Un panneau de réglages en un seul endroit
Les quatre assistants de préférences se composent naturellement :
<fieldset class="fieldset">
<legend>Preferences</legend>
<ThemePicker label="Theme" themesUrl="/themes/" themes={themes} storageKey="pref-theme" />
<LocalePicker label="Language" locales={locales} storageKey="pref-locale" />
<TextSizePicker label="Text size" sizes={sizes} storageKey="pref-text-size" />
<MotionPicker label="Motion" motions={motions} storageKey="pref-motion" />
</fieldset>
Vérifié : les extraits de locale-picker, text-size-picker, share-picker, date-time-picker et du panneau combiné ont été compilés individuellement contre les paquets 0.1.1 publiés, via
svelte/server (2026-08-29) ; les extraits de motion-picker, search-picker et picker-bar ont été rendus contre les composants des paquets eux-mêmes le 2026-10-06.
Où les trouver
# one directory per package in the monorepo, e.g.
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-svelte-theme-picker
# or lily-design-system-react-theme-picker, -vue- / -angular- / -html- / -web-components- / -nunjucks- / -blazor-
Chaque paquet a sa propre spec, des tests associés aux clauses de la spec, des exemples exécutables (y compris des motifs de cookies pour le SSR) et un pipeline de build + publication. Les paquets Svelte sont canoniques ; en cas de doute, leurs contrats l'emportent.
Étapes suivantes
- Catalogue de composants — la référence complète des 571 composants.
- Aide — dépannage et FAQ.
- Pourquoi Lily — et comment soutenir le projet.
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.