# Bits UI 设计系统

## Bits UI 设计系统界面预览

标记单项检查，查看批量控件的混合状态，检查未完成的进度，然后完成并保存本地清单。

## Bits UI 设计系统设计参考

Bits UI 2.19.5，搭配 Svelte 5.57.1。Bits UI 是无头库：所有 --app-* 颜色、字体和间距值均为本示例附带的明确原创配置，并非 Bits UI 官方设计令牌。原生数据属性与组件属性在下文分别说明。

### 原创语义化 CSS 配置

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --app-canvas | #f4f3f8 | 页面背景。 |
| --app-surface | #ffffff | 面板和对话框表面。 |
| --app-ink | #2d2938 | 正文。 |
| --app-muted | #746d80 | 辅助性文本。 |
| --app-line | #e3dfeb | 分隔线和边框。 |
| --app-action | #604c88 | 选中控件和主要操作。 |
| --app-on-action | #fff | 操作按钮上的文字。 |
| --app-focus | #9a80ce | 清晰可见的键盘焦点。 |
| --app-soft | #eee8f7 | 可选的柔和表面角色。 |
### 原创间距与几何尺寸

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --app-space-1 | 4px | 最小的命名间距单位。 |
| --app-space-2 | 8px | 紧凑间距。 |
| --app-space-3 | 12px | 控件与标签之间的间距。 |
| --app-space-4 | 16px | 面板内侧窄边距。 |
| --app-space-6 | 24px | 桌面端面板内边距和栏间距。 |
| --app-space-8 | 32px | 桌面端页面内边距。 |
| Checkbox geometry | 22×22px; 5px radius; 1px border | 明确的原创控件样式。 |
| Focus ring | 3px solid #9a80ce; 3px offset | 应用于键盘焦点可见时的按钮状态。 |
| Dialog width | min(440px, 100% − 28px) | 明确的响应式覆盖层几何尺寸。 |
| Dialog maximum height | 100vh − 28px with overflow:auto | 仅对覆盖层施加视口约束；不随页面高度变化。 |
| Type hierarchy | 34px title / 29px mobile; 16px accordion; 13px checks; 12px guidance | 原创系统字体层级。 |
### 原生组件契约

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| Checkbox.Root checked | boolean | 已完成或未完成状态。 |
| Checkbox.Root indeterminate | boolean | 部分检查已标记时，批量控件会显示混合状态。 |
| Checkbox data-state | checked / unchecked / indeterminate | 由样式表直接使用。 |
| Accordion.Root type | multiple | 可同时展开多个审核分区。 |
| Accordion value | string[] | 由 Svelte 绑定的已展开组 ID 列表。 |
| Dialog.Root open | boolean, two-way bound | 控制审核内容的显示状态。 |
| Dialog.Title / Description | Native title and description relationships | 无需手动添加重复的 ARIA ID。 |
| Dialog.Portal | Overlay and content rendered outside the normal panel | 通过面板的文档流避免内容裁切。 |
## Bits UI 设计系统完整指南

实用指南，介绍如何为真实界面选择、应用和评审此系统。

完整指导、实现起点和源代码链接。

## Bits UI 设计系统：围绕 Svelte 5 状态组合原生部件

### 围绕 Svelte 5 状态组合原生部件

> 此清单使用 $state 保存各项答案、已展开的分区 ID 和对话框的显示状态。$derived 推导出的完成项数同时用于显示进度和批量复选框。这样一来，真实数据源集中在一个 Svelte 模型中，而 Bits UI 则为各个组件提供原生交互。

Checkbox、Accordion 和 Dialog 均由各自的部件组合而成。审核对话框无需管理清单答案，手风琴分区关闭时也无需丢弃这些答案。对于多分区表单，这种分离方式是实用的起点：即使界面中可见的部件发生变化，模型中的数据也会保留。

阅读配套规范

## Bits UI 设计系统：配合使用 Svelte 5 组件与样式资源

### 配合使用 Svelte 5 组件与样式资源

