Pomocníci pro předvolby

Sedm malých balíčků na framework, z nichž každý vlastní jednu uživatelskou úlohu od začátku do konce, plus lišta, která pět z nich sestavuje. Už jste se setkali s theme-picker; tady jsou locale-picker, text-size-picker a motion-picker (předvolby), share-picker a search-picker (akce), date-time-picker (hodnota formuláře) a picker-bar.

Co vytvoříte

Panel nastavení, kde uživatelé volí jazyk a velikost textu — volby, které platí pro celý dokument, přetrvávají mezi návštěvami a stojí vás dvě komponenty a pár řádků CSS. Zhruba 15 minut.

Než začnete

Nejprve dokončete návod k frameworku pro svůj stack. Ukázky níže jsou ve Svelte; pomocníci pro React, Vue, Angular, HTML, Nunjucks a Blazor jim odpovídají smlouvu po smlouvě.

Tvar, který sdílejí

  • Bezhlavé tlačítko s ikonou, které otevírá listbox WAI-ARIA APG (nebo u date-time-picker dialog pro výběr data) — žádný nativní <select>, takže každý framework získá stejné chování klávesnice a stylovací háčky.
  • Jeden třídní háček na balíček (.locale-picker, .text-size-picker, .share-picker, .date-time-picker), nula dodaného CSS.
  • Bezpečné pro SSR: zápisy do DOM probíhají jen v životním cyklu mount/effect.
  • Čisté pro i18n: každý řetězec viditelný uživateli je prop.
  • K dispozici pro Svelte (kanonický), React, Vue, Angular, vlastní prvek HTML, Nunjucks a Blazor — v každém stejná smlouva.

theme-picker, locale-picker a text-size-picker vlastní každý jednu uživatelskou předvolbu od začátku do konce (výběr, aplikace na DOM, volitelné localStorage trvalé uložení přes prop storageKey ). share-picker a date-time-picker jsou jiného druhu: share-picker vlastní akci — nic nepoužívá na dokument a nic neukládá — a date-time-picker vlastní hodnotu formuláře, protože datum ve formuláři jsou data, nikoli předvolba.

locale-picker — jazyk a směr

Nechá uživatele vybrat národní prostředí a potom zapíše lang a dir na kořen dokumentu, aby ho následovala vaše knihovna i18n, vaše CSS i asistivní technologie. RTL se zjišťuje automaticky pro arabštinu, hebrejštinu a další písma psaná zprava doleva. Soustředí se čistě na signalizaci — překlad zajišťuje vaše knihovna i18n.

<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"
/>

Volby jsou popsány z vestavěné tabulky názvů národních prostředí (lze přepsat přes localeLabels), každá volba nese vlastní atribut lang , aby čtečky obrazovky vyslovily „Français“ francouzsky, a kódy s podtržítkem jako en_US se bezeztrátově převádějí do BCP 47 a zpět en-US. Připojte onChange (nebo svázanou hodnotu) k i18next, Paraglide, vue-i18n nebo čemukoli, co používáte.

text-size-picker — velikost ovládaná čtenářem

Zisk pro přístupnost za pár minut: pomocník nastaví data-text-size="{slug}" na kořen dokumentu a vaše CSS přiřadí každé hodnotě velikost.

<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%; }

Rozměrujte rozvržení v rem a celá aplikace se přizpůsobí volbě uživatele. Štítky se tvoří ze slugů s velkým počátečním písmenem („X Large“) nebo se přepisují přes sizeLabels.

Zkontrolujte svou práci: vyberte „Large“ ve výběru a text stránky se zvětší. Znovu načtěte — pořád je velký: volba se trvale uložila do localStorage. Přepněte výběr jazyka na arabštinu a dir="rtl" se na dokument nastaví automaticky.

share-picker — odeslat tuto stránku

Tlačítko s jedním glyfem, které otevře nativní sdílecí list zařízení tam, kde existuje, a jinak se vrátí k seznamu cílů, které dodáte, plus akci kopírování URL. Nedodává žádné URL sociálních sítí — které sítě patří do vašeho produktu, je vaše rozhodnutí, ne rozhodnutí designového systému.

