Files
classhelper-island-refactor…/out/sections/03-design-tokens.md
T
ClassIsland Prompt Kit 22c1784bab feat: ClassIsland / ClassHelper 灵动岛提示词套件
- 重构版主提示词(14 parts,面向 ClassHelper 灵动岛重构)
- ClassIsland 全量规格提示词(20 parts,含分卷与逐章版本)
- 投喂指南、分卷、逐节文件
- 调研记录、一致性基线、生成与质检脚本
2026-11-12 21:59:58 +08:00

36 KiB
Raw Blame History

3. 设计系统 Token 总表(颜色 / 字体 / 圆角 / 间距 / 阴影 / 层级 / DPI / 深浅色)

本节是整份提示词的「地基」。实现者必须先落地本节的 token(CSS 自定义属性 + TypeScript 常量),再开始写任何界面。任何界面代码不得出现裸色值、裸字号、裸圆角,一律引用本节 token。

实现技术栈为 ClassHelper 的 Electron + Vue 3 栈,宿主已有 packages/ui/src/tokens.css 的 --ch-ui-* 与桌面端 renderer/styles/index.css 的 --ch-*。保留并复用这些既有 token 作为「应用外壳层」,新增 --ci-* 命名空间承载 ClassIsland 主界面(岛)层 token。两层必须分开:--ch-* 管设置中心/管理页,--ci-* 管岛与课程信息。

3.1 颜色 Token

3.1.1 强调色与派生色

Token 名 默认值 用途 建议 CSS 变量 源码证据
PrimaryColor(用户强调色) #00BFFF(Colors.DeepSkyBlue) 设置项「强调色」的默认值;ColorSource=0 时作为全站 accent --ci-accent ClassIsland/Models/Settings.cs:35、Settings.cs:992
SecondaryColor #7FFFD4(Colors.Aquamarine) 备用强调色(组件/图表次级色) --ci-accent-2 Settings.cs:36、Settings.cs:1003
FluentAvalonia 初始 accent DodgerBlue=#1E90FF 主题服务尚未介入时的启动色 --ci-accent-fallback ClassIsland/App.axaml:17
SelectedPlatte 兜底 DodgerBlue=#1E90FF 壁纸调色板取不到颜色时的兜底 --ci-accent-palette-fallback Settings.cs:1036-1039、Settings.cs:80
AccentFillColorDefaultBrush 由 accent 派生(Fluent 资源) 提醒遮罩填充、教程高亮框、进度条强调 --ci-accent-fill ClassIsland.Core/StylesBase.axaml:90-93、XamlThemes/FluentTheme/Styles.axaml:180
AccentFillColorTertiaryBrush accent 低透明度变体 课程列表展开态底色 --ci-accent-fill-tertiary ClassIsland.Core/Controls/LessonsControls/LessonControlExpanded.axaml:182
AccentTextFillColorPrimaryBrush accent 文字色 拖拽高亮描边、TeachingTip 指示箭头 --ci-accent-text EditableComponentsListBox.axaml:310、MyTeachingTipStyles.axaml:213
TextOnAccentFillColorPrimaryBrush 白/黑(随 accent 对比度) 遮罩上的文字 --ci-text-on-accent FluentTheme/Styles.axaml:162,182;ClassicTheme/Styles.axaml:142
CustomizedAccentBarBackground1Brush 亮 #FFDDE6F0 / 暗 #26374C;运行时被覆盖为 accent 的 10% 透明 「强调按钮」淡底、Button.foreground-accent --ci-accent-soft Themes/LightTheme.axaml:18、Themes/DarkTheme.axaml:18、Services/ThemeService.cs:66-74

运行时强调色决策必须严格按以下分支实现(源码见 ClassIsland/MainWindow.axaml.cs:743-764):

  1. ColorSource == 0(自定义)→ 使用 PrimaryColor;
  2. ColorSource == 1(壁纸主题色)或 3(屏幕主题色)→ 使用 SelectedPlatte(壁纸调色板第 SelectedPlatteIndex 项);
  3. ColorSource == 2(跟随系统)→ 传 null,交给系统强调色;
  4. 其余 → 兜底 DodgerBlue。

--ci-accent-soft 必须以 color-mix(in srgb, var(--ci-accent) 10%, transparent) 实时推导,不得写死。ClassHelper 已有等价写法可复用:packages/ui/src/theme.css:4-9 用 color-mix() 派生 Element Plus 的 --el-color-primary-light-*。

3.1.2 前景文字阶梯(前景色 5 级)

主界面自定义前景色时,前景色不是 1 个值,而是由同一个基色派生出 5 个 alpha 版本,必须按下表实现(源码:ClassIsland.Core/Helpers/UI/ControlColorHelper.cs:20-52):

层级 资源键 alpha 用途 建议 CSS 变量
1 TextFillColorPrimaryBrush 255(100%) 主要文字、标题 --ci-text-1
2 TextFillColorInformativeSecondaryBrush 218(85.5%) 次要说明(本项目覆盖值) --ci-text-2
3 TextFillColorSecondaryBrush 197(77.3%) 辅助文字 --ci-text-3
4 TextFillColorTertiaryBrush 135(52.9%) 装饰/弱提示 --ci-text-4
5 TextFillColorDisabledBrush 93(36.5%) 禁用态 --ci-text-5

