diff --git a/.ua/backlog.json b/.ua/backlog.json index 3878668..8258cf3 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -1612,6 +1612,14 @@ "acceptance": "ua tokens <子串> 只列匹配项并在末尾标注匹配词,--json 同步过滤;无匹配时给出总数并以 1 退出。", "notes": "", "status": "done" + }, + { + "id": "g157", + "title": "补配方 10:暗色主题切换", + "motivation": "令牌层早就支持 [data-theme=dark],但配方里没有任何一条说清「怎么切、初值怎么定、原生控件为何仍是白底」,实践只能靠翻令牌表猜。", + "acceptance": "recipes.md 新增配方 10(切 data-theme + 同步 color-scheme + 初值先读 localStorage),verify 的配方结构校验通过,llms-full 与 MCP get_recipe 10 可取到骨架。", + "notes": "", + "status": "open" } ] } diff --git a/llms-full.txt b/llms-full.txt index cee94bb..4715bf8 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -2286,6 +2286,24 @@ grid({ columns: 2, gutter: 'lg' }, - 标题一律 `typography({ variant: 'title', level })` 出语义 `h1-h5`;正文长文本用 `ellipsis` 截断并自动挂 `title` 看全文。 - 只读字段用 `descriptions`(不要用 `form`):`form` 承载输入与校验,`descriptions` 只负责 label:value 对齐。 +## 配方 10:暗色主题切换(只切 data-theme,不改令牌名) + +```ts +const saved = localStorage.getItem('ua-theme'); +const dark = signal(saved ? saved === 'dark' : matchMedia('(prefers-color-scheme: dark)').matches); +effect(() => { + document.documentElement.dataset.theme = dark() ? 'dark' : 'light'; + document.documentElement.style.colorScheme = dark() ? 'dark' : 'light'; // 原生控件(date/滚动条)跟着变 + localStorage.setItem('ua-theme', dark() ? 'dark' : 'light'); +}); +floatButton({ icon: '🌗', label: '切换主题', onClick: () => dark(!dark()) }); +``` + +要点: +- 只改 `[data-theme]` 的取值:暗色是令牌**值**的另一套,名字永远不变,组件样式一律不写主题判断。 +- 初值顺序是「先 localStorage、再 prefers-color-scheme」;反过来会让用户的手动选择被系统偏好覆盖。 +- 同步设置 `color-scheme`,否则原生控件(日期选择、滚动条)在暗色下仍是白底。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。 diff --git a/llms.txt b/llms.txt index 61ef067..f2db143 100644 --- a/llms.txt +++ b/llms.txt @@ -153,3 +153,4 @@ - 配方 7:筛选栏(层级归属 + 日期区间)(3 条要点) - 配方 8:评论输入(@ 提及 + 参与人头像组)(3 条要点) - 配方 9:详情页排版(栅格 + 排版文本 + 描述列表)(3 条要点) +- 配方 10:暗色主题切换(只切 data-theme,不改令牌名)(3 条要点) diff --git a/packages/tools/cli/recipes.md b/packages/tools/cli/recipes.md index d92af50..bbdfc07 100644 --- a/packages/tools/cli/recipes.md +++ b/packages/tools/cli/recipes.md @@ -184,6 +184,24 @@ grid({ columns: 2, gutter: 'lg' }, - 标题一律 `typography({ variant: 'title', level })` 出语义 `h1-h5`;正文长文本用 `ellipsis` 截断并自动挂 `title` 看全文。 - 只读字段用 `descriptions`(不要用 `form`):`form` 承载输入与校验,`descriptions` 只负责 label:value 对齐。 +## 配方 10:暗色主题切换(只切 data-theme,不改令牌名) + +```ts +const saved = localStorage.getItem('ua-theme'); +const dark = signal(saved ? saved === 'dark' : matchMedia('(prefers-color-scheme: dark)').matches); +effect(() => { + document.documentElement.dataset.theme = dark() ? 'dark' : 'light'; + document.documentElement.style.colorScheme = dark() ? 'dark' : 'light'; // 原生控件(date/滚动条)跟着变 + localStorage.setItem('ua-theme', dark() ? 'dark' : 'light'); +}); +floatButton({ icon: '🌗', label: '切换主题', onClick: () => dark(!dark()) }); +``` + +要点: +- 只改 `[data-theme]` 的取值:暗色是令牌**值**的另一套,名字永远不变,组件样式一律不写主题判断。 +- 初值顺序是「先 localStorage、再 prefers-color-scheme」;反过来会让用户的手动选择被系统偏好覆盖。 +- 同步设置 `color-scheme`,否则原生控件(日期选择、滚动条)在暗色下仍是白底。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。