# Melt UI 设计系统

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

更改对齐方式、移动字间距滑块并切换网格；原始海报会根据构建器 store 更新。

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

经过验证的 @melt-ui/svelte 0.86.6 store/action 构建器运行于 Svelte 5.57.1。这里使用的是文档所述的构建器 API，而非单独的新一代 runes API。Melt 是无头库；下方所有 --study-* 视觉值均为应用程序自定义配置，并已完整提供。

### 原始语义视觉配置

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --study-canvas | #f3f0e9 | 外层页面。 |
| --study-surface | #fffdf8 | 控制面板。 |
| --study-ink | #32352e | 正文。 |
| --study-muted | #77796a | 辅助性文本。 |
| --study-line | #dbdece | 滑轨和面板边界。 |
| --study-action | #486348 | 选中的单选项和活动范围。 |
| --study-on-action | #fff | 操作文本。 |
| --study-focus | #8aa77c | 键盘焦点环。 |
| --study-poster | #e0e8bb | 原始海报纸张。 |
| --study-accent | #d68f57 | 装饰性轨道形状。 |
### 原始间距和字号阶梯

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --study-space-1 | 4px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| --study-space-2 | 8px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| --study-space-3 | 12px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| --study-space-4 | 16px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| --study-space-6 | 24px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| --study-space-8 | 32px | 应用程序中命名的间距值；并非 Melt 默认值。 |
| Text family | system-ui, sans-serif | 不依赖远程字体。 |
| Page title | 34px / 1.15; 29px narrow | 原始标题层级。 |
| Poster title | clamp(28px,5.5vw,64px); 28px below 360px | 原始响应式展示字号阶梯。 |
| Poster tracking | 0–8px, step 1; default 2px | 由滑块实际驱动的字间距。 |
| Grid spacing | 24px × 24px | 通过原生开关切换的装饰性参考线。 |
| Focus ring | 3px solid #8aa77c; 4px offset | 显式的 focus-visible 样式。 |
### 原生构建器约定

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| createRadioGroup.defaultValue | left | 仅选择一个对齐方式。 |
| Radio orientation / loop | horizontal / true | 方向键导航遵循水平分组，并会循环切换。 |
| createSlider.defaultValue | [2] | 即使只有一个滑块拇指，store 仍保存数组。 |
| Slider min / max / step | 0 / 8 / 1 | 有界整数跟踪。 |
| Slider elements.thumbs | Array-producing builder store | 0.86.6 返回的是多个拇指，而不是单个拇指元素。 |
| createSwitch.defaultChecked | true | 参考线默认显示。 |
| Builder attributes + action | {...$builder} use:builder | 无需可选的 Melt 预处理器即可使用显式语法。 |
| Thumb attributes + action | {...thumb} use:thumb.action | 每个生成的拇指都会携带自己的属性和 action。 |
## Melt UI 设计系统完整指南

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

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

## Melt UI 设计系统：Melt 为你编写的标记添加行为

### Melt 为你编写的标记添加行为

> 此示例使用 @melt-ui/svelte 0.86.6 中的 store/action API。createRadioGroup、createSlider 和 createSwitch 会返回元素构建器及状态 store。普通的按钮、span 和 div 会接收连接至原生控件行为的属性和 action。

此软件包不提供绿色纸张、海报字体排版或面板几何形状。这些设计选择均在完整的原始样式表中定义。文档还提到了单独的新一代 runes API；本页面明确标注经过验证的构建器版本，不会混用两代中彼此不兼容的示例。

阅读配套规范

## Melt UI 设计系统：同时展开属性并安装 action

### 同时展开属性并安装 action

一个元素既需要构建器属性，也需要 action。示例使用 {...$alignRoot} use:alignRoot 和 {...$alignItem(value)} use:alignItem 等写法。属性携带角色、状态和定位信息；action 则安装交互行为并负责清理。

较短的 use:melt 语法需要 Melt 的可选预处理器。若未启用该预处理器，运行时会抛出特定错误，而不会悄悄附加构建器。修复后的代码始终使用显式语法，因此下方的 Vite 配置无需依赖未说明的预处理步骤。每个滑块拇指同样会展开其返回的属性并调用 thumb.action。

阅读配套规范

## Melt UI 设计系统：在应用程序 CSS 中定义无头视觉系统

### 在应用程序 CSS 中定义无头视觉系统