实现规则:

  • 未启用自定义前景色时,上述 5 个 token 使用 Fluent 默认值:亮色 #E4000000 / #9E000000 / #72000000 / #5C000000,深色 #FFFFFFFF 及对应 alpha 版本【推断:FluentAvalonia 资源值不在本仓库,按 Fluent 2 规范给出】。
  • 启用自定义前景色时,5 个 token 全部按上表 alpha 从 CustomForegroundColor 派生,且必须同时重设 TemplatedControl.Foreground 与 TextElement.Foreground,否则模板内文字会漏改(ControlColorHelper.cs:34-40)。
  • 关闭自定义前景色时,必须 Remove 这 5 个局部资源并 SetValue(..., AvaloniaProperty.UnsetValue) 回落(ControlColorHelper.cs:44-50)——映射到 CSS 即删除元素上的内联 --ci-text-*,回落 :root。
  • 两个默认覆盖值:亮色 TextFillColorInformativeSecondaryBrush = #c0000000(75% 黑),深色 #daffffff(85.5% 白)(Themes/LightTheme.axaml:20、Themes/DarkTheme.axaml:20)。
  • 语义层级类必须映射为 CSS 工具类:.l-primary|.l1 → --ci-text-1、.l-secondary|.l2 → --ci-text-2、.l-instructive|.l3 → --ci-text-3、.l-decoration|.l4 → --ci-text-4、.l-inactive|.l5 → --ci-text-5(ClassIsland.Core/Themes/Layers.axaml:10-43)。

3.1.3 背景与表面色

Token 名 亮色 深色 用途 建议 CSS 变量 源码证据
SolidBackgroundFillColorBaseBrush #F3F3F3【推断】 #202020【推断】 经典主题岛背景、编辑模式窗口底、抽屉内容底、主题卡渐变底 --ci-bg-base ClassicTheme/Styles.axaml:214;DrawerHost.axaml:29;MainWindow.axaml:188
SolidBackgroundFillColorSecondaryBrush #EEEEEE【推断】 #1C1C1C【推断】 Fluent 主题岛背景 --ci-bg-secondary FluentTheme/Styles.axaml:45
SolidBackgroundFillColorTertiaryBrush #F9F9F9【推断】 #282828【推断】 弹出层底(.popup-bg) --ci-bg-tertiary StylesBase.axaml:291
ControlFillColorSecondaryBrush 半透明白/黑 同左 主题卡底色 --ci-fill-secondary ThemesSettingsPage.axaml:149
SmokeFillColorDefaultBrush 半透明遮罩 同左 编辑模式窗口背景、抽屉忽略层 --ci-smoke MainWindow.axaml:178;DrawerHost.axaml:20
Layer 应用底色 #F3F3F3 #161719 设置中心/管理页页面底(沿用 ClassHelper) --ch-bg ClassHelper/renderer/styles/index.css:27,114
Layer 卡片底 rgba(255,255,255,.7) rgba(32,33,36,.72) 应用外壳卡片 --ch-layer 同上 :28,115
CustomBackgroundColor #000000(默认) 同左 岛自定义背景色默认值 --ci-island-bg-custom Settings.cs:34、Settings.cs:1129

主界面行的背景最终呈现必须叠加两个不透明度:

  • 自定义背景色本身的不透明度:--ci-island-bg-opacity,默认 0.5(Settings.cs:64、:1141;Fluent 用 MainWindowStylesAssist.BackgroundOpacity 绑定到 Border.Opacity,见 FluentTheme/Styles.axaml:44);
  • 整行不透明度:MainWindowLineSettings.Opacity,默认 1.0(ClassIsland.Core/Models/Components/MainWindowLineSettings.cs:42;Controls/MainWindowLine.axaml:51)。
  • 鼠标移出淡化态:整行 opacity = 0.05(Controls/MainWindowLine.axaml:73-75)。

3.1.4 描边与分隔线

Token 名 值 用途 建议 CSS 变量 源码证据
岛描边 1px ControlElevationBorderBrush 经典/Fluent 行背景描边 --ci-stroke-island / 宽度 --ci-stroke-island-w:1px FluentTheme/Styles.axaml:46-47;ClassicTheme/Styles.axaml:61-65
ControlStrokeColorDefaultBrush 亮色半透明黑 编辑模式选中框描边 --ci-stroke-control MainWindow.axaml:357
DividerStrokeColorDefaultBrush 亮色半透明黑 操作条分隔线(1px,长 25px) --ci-stroke-divider MainWindow.axaml:610-612
SurfaceStrokeColorFlyoutBrush 半透明 弹窗描边 --ci-stroke-flyout StylesBase.axaml:292
ControlStrongFillColorDefaultBrush 中灰 OOBE 方块、Workflow 进度条底、Shimmer 底 --ci-fill-strong OobeIntroAnimationControl.axaml:34;WorkflowProgressIndicatorItemControl.axaml:26;Shimmer.axaml:11
主题卡描边 1px ControlElevationBorderBrush 主题网格卡片 --ci-stroke-card ThemesSettingsPage.axaml:150-151
拖拽高亮描边 1px accent 组件拖拽占位 --ci-stroke-drag EditableComponentsListBox.axaml:310-311
教程高亮描边 2.5px(外框)/ 3px(四角) 教程 spotlight --ci-stroke-tutorial TutorialHighlightControl.axaml:96-118