<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 je ve výchozím stavu location.href, takže běžný případ nepotřebuje žádné zapojení. Vynuťte cestu pomocí strategy="list" nebo strategy="native" když potřebujete konzistentní chování napříč platformami pro testy nebo snímky obrazovky.

date-time-picker — datum, čas nebo obojí

Textové pole, do kterého lze psát, plus tlačítko s ikonou, které otevře dialog pro výběr data WAI-ARIA APG. Správné pro dané prostředí už z konstrukce — názvy měsíců, názvy dnů, první den týdne a 12- či 24hodinové hodiny pocházejí z Intl — a hodnota je vždy seřaditelný řetězec ISO bez časového pásma: "2026-03-15" pro mode="date", "09:30" pro mode="time", "2026-03-15T09:30" pro 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",
  }}
/>

Hodnota ISO je shodná s tím, co <input type="date"> odesílá, takže nativní ovládací prvek můžete vyměnit dovnitř i ven, aniž byste sáhli na backend.

motion-picker — respektujte omezený pohyb

Pomocník nastaví data-motion="{slug}" na kořen dokumentu. Jeho první hodnota pochází z nastavení prefers-reduced-motion operačního systému návštěvníka — vždy, bez příznaku k aktivaci, protože pohyb je skutečná potřeba přístupnosti (WCAG 2.3.3). Vaše CSS a skripty rozhodují, co se potlačí.

<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 — vyhledávací pole, které nepřekáží

Tlačítko s ikonou, které otevře vyhledávací pole. Stisk Return nebo tlačítka ⏎ vedle pole přejde obyčejným požadavkem GET na /?<text> (text se ořízne a zakóduje jako URI; prázdný dotaz nevede nikam). Jeho tři přístupné názvy jsou povinné, protože pomocník nedodává angličtinu.

<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 mění cestu (/search?foo) a navigate drží navigaci uvnitř aplikace; bez něj pomocník volá location.assign.

picker-bar — celý řádek záhlaví najednou

picker-bar vykresluje hledání, téma, národní prostředí, velikost textu a sdílení v jednom řádku, s úplnou sadou referenčních témat a sedmistupňovou škálou textu předem zapojenými. Každý přístupný název přichází v jednom povinném objektu labels .

<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}
/>

Dostanete se k libovolnému obalenému výběru přes searchProps, themeProps, localeProps, textSizeProps a shareProps.

Popisky jsou vestavěné

Každý výběr zobrazí svůj štítek v popisku, když ukazatel spočine na jeho tlačítku nebo má tlačítko fokus klávesnice. Popisek zůstane, když ukazatel přejede na něj, Escape ho zavře, ať je fokus kdekoli, a nikdy se nezobrazí, dokud je otevřené vyskakovací okno výběru. Nese stejný text jako přístupný název tlačítka, takže není co konfigurovat ani dvakrát překládat; referenční témata ho ostylují.

Panel nastavení na jednom místě

Čtyři pomocníci pro předvolby se přirozeně skládají:

<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>

Ověřeno: ukázky pro locale-picker, text-size-picker, share-picker, date-time-picker a kombinovaný panel byly zkompilovány jednotlivě proti publikovaným 0.1.1 balíčkům přes svelte/server (2026-08-29); ukázky pro motion-picker, search-picker a picker-bar byly vykresleny proti vlastním komponentám balíčků 2026-10-06.

Kde je získat

# 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-

Každý balíček má vlastní spec, testy navázané na klauzule specu, spustitelné příklady (včetně vzorů cookies pro SSR) a pipeline pro sestavení a publikaci. Balíčky Svelte jsou kanonické; v případě pochybností vítězí jejich smlouvy.

Další kroky

Otázky cestou? Stránka nápovědy je plná odpovědí — a pokud by nějaký krok mohl být jasnější, dejte nám vědět a návod rádi vylepšíme.