--study-* 角色用于区分外层画布、控件表面、文本、分隔线、操作、焦点、海报纸张和装饰性强调色。六个具名间距值从四像素到三十二像素不等。这些是为复现此特定构图而做出的原创选择，并非由 Melt 维护的令牌目录。

选中的单选按钮和开关使用 data-state=checked，而滑块返回的内联位置决定拇指和选中范围的显示位置。样式表只负责补充几何样式和颜色。用手动计算的百分比替代这些原生位置会重复实现逻辑，还可能破坏对方向或书写方向的支持。

阅读配套规范

## Melt UI 设计系统：使用原生组导航保持单一对齐方式处于选中状态

### 使用原生分组导航保持单个对齐选项处于选中状态

createRadioGroup 的初始值为 left，方向设为水平，并启用循环导航。每个单选项都有稳定的值：left、center 或 right。海报的 text-align 直接读取选中的值，因此键盘导航和指针选择都会影响同一视觉布局。

为单选按钮组添加易于访问的“文本对齐”标签。三个选项都是由构建器支持的原生单选控件，而不是通过手动切换类名实现的普通按钮。选中状态既体现在语义信息中，也体现在用于填充视觉效果的 data-state 选择器中。

1. 选择“居中”，并查看海报的对齐方式。

2. 聚焦“字距”滑块并按 End，将值调至 8px。

3. 关闭布局网格，并保存当前本地布局。

阅读配套规范

## Melt UI 设计系统：即使只有一个拇指，也要将值作为数组处理

### 即使只有一个滑块拇指，也始终将值视为数组

滑块使用 defaultValue:[2] 作为初始值，而非标量。已安装的 0.86.6 构建器提供会生成数组的 elements.thumbs 存储，并由模板渲染返回的每个拇指。海报读取 $tracking[0]，并将其作为像素字距值应用。

取值范围为 0 到 8，步长为 1。按 Home 和 End 可跳至边界；按方向键可按指定步长移动。对于这个单拇指布局，读取 $tracking[0]；添加另一个拇指时，继续使用数组模型，不要另行引入一个无关的标量状态。

阅读配套规范

## Melt UI 设计系统：将视觉辅助网格与设计值分开

### 将视觉指南与设计值分开

createSwitch 的初始状态为选中，其状态会控制海报上的 guides 类。该类以 24 像素的间距绘制两层细微的重复网格渐变。关闭开关会移除渐变，但不会改变对齐方式或字距。

可见的“显示布局网格”标签与开关的稳定 ID 关联。开关拇指移动使用 CSS 过渡效果，并提供减少动态效果的覆盖样式。装饰性环绕插图设为 aria-hidden，且没有交互功能，不会与实际控件的语义相冲突。

阅读配套规范

## Melt UI 设计系统：协调可写存储，避免重复保存控件状态

### 协调可写 store，避免重复维护控制状态

对齐方式、字距和网格可见性仍由各自构建器的可写存储管理。渲染后的海报直接读取这些存储：text-align 使用对齐方式，letter-spacing 使用滑块值数组的首项，CSS 类则使用开关的选中值。再为这三个设置创建独立的应用模型，只会带来不必要的同步工作。

保存的快照根据这些值的签名生成。任一值发生变化都会清除确认状态；重置操作则将 left、[2] 和 true 写回存储。保留单元素数组很重要：即使只显示一个拇指，赋值标量 2 也不符合滑块的值约定。

阅读配套规范

## Melt UI 设计系统：为每个构建器提供属性、操作和名称

### 为每个构建器提供属性、操作和名称

单选按钮组应获得“文本对齐”标签，滑块拇指应关联可见的“字距”文本，开关应关联其可见标签。这些名称应添加到实际由构建器支持的元素上，而不是外围的装饰性包装元素上。

显式模板语法会一并安装属性和操作。对于滑块拇指，返回项中包含其操作，因此循环时要展开拇指属性并调用 thumb.action。为轨道和范围设置样式时，应保留构建器输出的定位信息；这些信息描述实际数值状态和方向，样式表则负责提供颜色和几何样式。

- 检查实际计算结果，而不只是数值标签。

- 将标签保留在原生构建器元素上。

- 为自定义视觉过渡效果提供减少动态效果的支持。

阅读配套规范

## Melt UI 设计系统：在常规 Svelte 项目中使用已验证的构建器 API

### 在普通 Svelte 项目中使用经过验证的构建器 API