此示例使用 Svelte 5 runes：用 $state 管理分组、展开的分区、对话框显示状态和保存状态；用 $derived 推导完成项数。直接导入 Bits UI 2.19.5。无需 Tailwind 插件、主题提供程序或图标库，即可实现这套原创视觉样式。

完整的 App.svelte 和 style.css 可在标准 Vite Svelte 项目中运行。入口使用 Svelte 的 mount，而非旧式的 new App 构造函数。移植此示例时，请同时保留组件的 runes 语法和 Bits UI 2.19.5 依赖；此处展示的绑定与回调并非旧版 Svelte 组件 API。

阅读配套规范

## Bits UI 设计系统：根据各项检查结果推导真正的混合状态

### 根据各项检查结果推导真正的混合状态

六个布尔检查项分布在三个分组中。只有六项全为 true 时，批量控件才会显示为选中；当计数介于一到五之间时，则显示为不确定状态。其 onCheckedChange 回调会更新所有检查项，因此混合状态是计算得出的结果，而非单独存储、可能与实际状态不一致的标记。

单项控件会调用一个小型变更函数来更新其模型，并使已保存的提示失效。选中一项后，渲染出的原生批量复选框会显示 aria-checked=mixed。样式表根据 data-state=checked 和 data-state=indeterminate 作出响应，使行为与外观保持一致，并由同一原生状态驱动。

1. 选中第一项焦点指示器检查，并查看批量控件中的短横线。

2. 打开“审核”清单，并确认“保存已完成审核”处于禁用状态。

3. 返回，标记所有检查项，并保存完整的本地快照。

阅读配套规范

## Bits UI 设计系统：允许各个分区独立操作，同时保留各自的答案

### 允许各个分区独立操作，同时保留各自的答案

Accordion.Root 使用 type=multiple，并绑定已展开组 ID 的数组。初始时各分区均展开，且可以分别展开“表单校正”和“结果反馈”分区。折叠分区不会清除其中的检查项，因为这些值保存在父级状态中。

每个触发器都会显示该分区已完成的项目数，因此即使内容已折叠，进度依然可见。原生 Header、Trigger 和 Content 部件保留了预期的关联关系和键盘行为。加号标记会根据触发器的 data-state 旋转，并遵循减少动态效果偏好，而不会通过单独的点击处理程序控制展开。

阅读配套规范

## Bits UI 设计系统：组合完整的对话框结构，并由其管理焦点

### 组合完整的对话框结构，并由其管理焦点

审核界面使用 Dialog.Root、Trigger、Portal、Overlay、Content、Title、Description 和 Close。这些标题和描述都是真正的原生部件，因此 Bits UI 能够建立它们之间的无障碍关联。Portal 会将覆盖层放到清单面板的正常文档流之外。

对话框内容设有响应式宽度限制，覆盖层高度也设有最大值；审核内容较长时可滚动查看。按 Escape 可关闭对话框，而不会清除清单。请保留触发器作为焦点返回目标，不要在覆盖层打开时将其移除。

阅读配套规范

## Bits UI 设计系统：明确并复用应用的视觉规则

### 明确并复用应用的视觉规则

CSS 将原生的选中和不确定状态映射到同一操作角色，但为每种状态使用不同的图形。单独的焦点角色用于表示键盘焦点位置，因此控件可以在保持选中状态的同时，指示下一次键盘操作将发生的位置。

命名间距比例为 4、8、12、16、24 和 32 像素。桌面端面板使用 24 像素间距，窄屏则使用 16 像素。规范表将这些具体选择记录为原始配置，方便读者复现或替换，也避免将演示样式误认为包所保证的默认值。

阅读配套规范

## Bits UI 设计系统：区分手动标记与自动化测试结果

### 区分人工标记与自动化测试结果

此清单记录读者标记的项目，不会检查其他页面、执行键盘测试或判定是否符合无障碍标准。简介文案和审核说明都明确了这一范围；这一点很重要，因为六项检查涉及实际的无障碍行为。

只有六项全部标记后，保存按钮才会启用。保存后的提示说明六项均由读者标记，且结果保存在本地。读者仍可打开未完成的审核以查看缺漏，但无法生成审核已完成的提示。这样的区分让示例中的状态转换更有意义。

阅读配套规范

