diff --git a/.changeset/widget-contract-theme-token-vocabulary.md b/.changeset/widget-contract-theme-token-vocabulary.md new file mode 100644 index 0000000000..6adf8f9cb0 --- /dev/null +++ b/.changeset/widget-contract-theme-token-vocabulary.md @@ -0,0 +1,36 @@ +--- +--- + +docs(protocol): `protocol/objectui/widget-contract` 的 Theme 段停止教 #3494 已删除的 `density`,整段 token 词表按 #5021 的退役结果重写 (#5291) + +该页 Theme 段的散文与 YAML 示例都在教 `density`(「`density` is one of `compact`, +`regular`, or `spacious`」+ 示例里的 `density: regular`)。这个键在 #3494 就被删了, +而 `ThemeSchema` 自 #4001 批 15 起是 `.strict()` —— 两件事叠加的结果是**照抄本页示例 +必然 parse 失败**:`defineStack({ themes })` / `defineTheme()` 都会拒。拒绝本身是响亮 +且带处方的(`THEME_RETIRED_KEY_GUIDANCE` 里 `density` 的墓碑),问题在于平台自己的权威 +文档把作者送进了那次拒绝——对从这一页取样写主题的 AI 作者尤其贵。 + +原示例其实有**两处**解析失败:除 `density` 外,`colors:` 下只有一行注释,YAML 解析成 +`null`,而 `colors` 是必填且 `primary` 必填。现在的示例是一份真能通过 `ThemeSchema` +解析的完整主题。 + +同时把整段的 token 词表口径刷新到 #5021 之后: + +- 逐一列出 `ThemeSchema` 的**十个**可写键(`name` / `label` / `description` / `mode` / + `extends` 五个身份与继承键,加 `colors` / `borderRadius` / `shadows` / `typography` / + `customVars` 五个 token 键),并给出每个键实际落到 document 上的 CSS 变量——包括 + `colors` 出门时的改名(`surface` → `--card`、`text` → `--foreground`、 + `error` → `--destructive` …)、`borderRadius.base` / `shadows.base` 发的是裸 + `--radius` / `--shadow`、`typography` 自 #5021 起只剩 `fontFamily.base`(发 + `--font-sans`)。 +- 新增一段 Callout 点名两批退役键:#3494 的 `spacing` / `breakpoints` / `logo` / + `density` / `wcagContrast` / `rtl` / `touchTarget` / `keyboardNavigation`,以及 #5021 + (`@objectstack/spec` 17.0.0, ADR-0049)的 `animation` / `zIndex`、`typography` 四条 + 排版标尺、`fontFamily.heading` / `mono`;两批的处方都是 `customVars`,且是逐字节等价 + 的替代(`customVars` 里写 `font-size-lg` 发的就是同一个 `--font-size-lg`),并给出 + `os migrate meta --from 16`。 + +页面的每条断言都对着 `packages/spec/src/ui/theme.zod.ts` 与 objectui `ThemeEngine.ts` +逐键核过:16 个退役键全部被拒、10 个活键全部被接受。 + +Docs-only;releases nothing. diff --git a/content/docs/protocol/objectui/widget-contract.mdx b/content/docs/protocol/objectui/widget-contract.mdx index cb6a7c96c3..59c880bde9 100644 --- a/content/docs/protocol/objectui/widget-contract.mdx +++ b/content/docs/protocol/objectui/widget-contract.mdx @@ -316,21 +316,54 @@ The widget manifest carries **no** performance block. Virtualization for large d ## Theme -ObjectUI theming is defined by `ThemeSchema` in `packages/spec/src/ui/theme.zod.ts`. A theme requires a `name`, `label`, and `colors` palette. The `mode` is one of `light`, `dark`, or `auto`, and `density` is one of `compact`, `regular`, or `spacious`. `borderRadius` is a scale object (`none`/`sm`/`base`/`md`/`lg`/...), not a single token: +ObjectUI theming is defined by `ThemeSchema` in `packages/spec/src/ui/theme.zod.ts`, and it declares **ten** authorable keys — that list is the whole vocabulary. Five of them are identity and inheritance: `name` (a snake_case identifier) and `label` are required, `description` is optional, `mode` is one of `light`, `dark`, or `auto` (default `light`), and `extends` names another theme to inherit from. The other five are the token surface: + +| Key | Required | Shape | What it puts on the document | +|-------|-------|-------|-------| +| `colors` | ✅ | `ColorPalette`; only `primary` is mandatory inside it | The shadcn palette variables — **renamed on the way out**: `surface` emits `--card`, `text` emits `--foreground`, `textSecondary` emits `--muted-foreground`, `disabled` emits `--muted`, `error` emits `--destructive`. | +| `borderRadius` | — | A scale object (`none`/`sm`/`base`/`md`/`lg`/`xl`/`2xl`/`full`), not a single token | `--radius-sm`, `--radius-md`, ... — and `base` emits the bare `--radius`. | +| `shadows` | — | The same stops plus `inner` | `--shadow-sm`, `--shadow-md`, ... — and `base` emits the bare `--shadow`. | +| `typography` | — | One live key since #5021: `fontFamily.base` | `--font-sans`. | +| `customVars` | — | A flat string map | Every entry verbatim, `--` prefixed if you omit it: `z-modal: '1050'` emits `--z-modal: 1050`. This is the declared door for any other custom property. | ```yaml name: corporate label: Corporate mode: light -density: regular colors: - # ColorPalette configuration + primary: '#2563eb' + surface: '#ffffff' + text: '#111827' borderRadius: base: 0.25rem md: 0.375rem +shadows: + base: '0 1px 3px rgb(0 0 0 / 0.1)' +typography: + fontFamily: + base: 'Inter, system-ui, sans-serif' +customVars: + space-4: 1rem ``` -Widgets inherit the active theme automatically; they do not each carry a full set of color/typography props. +`ThemeSchema` is `.strict()` (#4001), so a key outside that list is a **parse failure** at `defineStack({ themes })` / `defineTheme()`, carrying its own prescription — not a value silently dropped while the theme still reports valid. + + + **Older theme samples no longer parse** — check yours before copying it forward. + **#3494** removed `spacing`, `breakpoints`, `logo`, `density`, `wcagContrast`, + `rtl`, `touchTarget` and `keyboardNavigation`: the theme engine never emitted a + variable for any of them, so authoring one was a silent no-op. **#5021** + (`@objectstack/spec` 17.0.0, ADR-0049) removed `animation`, `zIndex`, the + `typography.fontSize` / `fontWeight` / `lineHeight` / `letterSpacing` scales and + `typography.fontFamily.heading` / `mono`: those *were* emitted, faithfully and + for years, but no first-party component or stylesheet has ever read one. + The prescription in both waves is `customVars`, and it is a byte-for-byte + replacement — `customVars` carrying `font-size-lg: 1.125rem` puts exactly the + same `--font-size-lg` on the document the retired scale did. Run + `os migrate meta --from 16` to rewrite stored metadata automatically. + + +Widgets inherit the active theme automatically; they do not each carry their own copy of the palette or the font stack. ## What's Next?