偏好设置辅助包
每种框架有七个小型包,每个包从头到尾负责一项用户任务,另有一个把其中五个组装起来的栏。你已经见过 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 的辅助包在契约上逐条一致。
它们共有的形态
- 一个 headless 图标按钮,打开 WAI-ARIA APG 列表框(对于 date-time-picker 则是日期选择器对话框)——不使用原生的
<select>,所以每种框架都有完全相同的键盘行为和样式钩子。 - 每个包一个类名钩子(
.locale-picker、.text-size-picker、.share-picker、.date-time-picker),不附带任何 CSS。 - SSR 安全:DOM 写入只发生在挂载/副作用生命周期中。
- 国际化友好:每一条面向用户的字符串都是 prop。
- 提供 Svelte(规范版本)、React、Vue、Angular、HTML 自定义元素、Nunjucks 和 Blazor 版本——每个版本的契约相同。
theme-picker、locale-picker 和 text-size-picker 各自从头到尾负责一项用户偏好(选择、应用到 DOM、通过 storageKey
prop 可选的 localStorage 持久化)。share-picker 和 date-time-picker 则性质不同:
share-picker 负责一个操作——它不对文档应用任何内容,也不保存任何内容——而 date-time-picker 负责一个
表单值,因为表单中的日期是数据,而不是偏好。
locale-picker——语言与方向
让用户选择一种语言环境,然后把 lang 和
dir 写到文档根元素上,让你的国际化库、你的 CSS 和辅助技术都跟着变化。阿拉伯语、希伯来语及其他从右到左的文字会被自动检测为 RTL。它只专注于发出信号——翻译由你的国际化库负责。
<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 字符串:mode="date" 时为
"2026-03-15",mode="time" 时为 "09:30",
mode="datetime" 时为 "2026-03-15T09:30"。
<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——不碍事的搜索框
一个打开搜索框的图标按钮。按下回车键,或字段旁边的 ⏎ 按钮,就会用一次普通的 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 以及组合面板的代码片段,已于 2026-08-29 针对已发布的 0.1.1 包,经
svelte/server 逐个编译通过;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-
每个包都有自己的规范、对应规范条款的测试、可运行的示例(包括 SSR cookie 模式),以及构建与发布流水线。Svelte 版本是规范版本;有疑问时,以它们的契约为准。
下一步
- 组件目录——完整的 571 个组件参考。
- 帮助——故障排除与常见问题。
- 为什么选择 Lily——以及如何支持这个项目。