## Bits UI 设计系统 证据变更时，清除完成提示

### 证据发生变化时，清除完成提示

任何单项或批量更改都会清除已保存状态，避免取消某项检查后仍显示已完成的确认信息。“全部清除”操作还会恢复初始展开的分区并关闭审核对话框，让所有相关状态回到明确的初始状态。

状态区域位于叠加层之外，因此关闭对话框后，已保存的提示仍会保留在文档中。提示描述的是页面本地状态，不会让人误以为报告已提交。重新加载页面会清除清单，这对于这个独立演示来说是合适的。

阅读配套规范

## Bits UI 设计系统 将组件部件关联到可见标签

### 将组件部件关联到可见标签

每个复选框都有稳定的 ID，并关联一个可见标签。选中或不确定状态由原生控件表示；勾号和短横线仅用于装饰。批量控件应同时关联布尔型的选中值和派生的不确定值，避免将部分选中状态误报为普通的未选中项。

Dialog.Title 和 Dialog.Description 通过原生结构提供审核名称和说明。Portal 将叠加层与手风琴的布局分开，而 Dialog.Close 则是明确的关闭操作。叠加层关闭后，外部状态区域仍会保留已保存的结果，因此不会随对话框内容一同消失。

- 确保可见标签与其控件相关联。

- 应用自定义样式后，仍保留明显的焦点可见环。

- 重新设置对话框样式时，不要移除标题或描述部件。

阅读配套规范

## Bits UI 设计系统组件示例

### 完整的 Svelte 5 清单

原生 Bits UI 组合，使用 $state/$derived 模型、受控复选框和基于 Portal 的审核对话框。

```
<script>
import {Accordion,Checkbox,Dialog} from 'bits-ui';
let groups=$state([{id:'keyboard',name:'Keyboard flow',description:'Move through the interface without a pointer.',checks:[{id:'focus',label:'Every action has a visible focus indicator.',done:false},{id:'order',label:'Focus follows the visual reading order.',done:false}]},{id:'forms',name:'Form correction',description:'Make a mistake and recover from it.',checks:[{id:'labels',label:'Each input has a persistent visible label.',done:false},{id:'errors',label:'Errors identify the field and explain the correction.',done:false}]},{id:'feedback',name:'Result feedback',description:'Confirm that the outcome is understandable.',checks:[{id:'status',label:'A status message describes the completed action.',done:false},{id:'color',label:'Meaning remains clear without color alone.',done:false}]}]);
let expanded=$state(['keyboard']),open=$state(false),saved=$state(false);
const complete=$derived(groups.reduce((sum,g)=>sum+g.checks.filter(c=>c.done).length,0));
function change(check,value){check.done=value;saved=false}
function all(value){groups.forEach(g=>g.checks.forEach(c=>c.done=value));saved=false}
function reset(){all(false);expanded=['keyboard'];open=false}
</script>
<main class="check-shell"><header><p class="eyebrow">INTERFACE REVIEW · MANUAL CHECKLIST</p><h1>Check the experience between the screens.</h1><p>Work through six practical checks, then review what you have marked. This is a personal checklist, not an automated accessibility test.</p></header><div class="check-layout"><section class="check-panel"><div class="bulk"><Checkbox.Root id="all-checks" checked={complete===6} indeterminate={complete>0&&complete<6} onCheckedChange={all} class="checkbox"><span aria-hidden="true">{complete===6?'✓':complete>0?'−':''}</span></Checkbox.Root><label for="all-checks">Mark all checks</label><span class="count">{complete}/6</span></div><Accordion.Root type="multiple" bind:value={expanded} class="accordion">{#each groups as group}<Accordion.Item value={group.id} class="accordion-item"><Accordion.Header class="accordion-heading"><Accordion.Trigger class="accordion-trigger"><span>{group.name}<small>{group.checks.filter(c=>c.done).length} of 2 checked</small></span><span class="plus" aria-hidden="true">+</span></Accordion.Trigger></Accordion.Header><Accordion.Content class="accordion-content"><p class="group-description">{group.description}</p>{#each group.checks as check}<div class="check-row"><Checkbox.Root id={check.id} checked={check.done} onCheckedChange={value=>change(check,value)} class="checkbox"><span aria-hidden="true">{check.done?'✓':''}</span></Checkbox.Root><label for={check.id}>{check.label}</label></div>{/each}</Accordion.Content></Accordion.Item>{/each}</Accordion.Root><Dialog.Root bind:open><Dialog.Trigger class="primary">Review checklist</Dialog.Trigger><Dialog.Portal><Dialog.Overlay class="overlay"/><Dialog.Content class="dialog"><Dialog.Title class="dialog-title">Your review snapshot</Dialog.Title><Dialog.Description class="dialog-description">{complete} of 6 checks are marked. Saving records your own review state; it does not certify the interface.</Dialog.Description><ul class="review-summary">{#each groups as group}<li><strong>{group.name}</strong><span>{group.checks.filter(c=>c.done).length} / 2</span></li>{/each}</ul>{#if complete<6}<p class="remaining">Return to the checklist to finish the remaining {6-complete} checks.</p>{/if}<div class="dialog-actions"><Dialog.Close class="secondary">Back to checks</Dialog.Close><button class="primary" disabled={complete<6} onclick={()=>{saved=true;open=false}}>Save completed review</button></div></Dialog.Content></Dialog.Portal></Dialog.Root><button class="reset" onclick={reset}>Clear all checks</button><p class="result" role="status">{saved?'Completed review saved locally. All six checks were marked by you.':'Progress stays in this preview until you reload.'}</p></section><aside class="check-notes"><div class="focus-art" aria-hidden="true"><span></span><i></i><b></b></div><p class="eyebrow">WHAT TO LOOK FOR</p><h2>Make the next action clear.</h2><p>A good check leaves evidence: where focus moved, what an error said, or how a result was announced.</p><dl><div><dt>Keyboard</dt><dd>Tab, Shift+Tab, Enter and Escape should support the relevant task.</dd></div><div><dt>Correction</dt><dd>Keep the user’s input and point to a specific next step.</dd></div><div><dt>Feedback</dt><dd>Describe the outcome in words as well as visual styling.</dd></div></dl></aside></div></main>
```

