偏好輔助工具

每個框架七個細套件,各自由頭到尾負責一個使用者工作,另外有一條組合其中五個嘅工具列。你已經認識 theme-picker;呢度係 locale-picker、text-size-picker 同 motion-picker(偏好)、share-picker 同 search-picker(動作)、date-time-picker(表單值),以及 picker-bar。

你會建立啲乜

一個設定面板,畀使用者揀佢哋嘅語言同文字大細 — 呢啲選擇適用於整份文件,喺不同訪問之間保留,而且只需要兩個元件同幾行 CSS。大約 15 分鐘。

開始之前

先完成 框架教學 嚟配合你嘅技術棧。以下範例係 Svelte;React、Vue、Angular、HTML、Nunjucks 同 Blazor 輔助工具逐個合約同佢對應。

佢哋共用嘅形狀

  • 一個打開 WAI-ARIA APG 清單方塊(或者 date-time-picker 嘅日期選擇器對話框)嘅無頭圖示按鈕 — 冇原生 <select>,所以每個框架都有一致嘅鍵盤行為同樣式掛鉤。
  • 每個套件一個類別掛鉤(.locale-picker, .text-size-picker, .share-picker, .date-time-picker),零 CSS 附帶。
  • SSR 安全:DOM 寫入只喺 mount/effect 生命週期入面發生。
  • 對 i18n 乾淨:每個使用者睇到嘅字串都係屬性。
  • 適用於 Svelte(標準)、React、Vue、Angular、HTML 自訂元素、Nunjucks 同 Blazor — 每個都係同一個合約。

theme-picker、locale-picker 同 text-size-picker 各自由頭到尾擁有一個使用者 偏好 (選擇、套用到 DOM、可選嘅 localStorage 持久性 storageKey 透過屬性)。share-picker 同 date-time-picker 性質唔同:share-picker 擁有一個 動作 — 佢唔套用任何嘢到文件,亦唔持久化任何嘢 — 而 date-time-picker 擁有一個 表單值,因為表單入面嘅日期係資料,唔係偏好。

locale-picker — 語言同方向

讓使用者揀地區設定,然後寫入 lang 同 dir 到文件根部,令你嘅 i18n 函式庫、CSS 同輔助科技全部跟隨。阿拉伯文、希伯來文同其他由右至左嘅文字會自動偵測 RTL。佢只專注於發出訊號 — 翻譯由你嘅 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"
/>

選項標籤取自內置嘅地區名稱表(可以透過 localeLabels覆蓋),每個選項都有自己嘅 lang 屬性,令螢幕閱讀器用法文讀出「Français」,而帶底線嘅代碼例如 en_US 可以無損咁來回轉換成 BCP 47 en-US。將 onChange (或者綁定嘅值)接駁到 i18next、Paraglide、vue-i18n 或者你用緊嘅任何嘢。

text-size-picker — 由讀者控制嘅大細

幾分鐘就做到嘅無障礙勝利:輔助工具喺文件根部設定 data-text-size="{slug}" ,而你嘅 CSS 將每個值對應到大細。

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

用 rem 設定你版面嘅大細,整個應用程式就會跟使用者嘅選擇縮放。標籤由 slug 轉成首字母大寫(「X Large」),或者用 sizeLabels.

檢查你嘅成果: 喺選擇器揀「Large」,頁面文字就會變大。重新載入 — 仍然係大:選擇已經持久化到 localStorage。將你嘅語言選擇器切換到阿拉伯文, dir="rtl" 就會自動設定喺文件上。

share-picker — 傳送呢一頁

一個單一圖示按鈕,有原生分享表嘅裝置上會打開裝置嘅分享表,否則就退回你提供嘅目的地清單,另外加複製網址動作。佢冇附帶社交網絡網址 — 邊啲網絡屬於你嘅產品由你話事,而唔係設計系統。

<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 預設係 location.href所以常見情況唔需要接線。需要跨平台一致行為作測試或截圖嘅時候,可以用 strategy="list" 或者 strategy="native" 強制指定路徑。

date-time-picker — 日期、時間,或者兩者

一個可以打字嘅文字欄位,加一個打開 WAI-ARIA APG 日期選擇器對話框嘅圖示按鈕。設計上地區正確 — 月份名稱、星期名稱、每週第一日,同 12 或 24 小時時鐘全部來自 Intl — 而值永遠係可排序、冇時區嘅 ISO 字串: "2026-03-15" 用於 mode="date", "09:30" 用於 mode="time", "2026-03-15T09:30" 用於 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",
  }}
/>

ISO 值同 <input type="date"> 提交嘅一樣,所以你可以喺唔改動後端嘅情況下,將原生控制項換入或者換出。

motion-picker — 尊重減少動態

輔助工具喺文件根部設定 data-motion="{slug}" 。佢嘅第一個值來自訪客作業系統嘅 prefers-reduced-motion 設定 — 永遠如此,冇選擇啟用嘅旗標,因為動態係真正嘅無障礙需要(WCAG 2.3.3)。你嘅 CSS 同腳本決定壓抑啲乜。

<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 — 唔阻手阻腳嘅搜尋框

一個打開搜尋欄位嘅圖示按鈕。按 Return,或者欄位旁邊嘅 ⏎ 按鈕,會以普通 GET 請求導航去 /?<text> (文字會被修剪同 URI 編碼;空白查詢唔會去任何地方)。佢嘅三個無障礙名稱係必需嘅,因為輔助工具唔附帶英文。

<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 更改路徑(/search?foo),而 navigate 將導航保持喺應用程式內;冇佢嘅話,輔助工具會呼叫 location.assign.

picker-bar — 一次過搞掂成行標題列

picker-bar 喺一行入面渲染搜尋、主題、地區設定、文字大細同分享,預先接駁好完整嘅參考主題同七級文字比例。每個無障礙名稱都喺一個必需嘅 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}
/>

透過 searchProps, themeProps, localeProps, textSizeProps 同 shareProps.

入面嘅

每個選擇器喺指標停留喺佢嘅按鈕上或者按鈕有鍵盤焦點嘅時候,都會喺工具提示入面顯示佢嘅標籤。指標移到工具提示上嗰陣佢會繼續顯示,Escape 無論焦點喺邊度都可以關閉佢,而且當選擇器嘅彈出視窗打開嘅時候佢永遠唔會顯示。佢帶有同按鈕無障礙名稱一樣嘅文字,所以冇嘢需要設定,亦冇嘢要翻譯兩次;參考主題會為佢加樣式。

設定面板集中一處

四個偏好輔助工具自然咁組合:

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

已驗證: locale-picker、text-size-picker、share-picker、date-time-picker 同組合面板嘅片段,已經逐一對照已發佈嘅 0.1.1 套件編譯,透過 svelte/server (2026-08-29);motion-picker、search-picker 同 picker-bar 嘅片段喺 2026-10-06 對照套件自己嘅元件渲染。

喺邊度攞

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

每個套件都有自己嘅 spec、對應 spec 條款嘅測試、可運行嘅範例(包括 SSR cookie 模式),以及建置 + 發佈流程。Svelte 套件係標準;有疑問嘅時候,以佢哋嘅合約為準。

下一步

一路上有問題? 幫助頁面 有好多答案 — 如果某個步驟可以更清楚, 話畀我哋知 我哋會好樂意改進教學。