Lily 入门
选择一个框架,克隆 headless 仓库或示例应用,然后开始组合你自己的页面。喜欢有引导的路径?请从教程开始。
安装
Lily 针对每个框架以独立的 Git 仓库形式发布。最快的试用方法是克隆你所用技术栈的 headless 仓库:
git clone https://github.com/LilyDesignSystem/lily-design-system-react-headless
cd lily-design-system-react-headless
pnpm install
同样的模式也适用于其他框架:
@lilydesignsystem/html-headless— 无需安装;复制.html文件即可@lilydesignsystem/svelte-headless—pnpm install@lilydesignsystem/react-headless—pnpm install@lilydesignsystem/vue-headless—pnpm install@lilydesignsystem/angular-headless—pnpm install@lilydesignsystem/nunjucks-headless—pnpm installlily-design-system-blazor-headless—dotnet build
headless 库的设计目的是被克隆或直接纳入你的项目——把源代码当作事实来源,需要什么就复制什么。偏好辅助组件还以可安装软件包的形式提供,并有构建与发布流水线(JS 框架用 npm,Blazor 用 NuGet)。
使用 headless 组件
headless 组件自带语义化 HTML、ARIA 和属性——但没有 CSS。下面是各框架中的一个按钮:
HTML
<button class="button" type="button" aria-label="Save">
Save
</button>
Svelte
<script>
import Button from "lily-design-system-svelte-headless/components/Button/Button.svelte";
</script>
<Button onclick={save}>Save</Button>
React
import Button from "lily-design-system-react-headless/components/Button";
<Button onClick={save}>Save</Button>
Vue
<script setup>
import Button from "lily-design-system-vue-headless/components/Button.vue";
</script>
<Button @click="save">Save</Button>
Angular
import { Button } from "@lilydesignsystem/angular-headless";
@Component({
imports: [Button],
template: `<lily-button (click)="save()">Save</lily-button>`,
})
Blazor
<Button OnClick="Save">Save</Button>
Nunjucks
{% from "components/button/macro.njk" import button %}
{{ button({ text: "Save", type: "button" }) }}
使用带样式的示例
示例应用包含 CSS、路由和完整的演示页面。最快的实验方式是启动 SvelteKit、Next、Nuxt、Analog 或 Eleventy 示例应用,并在 /components 查看演示。
git clone https://github.com/LilyDesignSystem/lily-design-system-svelte-sveltekit-examples
cd lily-design-system-svelte-sveltekit-examples
pnpm install
pnpm run dev
然后打开 http://localhost:5173 并浏览 /components。
样式与设计令牌
每个组件在其根元素上渲染一个 kebab-case 类。例如,<Button> 会渲染 <button class="button">。你想怎么设置样式都行:
.button {
background: var(--my-primary);
color: #fff;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
}
.button:hover { background: var(--my-primary-hover); }
Lily 默认的调色板(用于示例应用)是:
- 主色:
#2563eb - 危险:
#dc2626 - 警告:
#f59e0b - 成功:
#16a34a - 页面背景:
#f9fafb - 卡片背景:
#ffffff
这些只是建议,不是要求。换成你自己品牌的调色板,Lily 会欣然配合。
现成主题
不想从零开始写 CSS?Lily 附带 45 个独立的参考主题,位于 themes/ 目录中。每一个都是针对 Lily 类钩子的一份样式表——链接它,样式就生效了:
<link rel="stylesheet" href="/assets/themes/united-kingdom-government-digital-service.css" />
这一组主题涵盖:
- 公共部门 — NHS England、NHS Scotland 和 NHS Wales(各有面向患者和面向从业者的版本)、GOV.UK GDS,以及美国网页设计系统。
- 受厂商启发 — Adobe Spectrum、Mozilla Protocol。
- 通用 — 浅色、深色、nord、dracula、wireframe,以及三十多个其他主题。
主题选择器使用 :where(...),所以在优先级上你自己的 CSS 总是胜出。把它们与下面的 theme-picker 辅助组件搭配即可在运行时切换,或参阅主题教程。
偏好辅助组件
每个框架都有一个配套的 *-helpers 目录,其中有八个小型选择器(以及一个把它们组装在一起的 picker-bar)。每个都是打开弹出层的 headless 图标按钮——选项列表、链接列表、搜索表单,或(对 date-time-picker 而言)日期选择对话框——而不是原生的 <select>;它对 SSR 安全,也不附带任何 CSS:
- theme-picker — 通过替换一个受管理的
<link>在运行时加载主题样式表,在文档上设置data-theme,并可选择持久化到localStorage。 - locale-picker — 设置
lang和dir(自动检测从右到左),以便你的 i18n 库跟随;它自己不做任何翻译。 - text-size-picker — 在文档上设置
data-text-size;你的 CSS 把每个值映射为字体大小。 - motion-picker — 在文档上设置
data-motion,起点是访问者的减弱动效设置;由你的 CSS 和脚本决定要抑制什么。 - search-picker — 打开搜索框的图标按钮;提交后跳转到搜索页面。它拥有的是一个操作,而不是偏好。
- link-picker — 一个主页图标,打开由你的应用定义的页面链接菜单(首页、关于我们、联系我们、隐私政策……)。它拥有的是一个操作,而不是偏好。
- share-picker — 打开原生分享面板或使用方提供的目的地列表,外加复制网址。它拥有的是一个操作,而不是偏好:不应用任何东西,也不保存任何东西。
- date-time-picker — 一个文本字段加上用于日期、时间或两者的 APG 日期选择对话框。它拥有的是一个表单值,而不是偏好:ISO 字符串可与
<input type="date">来回转换。
git clone https://github.com/LilyDesignSystem/lily-design-system-svelte-helpers
Svelte 目录是规范参考;React、Vue、Angular、HTML、Nunjucks、Web Components 和 Blazor 的移植版逐项契约与之一致。参见辅助组件教程。
无障碍
组件以 WCAG 2.2 AAA 为目标。它们遵循这些模式:
- 用语义化 HTML 元素而不是通用的
<div>。 - 用
<label for="id">把标签与输入关联起来。 - 用
aria-labelledby/aria-describedby做相互引用。 - 用
aria-invalid+aria-errormessage表示错误状态。 - 用
role="alert"和aria-live表示动态内容。 - 用
aria-pressed、aria-expanded、aria-current表示状态。 - 为网格使用漫游式
tabindex。
焦点指示器刻意由使用方提供——Lily 从不绘制与你的设计冲突的默认焦点环。示例应用在其所有路由上都保持干净的 axe-core 基线。
国际化
每个标签、占位符、错误消息和按钮文字都是一个属性。没有硬编码的字符串。接入你选择的翻译框架——Paraglide、i18next、vue-i18n、react-intl、.resx 文件,什么都行。
对于日期、数字和货币,组件接受预先格式化的字符串:你用 Intl.DateTimeFormat / Intl.NumberFormat / 你喜欢的库进行格式化,然后传入结果。
locale-picker 辅助组件通过在文档根上设置 lang 和 dir,向你的 i18n 库传达所选的区域设置。
测试
每个框架子项目都使用其惯用技术栈附带自己的测试:
- HTML:在真实浏览器中运行的 WebDriverIO。
- Svelte: Vitest +
@testing-library/svelte. - React: Vitest +
@testing-library/react. - Vue: Vitest +
@testing-library/vue. - Angular:Vitest + TestBed(通过 Analog 的 Vite 插件)。
- Nunjucks:带渲染辅助函数的 Vitest。
- Blazor: bUnit.
测试只使用 Vitest 的内置匹配器——从不使用 jest-dom 匹配器。这让测试套件保持可移植。示例应用还增加了 Playwright 端到端套件、axe-core 无障碍基线和响应式视口扫描。
AI 代理
本站在根目录发布 llms.txt 和 llms.json——最重要页面的精选地图,供任何遵循 llms.txt 约定的工具使用。
规范单体仓库还提供两个 Claude 技能:lily-design-system-skill,一个通用技能,为使用该系统构建的人涵盖 Lily 的概念、术语和组合模式;以及 lily-design-system-maintainer-skill,一个技术技能,为在其上工作的人涵盖单体仓库所需的文件布局和工具。两者都位于规范单体仓库的根目录。
故障排查
组件能渲染,但看起来没有样式
这是 headless 在按预期工作——组件不附带任何 CSS。要么针对组件的 kebab-case 类编写 CSS(每个目录页面上都有显示),要么链接 45 个现成主题之一。
我的 CSS 似乎没能覆盖主题
应该可以——主题选择器包裹在 :where(...) 中,其优先级为零。如果某条规则仍然输了,请检查你的样式表是否在主题的 <link> 之后加载,以及选择器是否确实匹配组件的类钩子。
pnpm install 因对等依赖或版本错误而失败
使用较新的 pnpm(v10+)和 Node 22+。每个仓库都在 package.json 中固定了其框架版本;如果你的全局工具链较旧,pnpm env use --global lts 是最快的解决办法。
屏幕阅读器为某个控件朗读了错误的名称
检查组件必需的 label 属性——没有可见文字的组件需要它;而使用方提供并通过其余属性传入的 aria-label / aria-labelledby 会刻意优先于内置的连线。每个目录页面都记录了该组件的 ARIA 契约。
theme-picker 辅助组件不切换样式表
确认 themesUrl 指向浏览器可获取的目录(把 themes/ 文件作为静态资源提供),并且你的 themes 属性中的主题标识符与文件名一致。该辅助组件替换的是一个受管理的 <link data-lily-theme-picker> 的 href——在开发者工具中检查它,就能看到被请求的网址。
其他东西坏了
请在相关仓库(github.com/LilyDesignSystem)提交议题并附上最小复现——或查看社区与支持。
参与贡献
Lily 还很年轻,欢迎协作。目前最有用的贡献是:
- 新组件(尤其是来自成熟设计系统的模式)。
- 新主题——每个都是一份独立样式表,范围明确的首个拉取请求。
- 更好的示例样式——展示什么是可能的。
- 示例应用字符串的翻译。
- 附带最小复现的缺陷报告。
- 借助屏幕阅读器和辅助技术进行的无障碍审计。
请在相关仓库(github.com/LilyDesignSystem)提交议题和拉取请求。
社区与支持
- 问题与缺陷报告 — 请在相关仓库(github.com/LilyDesignSystem)提交议题。
- 电子邮件 — 维护者会阅读 joel@joelparkerhenderson.com,欢迎协作、指导和反馈。
- 镜像 — Lily 还会推送到 Codeberg 和 GitLab,这样你可以在自己喜欢的平台上参与。
- 行为准则 — 项目遵循标准的行为准则;请友善待人,以善意揣度他人。
常见问题
为什么用 headless 而不是自带样式?
预设样式的组件很方便——直到它们和你的品牌不匹配。headless 组件前期多一点工作,但让你完全掌控视觉设计。示例应用和 45 个主题展示了设置样式的方法;你可以直接采用,也可以完全替换。更完整的论述见为什么选择 Lily。
为什么有这么多组件?
Lily 的目标是覆盖大多数应用所需的模式,而不强迫你从零构建——包括国家标识符输入和编辑式滚动叙事这类更深入的场景。目录借鉴了十几个成熟的设计系统,再加上原创工作——参见关于。
我能把 Lily 和 Tailwind 一起用吗?
可以。每个组件都暴露一个 kebab-case 根类,外加使用方提供的 className / class。想怎么在上面叠加 Tailwind 工具类都可以。
我能把 Lily 和 DaisyUI 这类语义化 CSS 框架一起用吗?
可以。根元素上的 kebab-case 类名可作为语义化 CSS 钩子。把 Lily 与语义化框架搭配,你就得到仍然尊重 ARIA 和 i18n 的预设样式组件。
有 npm 包吗?
偏好辅助组件以软件包形式提供,并有 npm/NuGet 发布流水线。headless 组件库的设计目的是被克隆或直接纳入项目——源代码就是交付物,所以你可以阅读、裁剪并完全掌握你所发布的内容。headless 库发布到包注册表仍在路线图上。
为什么是多重许可?
不同的项目有不同的许可需求。BSD 和 MIT 是宽松的,Apache-2.0 带有专利授权,而 GPL 选项支持 copyleft。选择适合你情况的即可。
我该如何报告缺陷或请求新功能?
在相关的 GitHub 仓库提交议题,或发邮件至 joel@joelparkerhenderson.com。