代码参考

- 主控件根据六项单独检查推导选中和不确定状态。

- 是否允许保存取决于检查是否全部完成，而不取决于对话框是否打开。

- 此手动工作表不会运行无障碍审计。

### 完整的原创视觉配置

命名语义颜色、间距比例、原生 data-state 选择器和响应式叠加层样式。

```
:root{--app-canvas:#f4f3f8;--app-surface:#ffffff;--app-ink:#2d2938;--app-muted:#746d80;--app-line:#e3dfeb;--app-action:#604c88;--app-on-action:#fff;--app-focus:#9a80ce;--app-soft:#eee8f7;--app-radius:12px;--app-space-1:4px;--app-space-2:8px;--app-space-3:12px;--app-space-4:16px;--app-space-6:24px;--app-space-8:32px}html,body,#app{height:auto;min-height:0;margin:0}*{box-sizing:border-box}body{font-family:system-ui,sans-serif;background:var(--app-canvas);color:var(--app-ink)}button{font:inherit;cursor:pointer}button:disabled{opacity:.45;cursor:default}button:focus-visible{outline:3px solid var(--app-focus);outline-offset:3px}.check-shell{max-width:1080px;margin:auto;padding:var(--app-space-8)}.eyebrow{font-size:10px;letter-spacing:.14em;font-weight:700;color:var(--app-muted)}h1{font-size:34px;line-height:1.15;max-width:710px;margin:12px 0}header>p:last-child{font-size:14px;line-height:1.7;max-width:640px;color:var(--app-muted)}.check-layout{display:grid;grid-template-columns:minmax(0,1fr) 270px;gap:var(--app-space-6);margin-top:28px}.check-panel{background:var(--app-surface);border:1px solid var(--app-line);border-radius:16px;padding:var(--app-space-6);min-width:0}.bulk{display:flex;align-items:center;gap:12px;font-size:14px;font-weight:600;padding-bottom:24px}.count{margin-left:auto;color:var(--app-muted);font-size:12px}.checkbox{width:22px;height:22px;flex-shrink:0;border:1px solid #aaa1ba;background:white;border-radius:5px;display:inline-flex;align-items:center;justify-content:center;padding:0;line-height:1}.checkbox[data-state=checked],.checkbox[data-state=indeterminate]{background:var(--app-action);border-color:var(--app-action);color:var(--app-on-action)}.accordion{margin-bottom:24px}.accordion-item{border-top:1px solid var(--app-line)}.accordion-item:last-child{border-bottom:1px solid var(--app-line)}.accordion-heading{margin:0;font-size:16px}.accordion-trigger{width:100%;border:0;background:transparent;display:flex;align-items:center;justify-content:space-between;text-align:left;padding:20px 0;color:var(--app-ink);font-weight:600}.accordion-trigger small{display:block;font-weight:400;font-size:11px;color:var(--app-muted);margin-top:6px}.plus{font-size:23px;font-weight:400;transition:transform .15s}.accordion-trigger[data-state=open] .plus{transform:rotate(45deg)}.accordion-content{padding:0 0 20px}.group-description{font-size:12px;line-height:1.6;color:var(--app-muted);margin:0 0 16px}.check-row{display:flex;align-items:flex-start;gap:12px;margin-top:14px}.check-row label{font-size:13px;line-height:1.6;cursor:pointer}.primary,.secondary{border:1px solid transparent;border-radius:8px;padding:12px 16px;font-size:13px;font-weight:600}.primary{background:var(--app-action);color:var(--app-on-action)}.secondary{background:white;color:var(--app-ink);border-color:var(--app-line)}.reset{border:0;background:transparent;color:var(--app-muted);font-size:12px;padding:12px}.result{font-size:12px;line-height:1.6;color:var(--app-muted);margin:18px 0 0}.check-notes{min-width:0;padding:0 4px}.check-notes h2{font:400 29px/1.2 Georgia,serif}.check-notes>p:not(.eyebrow){font-size:13px;line-height:1.7;color:var(--app-muted)}.check-notes dl>div{padding:14px 0;border-top:1px solid var(--app-line)}.check-notes dt{font-size:13px;font-weight:600}.check-notes dd{font-size:12px;line-height:1.7;color:var(--app-muted);margin:5px 0 0}.focus-art{height:165px;background:#e6e0ef;border-radius:12px;position:relative;overflow:hidden;margin-bottom:24px}.focus-art span{position:absolute;width:140px;height:85px;left:35px;top:44px;background:white;border-radius:8px;transform:rotate(-9deg);box-shadow:0 0 0 6px #b3a3cd}.focus-art i{position:absolute;width:75px;height:13px;background:#b7adc6;left:60px;top:61px;transform:rotate(-9deg)}.focus-art b{position:absolute;width:72px;height:28px;background:#695587;left:87px;top:91px;border-radius:5px;transform:rotate(-9deg)}.overlay{position:fixed;inset:0;background:#21193180;z-index:20}.dialog{position:fixed;z-index:21;left:50%;top:50%;transform:translate(-50%,-50%);width:min(440px,calc(100% - 28px));max-height:calc(100vh - 28px);overflow:auto;background:white;padding:24px;border-radius:14px;box-shadow:0 20px 80px #23193640}.dialog-title{font-size:23px;margin:0 0 12px}.dialog-description,.remaining{font-size:13px;line-height:1.7;color:var(--app-muted)}.review-summary{padding:0;list-style:none}.review-summary li{display:flex;justify-content:space-between;gap:12px;padding:12px 0;border-bottom:1px solid var(--app-line);font-size:13px}.dialog-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}@media(max-width:740px){.check-layout{grid-template-columns:minmax(0,1fr)}.check-shell{padding:20px}h1{font-size:29px}}@media(max-width:360px){.check-shell{padding:14px}.check-panel,.dialog{padding:16px}.check-panel>.primary,.dialog-actions>*{width:100%}}@media(prefers-reduced-motion:reduce){.plus{transition:none}}
```