完整组件使用 Svelte 存储订阅，即 $alignment、$tracking 和 $grid。Svelte 5 可以编译这种成熟的组件语法；入口使用当前的 mount 函数。由于上文已提供完整视觉层，因此无需自定义图标库或样式表包。

下方的标准 Vite Svelte 配置固定使用 @melt-ui/svelte 0.86.6 和 Svelte 5.57.1。它不会安装 Melt 预处理器，因为组件已使用显式等效语法。迁移到较新的 runes 包时，应有意重写 API，而不是只更改依赖版本。

阅读配套规范

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

### 完整的存储/操作构建器组合

createRadioGroup、createSlider 和 createSwitch 会为普通标记添加原生语义和行为。

```
<script>
import {createRadioGroup,createSlider,createSwitch} from '@melt-ui/svelte';
const {elements:{root:alignRoot,item:alignItem},states:{value:alignment}}=createRadioGroup({defaultValue:'left',orientation:'horizontal',loop:true});
const {elements:{root:trackingRoot,range:trackingRange,thumbs},states:{value:tracking}}=createSlider({defaultValue:[2],min:0,max:8,step:1});
const {elements:{root:gridRoot},states:{checked:grid}}=createSwitch({defaultChecked:true});
let saved='';let previous='';
$: current=`${$alignment}|${$tracking[0]}|${$grid}`;
$: if(current!==previous){saved='';previous=current}
function save(){saved=`Saved locally: ${$alignment} aligned, ${$tracking[0]}px tracking, grid ${$grid?'on':'off'}.`}
function reset(){alignment.set('left');tracking.set([2]);grid.set(true);saved=''}
</script>
<main class="poster-shell"><header><p class="eyebrow">TYPE COMPOSITION · LIVE STUDY</p><h1>A small change. A different rhythm.</h1><p>Use native Melt UI builders to change the alignment, tracking and guide visibility of an original typographic poster.</p></header><div class="poster-layout"><section class="controls"><h2>Composition</h2><p class="control-label" id="alignment-label">Text alignment</p><div {...$alignRoot} use:alignRoot aria-labelledby="alignment-label" class="alignment">{#each ['left','center','right'] as value}<button {...$alignItem(value)} use:alignItem class="align-option">{value[0].toUpperCase()+value.slice(1)}</button>{/each}</div><div class="tracking-control"><p class="control-label" id="tracking-label">Letter spacing <strong>{$tracking[0]}px</strong></p><div {...$trackingRoot} use:trackingRoot class="slider"><div {...$trackingRange} use:trackingRange class="slider-range"></div>{#each $thumbs as thumb}<span {...thumb} use:thumb.action aria-labelledby="tracking-label" class="slider-thumb"></span>{/each}</div><div class="scale"><span>0px</span><span>8px</span></div></div><div class="grid-control"><label for="show-grid">Show layout grid</label><button id="show-grid" {...$gridRoot} use:gridRoot class="switch"><span></span></button></div><p class="hint">The grid is a visual aid. It does not change the poster’s text or spacing.</p><button class="primary" on:click={save} disabled={!!saved}>Save composition</button><button class="reset" on:click={reset}>Restore initial settings</button><p class="result" role="status">{saved||'This study changes only the local preview.'}</p></section><section class="poster" class:guides={$grid} style:text-align={$alignment} aria-label="Live typographic poster"><div class="poster-top"><span>TYPE / 2026</span><span>STUDY 04</span></div><div class="poster-orbit" aria-hidden="true"><i></i><b></b></div><div class="poster-title" style:letter-spacing={`${$tracking[0]}px`}><span>SPACE</span><span>TO</span><span>THINK.</span></div><div class="poster-bottom"><p>A pause between<br/>one idea and the next.</p><span>Original type study<br/>{$alignment} · {$tracking[0]}px</span></div></section></div></main>
```

代码参考

- 滑块值是一个数组；海报读取其中的首项。

- 代码使用显式属性展开和操作，无需依赖未说明的预处理器。

- 任一构建器存储发生变化，已保存状态就会失效。

### 完整的原始海报和控件样式

语义化 CSS 变量、控件 data-state 选择器、焦点环，以及响应式排版海报。