3.1.5 状态色

天气与空气质量状态色(浅色/深色两套,必须都实现):

语义 亮色 深色 建议 CSS 变量 源码证据
AQI 1 优 ForestGreen=#228B22 MediumSeaGreen=#3CB371 --ci-aqi-1 LightTheme.axaml:10;DarkTheme.axaml:10
AQI 2 良 #CCCC00 Yellow=#FFFF00 --ci-aqi-2 :11
AQI 3 轻度 DarkOrange=#FF8C00 Orange=#FFA500 --ci-aqi-3 :12
AQI 4 中度 IndianRed=#CD5C5C 同亮色 --ci-aqi-4 :13
AQI 5 重度 DarkRed=#8B0000 同亮色 --ci-aqi-5 :14
AQI 6 严重 Purple=#800080 MediumPurple=#9370DB --ci-aqi-6 :15
雨天图标色 Blue=#0000FF DeepSkyBlue=#00BFFF --ci-weather-rain LightTheme.axaml:3;DarkTheme.axaml:3
上课发光 DropShadowEffect blur 6(亮)/2(暗),颜色 #FFFF00 同左 --ci-glow-class LightTheme.axaml:4-7;DarkTheme.axaml:4-7
危险/删除按钮 IndianRed=#CD5C5C 同左 --ci-danger Themes/Generic.xaml:225-226,275-276;MainWindow.axaml:435
警告/错误图标 SystemFillColorCriticalBrush / SystemFillColorCautionBackgroundBrush 同左 --ci-warning-* StylesBase.axaml:209,217;ThemesSettingsPage.axaml:343

3.1.6 阴影与遮罩色(必须逐值实现)

用途 值 建议 CSS 变量 源码证据
Fluent 岛投影 0 4 8 2 #48000000 --ci-shadow-island: 0 4px 8px 2px #48000000 FluentTheme/Styles.axaml:49
提醒遮罩时岛投影 0 8 32 0 #66000000 --ci-shadow-mask FluentTheme/Styles.axaml:324,327
竖抽屉/遮罩卡投影 0 8 32 0 #66000000 --ci-shadow-drawer VerticalDrawer.axaml:45
横抽屉内浮层投影 0 0 8 #33000000 --ci-shadow-drawer-x DrawerHost.axaml:33
经典主题提醒时行投影 DropShadowEffect BlurRadius=8, Opacity=1, Offset=0 --ci-shadow-classic-mask ClassicTheme/Styles.axaml:283-287
时间线装饰器阴影 DropShadowEffect opacity 0.4, blur 8 --ci-shadow-adorn Themes/Generic.xaml:215-219
弹窗底渐变遮罩 #00ffffff→(0.65)#00ffffff→(1)#ffffffff --ci-mask-fade ThemesSettingsPage.axaml:162-169
教程聚光遮罩 #99000000(60% 黑) --ci-scrim-tutorial TutorialSpotlightControl.axaml:45-61
编辑模式调试叠加 #77222222 --ci-debug-bg MainWindow.axaml:645
启动闪屏底 #88111111 + 1px ControlStrokeColorOnAccentDefaultBrush --ci-splash-bg SplashWindow.axaml:24-28
主题卡渐变底 径向 #ff0c0e1f→#ff0d1111(关于页) --ci-brand-gradient-a/b AboutSettingsPage.axaml:153-154
关于页正文底 #0d1111 --ci-brand-dark AboutSettingsPage.axaml:131
通知涟漪默认填充 AccentFillColorDefaultBrush(可被 NotificationContent.Color 覆盖) --ci-ripple RippleEffect.axaml.cs:61;MainWindowLine.cs:750
通知涟漪描边宽 200(Ellipse StrokeThickness) --ci-ripple-stroke:200 RippleEffect.axaml:15

3.2 字体 Token

3.2.1 字体族