代码参考

- 这些是原始的 --app-* 变量，并非 Bits 官方调色板。

- 包含焦点和减少动态效果的样式。

- 只有叠加层使用相对于视口的最大高度。

## Bits UI 设计系统 AI Agent 设置

### 实现起点

已验证 Bits UI 2.19.5 与 Svelte 5.57.1。需要完整的原始样式表；Bits UI 不提供默认颜色或页面布局。

```
// npm create vite@latest bits-review -- --template svelte
// cd bits-review && npm install
// npm install svelte@5.57.1 bits-ui@2.19.5
// Save the complete examples as src/App.svelte and src/style.css.
// src/main.js:
import {mount} from 'svelte';
import App from './App.svelte';
import './style.css';
mount(App, {target:document.querySelector('#app')});
// index.html: <div id="app"></div><script type="module" src="/src/main.js"></script>
// npm run dev
```

### 适用于你项目的提示词

```
使用 Bits UI 2.19.5 和 Svelte 5 构建所提供的手动界面审核。将六项检查放入三个 Accordion 分区，根据单项答案推导批量选中和不确定状态，并在分区折叠时保留答案。使用完整的 Dialog 部件组合审核功能，允许查看未完成的审核，但只有六项全部标记后才启用保存。每次答案变更都会使已保存的反馈失效；“全部清除”会恢复初始展开状态并关闭审核。加入完整的 CSS，并说明结果只是由读者标记并保存在本地的检查项，而非自动化无障碍认证。
```