```
:root{--study-canvas:#f3f0e9;--study-surface:#fffdf8;--study-ink:#32352e;--study-muted:#77796a;--study-line:#dbdece;--study-action:#486348;--study-on-action:#fff;--study-focus:#8aa77c;--study-poster:#e0e8bb;--study-accent:#d68f57;--study-space-1:4px;--study-space-2:8px;--study-space-3:12px;--study-space-4:16px;--study-space-6:24px;--study-space-8:32px}html,body,#app{height:auto;min-height:0;margin:0}*{box-sizing:border-box}body{background:var(--study-canvas);color:var(--study-ink);font-family:system-ui,sans-serif}button{font:inherit;cursor:pointer}button:focus-visible,[role=slider]:focus-visible{outline:3px solid var(--study-focus);outline-offset:4px}button:disabled{opacity:.45;cursor:default}.poster-shell{max-width:1060px;margin:auto;padding:32px}.eyebrow{font-size:10px;font-weight:700;letter-spacing:.14em;color:var(--study-muted)}h1{font-size:34px;line-height:1.15;max-width:650px;margin:12px 0}header>p:last-child{font-size:14px;line-height:1.7;color:var(--study-muted);max-width:620px}.poster-layout{display:grid;grid-template-columns:300px minmax(0,1fr);gap:24px;margin-top:28px}.controls{padding:24px;background:var(--study-surface);border:1px solid var(--study-line);border-radius:14px;align-self:start;min-width:0}.controls h2{font-size:20px;margin:0 0 24px}.control-label{font-size:12px;font-weight:600;margin:0 0 12px}.control-label strong{float:right;color:var(--study-action)}.alignment{display:flex;border:1px solid var(--study-line);padding:4px;border-radius:8px;gap:4px}.align-option{border:0;flex:1;padding:9px 4px;border-radius:5px;font-size:12px;background:transparent;color:var(--study-muted)}.align-option[data-state=checked]{background:var(--study-action);color:var(--study-on-action)}.tracking-control{margin-top:26px}.slider{position:relative;height:24px;display:flex;align-items:center;touch-action:none}.slider:before{content:'';height:4px;background:var(--study-line);position:absolute;inset:10px 0;border-radius:4px}.slider-range{height:4px;position:absolute;background:var(--study-action);border-radius:4px}.slider-thumb{height:20px;width:20px;border:2px solid var(--study-action);background:white;border-radius:50%;cursor:grab}.scale{display:flex;justify-content:space-between;font-size:10px;color:var(--study-muted);margin-top:8px}.grid-control{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--study-line);padding-top:22px;margin-top:24px;font-size:13px}.switch{width:42px;height:24px;padding:3px;border:0;border-radius:999px;background:#b7beaf;flex-shrink:0}.switch span{display:block;width:18px;height:18px;border-radius:50%;background:white;transition:transform .15s}.switch[data-state=checked]{background:var(--study-action)}.switch[data-state=checked] span{transform:translateX(18px)}.hint{font-size:11px;line-height:1.7;color:var(--study-muted);margin:12px 0 24px}.primary{display:block;width:100%;padding:12px;border:0;border-radius:7px;background:var(--study-action);color:white;font-size:13px;font-weight:600}.reset{width:100%;padding:12px 0;border:0;background:transparent;color:var(--study-muted);font-size:11px}.result{font-size:11px;line-height:1.7;color:var(--study-muted);margin:8px 0 0}.poster{background:var(--study-poster);padding:28px;border-radius:14px;min-width:0;overflow:hidden;position:relative}.poster.guides{background-image:linear-gradient(#6680561c 1px,transparent 1px),linear-gradient(90deg,#6680561c 1px,transparent 1px);background-size:24px 24px}.poster-top{display:flex;justify-content:space-between;gap:12px;font-size:9px;font-weight:700;letter-spacing:.1em;position:relative;z-index:1}.poster-orbit{height:130px;position:relative;margin:10px 0 20px}.poster-orbit i{display:block;position:absolute;width:140px;height:140px;background:var(--study-accent);border-radius:50%;right:10%;top:0}.poster-orbit b{display:block;position:absolute;width:140px;height:140px;border:2px solid #617748;border-radius:50%;right:27%;top:0}.poster-title{font-size:clamp(28px,5.5vw,64px);line-height:1.08;font-weight:800;position:relative}.poster-title span{display:block}.poster-bottom{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;border-top:1px solid #9fac7c;margin-top:26px;padding-top:18px;font-size:11px;line-height:1.7}.poster-bottom p{margin:0}.poster-bottom>span{font-size:9px;color:#627046}@media(max-width:740px){.poster-layout{grid-template-columns:minmax(0,1fr)}.poster-shell{padding:20px}h1{font-size:29px}.poster-title{font-size:clamp(30px,9vw,56px)}}@media(max-width:360px){.poster-shell{padding:14px}.controls,.poster{padding:16px}.poster-title{font-size:28px}.poster-orbit{height:110px}.poster-orbit i,.poster-orbit b{width:115px;height:115px}.poster-top{font-size:8px}}@media(prefers-reduced-motion:reduce){.switch span{transition:none}}
```