Token 值 用途 建议 CSS 变量/写法
AppFont(全局默认) HarmonyOS Sans SC, Microsoft YaHei UI, Noto Sans CJK SC, Noto Sans SC, PingFang SC, Source Han Sans SC, SimHei, WenQuanYi Micro Hei, sans-serif, FluentSystemIcons-Resizable 全应用默认字体 --ci-font: 'HarmonyOS Sans SC', 'Microsoft YaHei UI', 'Noto Sans CJK SC', 'Noto Sans SC', 'PingFang SC', 'Source Han Sans SC', SimHei, sans-serif
MainWindowFont(岛字体,用户可改) 默认等于 DefaultFontFamilyKey:avares://ClassIsland/Assets/Fonts/#HarmonyOS Sans SC, ...FluentSystemIcons-Resizable 只作用于岛的 ZoomBorder 文本 --ci-font-island(元素级覆盖)
HarmonyOsSans(旧键) HarmonyOS Sans SC, Microsoft YaHei UI, SimHei 旧样式/右键菜单 兼容别名
BackendFontFamily Microsoft YaHei UI 后端渲染/图表兜底 --ci-font-backend
图标字体 1 FluentSystemIcons-Resizable(avares://ClassIsland.Core/Assets/Fonts/#FluentSystemIcons-Resizable) 全局 Fluent 图标 --ci-font-icon-fluent
图标字体 2 lucide(#lucide) Lucide 天气图标等 --ci-font-icon-lucide
图标字体 3 SF-Symbols(#SF-Symbols) SFSymbols 天气图标 --ci-font-icon-sf

证据:ClassIsland/Assets/Fonts/Fonts.axaml:3、Assets/Fonts/Fonts.xaml:3、MainWindow.axaml.cs:185-189、App.axaml:48、ClassIsland.Core/AppBase.cs:142-152、ClassIsland.Core/ThemeBase.axaml:46-47。

实现要求:

  • 字体栈必须按上表顺序声明,任何一环缺失即回落下一位;不得只写 HarmonyOS Sans SC。
  • 字体文件必须以本地资源打包,禁止运行时从网络加载字体(离线教室环境)。
  • 图标字体与正文字体必须拆成两个 token,图标组件禁止继承正文字体族。

3.2.2 字重

字重设置以整数保存,映射表必须逐值实现(ClassIsland.Core/Converters/IntToFontWeightConverter.cs:16-28):

数值 字重名 CSS
100 Thin 100
200 ExtraLight 200
300 Light 300
400 Normal 400
500 Medium(默认) 500
600 SemiBold 600
700 Bold 700
800 ExtraBold 800
900 Black 900
其他 Normal 400

默认字重来自 Settings.cs:101((int)FontWeight.Medium = 500)。岛内绝大多数文字必须用 500(Medium),标题可用 700(Bold),说明文字用 400(Regular)。

4 档核心字号在设置页的输入范围均为 1–40 px(AppearanceSettingsPage.axaml:482-533,NumberBox 的 Minimum=1、Maximum=40)。实现时必须允许 1–40 的整数/小数输入,并在预览区用四行示例文字实时展示 4 档效果(源码「字号预览」tab:AppearanceSettingsPage.axaml:570-591)。

3.2.3 字号阶梯(核心 4 档 + 扩展档)

核心 4 档是用户可调的「主界面字号」,默认值与用途如下(Settings.cs:197-200;ClassIsland.Core/ThemeBase.axaml:32-35;Settings.cs:1209-1251):

Token 默认 px 用途 建议 CSS 变量 证据
MainWindowSecondaryFontSize 14 次要信息:天气副标题、日期星期、倒计时标签 --ci-fs-secondary ThemeBase.axaml:32;WeatherComponent.axaml:261,294,296,305
MainWindowBodyFontSize 16 正文:课程名、时间、温度 --ci-fs-body ThemeBase.axaml:33;MainWindow.axaml:313;CountDownComponent.axaml:65
MainWindowEmphasizedFontSize 18 强调:时钟、提醒主文案 --ci-fs-emphasized ThemeBase.axaml:34;ClockComponent.axaml:14;TwoIconsMaskTemplate.axaml:14
MainWindowLargeFontSize 20 大号标题 --ci-fs-large ThemeBase.axaml:35

扩展固定档(非用户设置,必须写死为 token 并说明来源):

字号 用途 建议 CSS 变量 证据
9 启动闪屏版本号(0.5 不透明度) --ci-fs-version SplashWindow.axaml:86-87
12 主题卡作者名 --ci-fs-caption ThemesSettingsPage.axaml:191
13 组件设置小字、ClassHelper 控件基准 --ci-fs-control-base CountDownComponentSettingsControl.axaml:185-201;ClassHelper/renderer/styles/index.css:97
14 通用控件/次级标签 --ci-fs-label MainWindow.axaml:406,452,497
16 主题卡名称、闪屏状态文字 --ci-fs-title ThemesSettingsPage.axaml:188;SplashWindow.axaml:80
17 滚动提醒文字 --ci-fs-rolling RollingTextTemplate.axaml:26
18 OOBE 说明文字 --ci-fs-oobe-body WelcomeWindowIntroControl.xaml:166
20 启动 logo 文字、导航标签 --ci-fs-brand SplashWindow.axaml:56-58;StylesBase.axaml:118-123
22 天气温度/图标文字 --ci-fs-weather WeatherComponent.axaml:86-175
32 OOBE 大标题 --ci-fs-oobe-title OobeIntroAnimationControl.axaml:69,87;WelcomePage.axaml:38

实现硬约束:

  • 4 档核心字号必须由用户设置驱动,且必须能作用到「组件自身」与「单个主界面行」两个作用域:行级覆盖时把 4 个变量写到行根元素的 style 上;关闭行级覆盖时移除内联变量,回落 :root(MainWindowCustomizableNodeHelper.cs:20-37)。
  • 缩放:所有字号乘以界面缩放 --ci-scale(默认 1.0),但不得用浏览器 zoom,必须用布局缩放以保持像素对齐(见 3.8)。
  • 行高:源码未给出显式 LineHeight,建议正文 line-height: 1.25、说明文字 1.6【推断:依据 ClassHelper theme.css:60-63 的 line-height:1.6 与 ClassIsland 主界面 40px 行高/16px 字号的比值】。

3.3 圆角 Token

Token 默认值 用途 建议 CSS 变量 证据
RadiusX / RadiusY(岛圆角) 8(UI 范围 0–20,步进 0.5,提示文案:调至最大时左右边缘为半圆) 主界面行背景圆角;SizeDoubleToCornerRadiusConverter 以 ConverterParameter=1.0 直接取值(除以 1 即原值) --ci-radius-island: 8px Settings.cs:183-184、:1187-1207;AppearanceSettingsPage.axaml:75-87;FluentTheme/Styles.axaml:48,91,124,160-168,252;SizeDoubleToCornerRadiusConverter.cs:12-18
行级自定义圆角 0(关闭) 单行覆盖圆角 --ci-radius-island-local MainWindowLineSettings.cs:40-41
岛内容高度 40 所有行的容器高度(Fluent/Classic 同值) --ci-island-height: 40px FluentTheme/Styles.axaml:65;ClassicTheme/Styles.axaml:16;MainWindowLine.axaml:16
弹窗圆角 6 .popup-bg、编辑模式操作条 --ci-radius-popup: 6px StylesBase.axaml:295;MainWindow.axaml:488,599
卡片圆角 4 设置项卡片、主题卡、Shimmer、时间线装饰器、OOBE 提示 --ci-radius-card: 4px StylesBase.axaml:257-260;ThemesSettingsPage.axaml:152,161;Themes/Generic.xaml:214
控件圆角 4 按钮/输入框等 --ci-radius-control: 4px ClassHelper index.css:52;theme.css:10
抽屉圆角 8 8 0 0 底部竖抽屉 --ci-radius-drawer: 8px 8px 0 0 VerticalDrawer.axaml:9
胶囊圆角 999 徽标、胶囊按钮 --ci-radius-pill: 999px classic-island.css:308,454,541,694
圆形按钮 14(28×28) 主题卡安装按钮 --ci-radius-icon-btn: 14px ThemesSettingsPage.axaml:246-249
OOBE 大圆钮 24(48×48) 欢迎页「下一步」 --ci-radius-oobe-btn: 24px WelcomePage.axaml:61-65
岛内小元素 0.5 × --ci-island-font / 0.36 × --ci-island-font 岛内图标块 用 calc 派生 classic-island.css:388,403,476,502

实现硬约束:

  • 岛圆角必须四角同值(源码把 RadiusX 同时传给宽高两个方向:FluentTheme/Styles.axaml:31-34 传两次 RadiusX),不得实现「椭圆圆角」。
  • 圆角必须作用于「背景层」与「内容裁剪层」两层,且两层同值,否则内容会溢出圆角外(FluentTheme/Styles.axaml:48,91,124,160-168)。
  • 若引入 ClassHelper 的连续圆角(squircle),必须保持 SUPERELLIPSE_EXPONENT = 4.2、每角 CORNER_SEGMENTS = 14、展开卡半径 min(48*scale, w/2, h/2) 不变(ClassHelper/packages/desktop-client/src/island/squircle.ts:21,24,79-81)。默认实现必须用 CSS border-radius(与 Avalonia CornerRadius 的直角圆弧一致,保证与 ClassIsland 逐像素相同);连续圆角只能由主题包显式启用(P2),不得作为默认岛外形。

3.4 间距 Token

Token 值 用途 建议 CSS 变量 证据
行内容左右内边距 12 0 岛内容区 GridContentRoot.Margin --ci-island-pad-x: 12px FluentTheme/Styles.axaml:110;ClassicTheme/Styles.axaml:100
行内容最小宽度 20 MinWidth --ci-island-min-w: 20px FluentTheme/Styles.axaml:109
组件间距 6 0 每个 ComponentPresenter.Margin;token 值取相邻间距 12px(每个组件左右各 6px),供 calc(var(--ci-component-gap) / 2) 反推单侧 margin --ci-component-gap: 12px MainWindow.axaml:396,546;与 part 04 §4.4 对齐
行间距 5 多行堆叠 StackPanel.Spacing(用户设置) --ci-line-gap: 5px Settings.cs:219;MainWindow.axaml:344
设置页容器 margin 12 12 18 12;max-width 960;spacing 4 设置页正文 --ci-settings-pad / --ci-settings-max-w: 960px StylesBase.axaml:67-71;ThemeBase.axaml:37
组件设置容器 margin 4 0 4 12;max-width 960;spacing 4 子组件设置 --ci-component-settings-pad StylesBase.axaml:73-77
弹窗内边距 12 .popup-bg --ci-popup-pad: 12px StylesBase.axaml:294
主题卡网格 单元高 150;目标宽 328;单元 margin 2;卡内 padding 8 主题市场网格 --ci-theme-card-h: 150px、--ci-theme-card-w: 328px ThemesSettingsPage.axaml:139-142,172
编辑模式操作条 底距 64;padding 4;按钮间距 6 编辑态底部工具条 --ci-editbar-bottom: 64px MainWindow.axaml:595-604
闪屏 尺寸 400×100;padding 17;logo 高 24;行距 8;底部进度条高 4 启动闪屏 --ci-splash-w: 400px、--ci-splash-h: 100px SplashWindow.axaml:16-17,24,29,42,92-96
岛内水平内边距(ClassHelper 风格) 0.78 × 字号 岛胶囊左右内边距 calc 派生 classic-island.css:215
进度条高度 3px 岛内倒计时/提醒进度条统一高度 --ci-progress-height: 3px 与 part 04 §4.4 对齐;源码进度条未显式设高(FluentTheme/Styles.axaml:126-146),取 FluentAvalonia ProgressBar 默认值【推断】
岛内元素间距(ClassHelper) 0.62 × 字号 岛内行间距 calc 派生 classic-island.css:212

3.5 透明与模糊 Token

Token 值 用途 建议实现 证据
主窗口透明级别 Transparent 非编辑态的岛窗口必须逐像素透明 Electron transparent: true + backgroundColor: '#00000000' MainWindow.axaml:168-176
编辑模式透明级别 AcrylicBlur, Transparent(回退 Transparent) 编辑态窗口使用亚克力 只能用 CSS backdrop-filter 在自绘层模拟,不得用 setBackgroundMaterial(会破坏逐像素透明) MainWindow.axaml:177-181;ClassHelper island.ts:1726-1734 明确禁止
普通窗口模式 若禁用透明则 TransparencyLevelHint=None 窗口模式 transparent:false MainWindow.axaml:187-190
闪屏透明 AcrylicBlur, Transparent 启动闪屏 backdrop-filter: blur(...) + 半透明底 SplashWindow.axaml:21
岛背景不透明度 0.5(默认范围 0–1,步进 0.05,滑块带数值气泡) 背景层 opacity --ci-island-opacity(主名;兼容别名 --ci-island-bg-opacity) Settings.cs:64,1141;AppearanceSettingsPage.axaml:61-72;FluentTheme/Styles.axaml:44
行整体不透明度 1.0(行级设置,可被单行覆盖) 行级 opacity --ci-line-opacity MainWindowLineSettings.cs:42
鼠标移出淡化 0.05 悬停淡出模式 opacity:.05 MainWindowLine.axaml:73-75
提醒特效渲染缩放 1.0;屏高 ≥1400 → 0.75;≥2000 → 0.5(自动时) 强提醒涟漪窗口缩放 --ci-effect-scale Settings.cs:150;MainWindow.axaml.cs:377-392
遮罩动画层级不透明度 0 → 1(0.1s) 遮罩出现时附加投影 box-shadow transition FluentTheme/Styles.axaml:355-367

硬规则:

  • 不得给岛卡片加 backdrop-filter(会把整块矩形模糊掉);模糊只允许出现在「编辑模式窗口背景」与「闪屏底」这两个整窗层。
  • 岛必须是「透明窗口 + 自绘圆角卡片」,卡片外区域完全透明、可点击穿透(与 ClassHelper 一致,见 island.ts:250-257)。

3.6 层级(z-index)Token

层 数值 用途 建议 CSS 变量 证据
窗口层级-底层 WindowLayer=0 岛沉到桌面层(Bottommost),仅提醒/编辑时置顶 --ci-z-window:0 Settings.cs:52;MainWindow.axaml.cs:843-874
窗口层级-置顶 WindowLayer=1(默认) 岛始终置顶 --ci-z-window-top:1 同上;默认值 Settings.cs:52
岛内容层 0 正常内容 — —
遮罩/覆盖层 1 内容之上、背景之下 --ci-z-mask:1 FluentTheme/Styles.axaml:155-197
拖拽占位 1(且 opacity .5) 编辑态拖动项 --ci-z-drag:1 MainWindow.axaml:478-481
时间线装饰器 9999 分割线/行动装饰器必须压住时间块 --ci-z-timeline-adorn:9999 Themes/Generic.xaml:193,243
「无穷大」哨兵 33550336 必须永远最前的元素(OOBE 方块、时间线提示、拖拽阈值) --ci-z-sentinel:33550336 OobeIntroAnimationControl.axaml:45;TimeLineListControl.axaml:309;MainWindow.axaml:334
提醒特效窗口 独立 Topmost 窗口 全屏涟漪,高于一切 独立 BrowserWindow alwaysOnTop Views/TopmostEffectWindow.axaml.cs:120-128
教程聚光灯 独立置顶窗口 遮罩挖洞 独立窗口 Controls/Tutorial/TutorialSpotlightControl.axaml:41
抽屉遮罩 覆盖内容 横/竖抽屉 --ci-z-drawer:10【推断】 DrawerHost.axaml、VerticalDrawer.axaml
应用外壳引导层 10000 全屏引导 --ch-z-guide:10000 ClassHelper/packages/ui/src/theme.css:155
主题切换快照层 旧 1 / 新 2 View Transition 两帧 --ch-z-view-old/new ClassHelper/renderer/styles/index.css:948-954

实现必须满足:

  • 岛内容、遮罩、覆盖层在同一「行」内按上表叠放;多行之间不重叠(MainWindowLine 的 ClipToBounds=False,行本身不裁剪)。
  • 33550336 是源码里反复使用的「无穷大」哨兵(同时被用作拖拽阈值 HorizontalDragThreshold="33550336" 表达「禁止横向拖动」,见 MainWindow.axaml:334)。实现时可直接用 z-index: 2147483647 代替,但必须在常量注释里保留原值语义。
  • 编辑器/设置中心内任何弹窗、Tooltip 都必须高于主内容;不得用负 z-index 实现遮罩。

3.7 DPI 与缩放规则

规则 数值/算法 证据
界面缩放用户设置 Scale,默认 1.0,UI 范围 0.75–2.5,步进 0.05(滑块带数值气泡,格式 F2) Settings.cs:86,1153;Views/SettingPages/AppearanceSettingsPage.axaml:27-39
缩放实现 用 LayoutTransform(布局缩放)+ ScaleTransform,同时作用于所有行;不得用 transform: scale() 直接缩放窗口内容(会模糊) MainWindow.axaml:250-265
编码缩放补偿 GridRootLeft = Width/10*(Scale-1)、GridRootTop = Height/10*(Scale-1) MainWindow.axaml.cs:881-882,938-939
编辑模式缩放边界 MinZoom 0.5 / MaxZoom 3 / ZoomSpeed 1.2,EnableConstrains=True,显示缩放指示 MainWindow.axaml:199-209
窗口尺寸换算 逻辑宽 = 物理宽 / dpiX;逻辑高 = (物理高 − 1) / dpiY(−1 防被误判全屏) MainWindow.axaml.cs:969-971
窗口定位 使用物理像素 PixelPoint,不做 dpi 换算 MainWindow.axaml.cs:905-909
安全区(主题声明) 竖直安全区 = 当前启用主题 VerticalSafeAreaPx 的最大值;Fluent 主题为 20 Services/XamlThemeService.cs:111-135;App.Services.xaml.cs:314
教程运行时的安全区 主题安全区与 150 取大者 MainWindow.axaml.cs:898-902
通知特效窗口缩放 1 / dpiX MainWindow.axaml.cs:929
鼠标命中判定 屏幕坐标与 Bounds * dpi * Scale 比较 Controls/MainWindowLine.cs:625-636
字体缩放(关怀模式,应用外壳) --ch-font-scale: 1;关怀模式 1.15,只放大字号不动几何 ClassHelper/renderer/styles/index.css:103,973-979
岛内字号缩放(ClassHelper 模型) 所有岛内尺寸由 --island-font 用 calc() 派生 classic-island.css:2-7,57

实现要求:

  • 所有视觉常量必须定义在 96 DPI 的 CSS px 基准上,再由 --ci-scale 统一放大;不得为不同 DPI 写两套值。
  • 多显示器:每行/每窗口使用「所在显示器」的 DPI 与工作区;切换显示器必须重新计算窗口尺寸与位置(GetSelectedScreenSafe,MainWindow.axaml.cs:806-812)。
  • Scale 改变时必须重算窗口宽高与安全区,不能只改 CSS transform。

3.8 深浅色规则

规则 要求 证据
主题模式枚举 0=跟随系统、1=明亮、2=黑暗;默认 2(黑暗) Settings.cs:32,979-989;Services/ThemeService.cs:53-59
跟随系统实现 themeVariant=Default + preferSystemTheme=true;系统切换要实时响应 ThemeService.cs:53-63
资源覆盖机制 Light/Dark 两套 ThemeDictionary,同名 key 覆盖:RainyColorBrush、LuminousClass、6 个 AQI、CustomizedAccentBarBackground1Brush、TextFillColorInformativeSecondaryBrush App.axaml:35-38;Themes/LightTheme.axaml、Themes/DarkTheme.axaml
自定义前景色优先级 用户自定义前景色 > 主题前景色;关闭时回落主题 ControlColorHelper.cs:20-52
自定义背景色优先级 用户自定义背景色 > 主题背景;关闭时回落 SolidBackgroundFillColor* FluentTheme/Styles.axaml:51-56;ClassicTheme/Styles.axaml:216-218
深色下的阴影 阴影颜色不变(黑),只调不透明度;不得在深色下把投影改成白色 Fluent #48000000/#66000000/#33000000 与 VerticalDrawer.axaml:47 注释「Even in WinUI, shadow is always black regardless of light/dark mode」
ClassHelper 深色底色 应用壳亮 #F3F3F3/暗 #161719;卡片 rgba(255,255,255,.7) / rgba(32,33,36,.72) renderer/styles/index.css:27-48,114-137
主题切换过渡 窗口 Background 用 200ms 过渡;整页换肤用圆形扩散 View Transition(320×1.5=480ms) MainWindow.axaml:40-44;ClassHelper/renderer/composables/motion.ts:226-235

实现禁止项:

  • 禁止在组件里写死 #fff/#000;必须走 --ci-text-*。
  • 禁止只做深色、不做亮色(两套必须同步验收)。
  • 禁止在深色模式使用纯黑 #000000 作为岛背景(默认自定义背景色是黑,但必须靠 --ci-island-bg-opacity 降为 50% 并叠加主题描边,否则与桌面融为一体)。

3.9 ClassHelper 侧落点(实现映射表)

内容 落点文件 要求
应用外壳 token packages/ui/src/tokens.css 保留 --ch-ui-*,新增 --ci-* 只读引用
应用外壳主题 packages/ui/src/theme.css 把 --ci-accent 注入 --el-color-primary 系列,color-mix 派生
桌面端全局样式 packages/desktop-client/src/renderer/styles/index.css 在 :root 与 html.dark 中定义 --ci-* 的亮/暗值
岛渲染进程样式 src/island/classic-island.css、custom-island.css 定义 --island-* 与 --wn-*(classic-island.css:60-82)
动效常量 packages/shared/src/motion.ts + 桌面端/管理端 composables/motion.ts 新增 token 只加在 shared;不得两端各抄一份(motion.ts:14-16 明确约束)
设计常量的 TS 形态 packages/shared/src/constants.ts 输出 CLASSISLAND_TOKENS 常量对象,供窗口几何计算复用

3.10 落地顺序与常见错误

实现顺序必须严格如下,不得跳步:

  1. 先在 packages/shared/src/constants.ts 建立常量对象(颜色、字号、圆角、间距、层级、DPI 基准),字段名与本节 token 名一一对应,导出为只读(as const)。
  2. 在 packages/ui/src/tokens.css 的 :root 写入亮色值,在 html.dark 写入深色值;两处必须保持键集合完全一致,缺一个键都算不合格。
  3. 在 packages/desktop-client/src/renderer/styles/index.css 引入 --ci-* 的桌面端覆盖(通知特效窗口、闪屏窗口等独立渲染入口要单独引入同一份 token)。
  4. 在 src/island/classic-island.css 与 custom-island.css 里把 --island-* 映射到 --ci-*,禁止在岛样式里重新定义颜色字面量。
  5. 最后才写组件;组件只允许消费 token。

常见错误(必须在实现时主动规避):

  • 把「行级字号覆盖」写成给整个岛设置字号:这样改一行会连带改所有行,与源码作用域不符(源码把资源写在行控件自身,见 MainWindowCustomizableNodeHelper.cs:20-26)。
  • 把 5 级前景色实现成「同一颜色的不同 opacity 属性」:opacity 会连带影响子元素与阴影,源码用的是颜色 alpha 通道(ControlColorHelper.cs:24-33),必须写进颜色值本身。
  • 用 filter: drop-shadow() 代替 box-shadow 实现岛投影:filter 会新建渲染表面,开合时出现闪帧(ClassHelper classic-island.css:114-120 已记录该问题)。
  • 在深色主题下把阴影改成 rgba(0,0,0,.6) 以外的颜色,或直接删除阴影:源码在两种主题下都用黑色阴影,只改透明度。
  • 忘记「安全区」:Fluent 主题声明了 20px 竖直安全区,岛贴边时会空出这段距离(App.Services.xaml.cs:314、XamlThemeService.cs:111-135),漏实现会导致岛压住任务栏或屏幕边缘。
  • 忘记 Scale 变化时重算窗口:只改 CSS 会导致点击热区与可见区域错位(源码在 MainWindow.axaml.cs:876-931 每次都重算 Bounds 与 ActualClientBound)。
  • 把「编辑模式操作条」的层级设在岛内容之下:它必须浮在行内容之上,且底距 64px(MainWindow.axaml:595)。

3.11 验收标准

实现者必须逐条自查,全部通过才算完成本节:

  1. 颜色:全仓库(渲染进程 + 主进程 + shared)搜索,除 token 定义文件外不得出现 # 开头的颜色字面量;grep -r "#[0-9a-fA-F]\{6\}" 的命中只允许出现在 token 文件与主题包预览样式中。
  2. 强调色:修改 --ci-accent 一处,岛背景描边、提醒遮罩、进度条、按钮强调态、天气图标强调色全部同步变化,无残留默认蓝。
  3. 5 级前景:开启自定义前景色后,5 个 alpha 分别为 100%/85.5%/77.3%/52.9%/36.5%;关闭后 5 个变量被移除并回落。
  4. 字号:把 4 档字号分别改成 10/20/30/40,岛内所有文字按对应档位变化且不溢出 40px 行高外的容器;行级覆盖可只影响单行。
  5. 圆角:把 --ci-radius-island 从 8 改到 20,背景层与裁剪层同时变化,内容不溢出四角;其他卡片圆角不受影响。
  6. 间距:改 --ci-island-pad-x 与 --ci-component-gap,内容宽度变化后背景宽度动画仍正常(见 part 14)。
  7. 透明:非编辑态岛卡片外区域 100% 透明(用取色器/截图验证 alpha=0);编辑态出现亚克力底;全程不允许整窗材质导致卡片外出现色块。
  8. 层级:编辑态拖动项浮在其他项之上;提醒遮罩覆盖内容但低于右上角操作按钮(若有);33550336 哨兵元素永远最前。
  9. DPI:在 100%/125%/150%/200% 四档缩放下,岛高度逻辑值恒为 40、圆角逻辑值恒为 8、文字不模糊;跨显示器拖动后重新计算,无半个像素的缝。
  10. 深浅色:Light/Dark 各截图对照,两类主题的 AQI 色、雨天色、说明文字 alpha 与上表一致;深色下阴影仍为黑色。
  11. CSS 变量唯一来源:--ci-* 只在两处定义(:root 与 html.dark),组件内只引用不重定义(行级作用域覆盖除外)。
  12. 字符集:所有 token 名使用 kebab-case,前缀统一为 ci-;禁止出现 --ci-primaryColor 这类混合命名。