From 9717eaf358e64202f12556442d4a77f90dfa8128 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 12:29:38 +0000 Subject: [PATCH] =?UTF-8?q?docs(protocol):=20widget-contract=20=E7=9A=84?= =?UTF-8?q?=20Theme=20=E6=AE=B5=E5=81=9C=E6=AD=A2=E6=95=99=20#3494=20?= =?UTF-8?q?=E5=B7=B2=E5=88=A0=E9=99=A4=E7=9A=84=20`density`,token=20?= =?UTF-8?q?=E8=AF=8D=E8=A1=A8=E6=8C=89=20#5021=20=E9=87=8D=E5=86=99=20(#52?= =?UTF-8?q?91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `content/docs/protocol/objectui/widget-contract.mdx` 的 Theme 段散文与 YAML 示例 都在教 `density`(「`density` is one of `compact`, `regular`, or `spacious`」+ 示例里的 `density: regular`)。该键在 #3494 就被删了,而 `ThemeSchema` 自 #4001 批 15 起是 `.strict()` —— 照抄本页示例必然 parse 失败。拒绝本身是响亮且带处方的 (`THEME_RETIRED_KEY_GUIDANCE` 的 `density` 墓碑),问题在于平台自己的权威文档把 作者送进了那次拒绝;对从这一页取样写主题的 AI 作者尤其贵。 原示例其实有两处解析失败——除 `density` 外,`colors:` 下只有一行注释,YAML 解析成 `null`,而 `colors` 必填且其 `primary` 必填。现在的示例是一份真能通过 `ThemeSchema` 解析的完整主题。 同时把整段 token 词表刷新到 #5021 之后: - 逐一列出 `ThemeSchema` 的十个可写键,并给出每个键实际落到 document 上的 CSS 变量 ——`colors` 出门时的改名(`surface` → `--card`、`text` → `--foreground`、 `error` → `--destructive` …)、`borderRadius.base` / `shadows.base` 发裸 `--radius` / `--shadow`、`typography` 自 #5021 起只剩 `fontFamily.base` (发 `--font-sans`)、`customVars` 逐字发出。 - 新增 Callout 点名两批退役键:#3494 的八个,以及 #5021(`@objectstack/spec` 17.0.0, ADR-0049)的 `animation` / `zIndex`、`typography` 四条排版标尺、 `fontFamily.heading` / `mono`;处方统一是 `customVars`(逐字节等价替代),并给出 `os migrate meta --from 16`。 每条断言都对着 `packages/spec/src/ui/theme.zod.ts` 与 objectui `ThemeEngine.ts` 逐键核过:16 个退役键全部被拒、10 个活键全部被接受。 不碰 `content/docs/references/**` 与 `content/docs/releases/`。Docs-only。 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE --- .../widget-contract-theme-token-vocabulary.md | 36 ++++++++++++++++ .../protocol/objectui/widget-contract.mdx | 41 +++++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 .changeset/widget-contract-theme-token-vocabulary.md 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?