## Bits UI 设计系统的来源与范围

Bits UI 2.19.5 与 Svelte 5.57.1。使用原始应用设计令牌和插图。这是一份使用本地状态的手动清单，并非自动化无障碍审计或认证。

- 入门指南 Svelte 设置与包集成。

- 样式 无头样式边界与数据属性。

- 复选框 选中、不确定和受控状态。

- 手风琴 支持多项展开并采用原生结构。

- 对话框 Portal、标题、描述、焦点与关闭操作。

- 状态管理 绑定与受控值。

## Bits UI 设计系统相关资源

### Bootstrap

通过实际的间距比例、语义化颜色、响应式网格和组件 API 使用 Bootstrap 5.3.8。体验可用的预约表单、错误摘要、表格筛选器、模态框和色彩模式切换，然后复用文档中的代码。

### Bulma

使用 Bulma 的实际字段/控件结构、响应式分栏、语义化颜色修饰符和 CSS 变量，构建编辑工作台，并提供完整的校验代码。

### Chakra UI

Chakra UI v3 参考资料，涵盖设计令牌、语义颜色角色、配方和复合表单组件。查看实际的间距与字体比例，然后尝试使用原生组件构建工作区个人资料表单，其中包含验证、保存失败模拟以及浅色/深色外观。


- [实现参考](https://www.bits-ui.com/docs/components/checkbox)
- [来源](https://www.bits-ui.com/docs/styling)
- [来源](https://www.bits-ui.com/docs/components/dialog)
- [阅读配套规范](https://www.bits-ui.com/docs/styling)
- [阅读配套规范](https://www.bits-ui.com/docs/getting-started)
- [阅读配套规范](https://www.bits-ui.com/docs/components/checkbox)
- [阅读配套规范](https://www.bits-ui.com/docs/components/accordion)
- [阅读配套规范](https://www.bits-ui.com/docs/components/dialog)
- [阅读配套规范](https://www.bits-ui.com/docs/state-management)
- [代码参考](https://www.bits-ui.com/docs/components/checkbox)
- [代码参考](https://www.bits-ui.com/docs/styling)
- [入门指南 Svelte 设置与包集成。](https://www.bits-ui.com/docs/getting-started)
- [样式 无头样式边界与数据属性。](https://www.bits-ui.com/docs/styling)
- [复选框 选中、不确定和受控状态。](https://www.bits-ui.com/docs/components/checkbox)
- [手风琴 支持多项展开并采用原生结构。](https://www.bits-ui.com/docs/components/accordion)
- [对话框 Portal、标题、描述、焦点与关闭操作。](https://www.bits-ui.com/docs/components/dialog)
- [状态管理 绑定与受控值。](https://www.bits-ui.com/docs/state-management)