代码参考

- 所有视觉令牌均为原创，并非 Melt 官方默认值。

- 滑块拇指/范围的位置来自原生构建器属性。

- 装饰性网格的可见性与字距设置相互独立。

## Melt UI 设计系统 Agent 设置

### 实现起点

在 Svelte 5.57.1 中，已验证来自 @melt-ui/svelte 0.86.6 的存储/操作 API。显式构建器语法无需依赖可选的 Melt 预处理器。这并非独立的下一代 runes API。

```
// npm create vite@latest melt-type-study -- --template svelte
// cd melt-type-study && npm install
// npm install svelte@5.57.1 @melt-ui/svelte@0.86.6
// 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
```

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

```
使用 @melt-ui/svelte 0.86.6 的 store/action 构建器搭配 Svelte 5 完成字体排版构成研究。为 createRadioGroup、createSlider 和 createSwitch 元素同时添加 attributes 和 actions；使用给出的显式语法，无需依赖未说明的预处理器。保留 slider 的单元素数组和 elements.thumbs 契约、对齐值及网格可见性。将海报的计算样式直接绑定到这些 stores；发生更改后使已保存的反馈失效，并重置为 left、[2] 和 true。不要混用较新的 runes API 或预约模型。
```

## Melt UI 设计系统来源与范围

@melt-ui/svelte 0.86.6 的 store/action 构建器搭配 Svelte 5.57.1。所有视觉令牌和海报内容均为原创。保存记录仅保留本地预览状态，不会导出或发布设计。

- 用法 构建器 attributes、actions 和状态 stores。

- 预处理器 为何使用：melt 需要预处理，以及对应的显式写法。

- 单选组 互斥选择与键盘导航。

- Slider 数组值、限制、方向和按键。

- Switch 布尔状态与语义。

- 受控状态 可写 stores 与更改函数。

- 安装 指定版本的软件包配置。

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

### Naive UI

原生 Naive UI 数据表工作台，采用经过验证的主题对象值，支持行选择、展开、排序、分页和本地批量审核操作。

### Nuxt UI

使用真实 Vue 组件、语义化主题引用、输入验证和明确的本地草稿行为，构建完整的 Nuxt UI 4.11.3 简报编辑器。

### Oruga UI

原生 Oruga 目录编辑器，支持搜索和移除主题标签、强制执行词汇限制、使用可选主题的真实令牌，并通过实时卡片呈现所选标签。


- [实现参考](https://www.melt-ui.com/docs/builders/slider)
- [来源](https://www.melt-ui.com/docs/usage)
- [来源](https://www.melt-ui.com/docs/builders/slider)
- [阅读配套规范](https://www.melt-ui.com/docs/usage)
- [阅读配套规范](https://www.melt-ui.com/docs/preprocessor)
- [阅读配套规范](https://www.melt-ui.com/docs/builders/radio-group)
- [阅读配套规范](https://www.melt-ui.com/docs/builders/slider)
- [阅读配套规范](https://www.melt-ui.com/docs/builders/switch)
- [阅读配套规范](https://www.melt-ui.com/docs/controlled)
- [阅读配套规范](https://www.melt-ui.com/docs/installation)
- [代码参考](https://www.melt-ui.com/docs/usage)
- [用法 构建器 attributes、actions 和状态 stores。](https://www.melt-ui.com/docs/usage)
- [预处理器 为何使用：melt 需要预处理，以及对应的显式写法。](https://www.melt-ui.com/docs/preprocessor)
- [单选组 互斥选择与键盘导航。](https://www.melt-ui.com/docs/builders/radio-group)
- [Slider 数组值、限制、方向和按键。](https://www.melt-ui.com/docs/builders/slider)
- [Switch 布尔状态与语义。](https://www.melt-ui.com/docs/builders/switch)
- [受控状态 可写 stores 与更改函数。](https://www.melt-ui.com/docs/controlled)
- [安装 指定版本的软件包配置。](https://www.melt-ui.com/docs/installation)
