多品牌、暗色与体验 Profile
五个独立维度
// Visual axes are independent of product authorization and data contracts.type ColorMode = "light" | "dark" | "system";type BrandTheme = | "enterprise-neutral" | "legal-navy" | "legal-amber" | "legal-burgundy" | "legal-jade" | "legal-orange";type Density = "dense" | "compact" | "comfortable" | "spacious";type ShellPreset = "side" | "top"; // 冻结实现:minimal/responsive 为纸面设计// Workspace behavior is selected by the product profile, not by each page.type WorkspaceMode = "single-route" | "managed-tabs";| 轴 | 能改变 | 不能改变 |
|---|---|---|
| Mode | 表面、文字、边界、阴影和色阶映射 | 品牌身份、权限、结构 |
| Brand | 品牌色阶、辅助强调、受控导航色温 | 状态语义、业务流程、菜单能力 |
| Density | 控件高度、表格行高、字段间距 | Reference spacing、字体家族、页面内容 |
| Shell | 全局区域和导航方向 | Theme、SDK、权限 |
| Workspace | 资源打开、切换、关闭和恢复方式 | URL 身份、后端授权 |
不要用 CSS 声明顺序组合 Brand 与 Dark。Brand 只提供 Reference Alias,Mode 再将其映射到 System Role。
前三项是 ADR 0801 定义的正交视觉轴;后两项属于 Experience Pattern。Profile 只是为一个 产品场景组合默认值,不是第六个视觉轴,也不携带权限或业务含义。
默认 Profile
| 启动输入 | Shell | Workspace | Density |
|---|---|---|---|
| 默认(无环境变量) | Side | Managed Tabs | dense |
VITE_SHELL_PRESET=top | Top | Single Route | 用户/租户偏好 |
| 登录模板路由 | 固定 | Single Route | 密度由模板固定 |
Legal 桌面默认品牌 legal-navy。工作台默认密度是 dense;Compact 及更宽松档位是用户显式选择,不是身份隐含值。
- Legal 桌面默认
platform-workbench + legal-navy。 - Dense 是大型表格、复杂筛选和批量操作的桌面高密档,不用于公开 Identity 或触摸环境。
- 香槟金(legal-amber)与 Warning 色相相近但语义独立,不得混用。
- Identity 不显示业务侧栏或 Workspace Tabs。
- 同一产品区域不能逐页混用 Side 与 Top。
选择与持久化
推荐解析优先级:
产品允许范围 -> 租户显式 Brand/Profile -> 用户 Mode/Density 偏好 -> 系统明暗偏好 -> enterprise-neutral fallback- 用户可持久化
Mode、Density、侧栏折叠和受允许的 Theme 偏好。 - 租户选择只能从服务器返回的白名单中解析,不能让客户端注入任意 CSS。
- localStorage 只保存展示偏好,绝不保存 TenantId、UserId、Role、Permission 或 refresh token。
- 首屏脚本在 React 挂载前解析 Mode、Brand、Density 与系统明暗,避免主题闪烁;运行时由
AppearanceProvider统一同步外观三轴,AccessibilityProvider统一同步无障碍轴。
无障碍覆写
外观三轴(Brand/ColorMode/Density)之外,系统另有七条无障碍覆写轴,由 AccessibilityProvider 写入 data-* 属性驱动 CSS 级联;每条轴独立持久化于 bitz.accessibility.*:
| 轴 | data 属性 | 取值 | 作用 |
|---|---|---|---|
| 字号缩放 | data-font-scale | 100 / 115 / 130 / 150 | 按比例放大 --sys-type-* 与控件字号行高,150% 面向弱视场景 |
| 高对比度 | data-contrast | high | 文字、边界、焦点环和状态色切到 mediaScrim / textStrong 极端映射 |
| 色觉模拟 | data-color-vision | protanopia / deuteranopia / tritanopia | 状态色(danger/success/warning/info)切换为色觉友好配色,避免红绿二元编码 |
| 减弱动效 | data-reduce-motion | auto / on / off | 结构动效降为 instant,保留状态变化但不产生位移 |
| 光标辅助 | data-cursor-assist | standard / large / highlight | 大光标或高亮跟随,提升指针可见性 |
| 读屏优化 | data-screen-reader | auto / optimized | 为读屏用户隐藏装饰动效与冗余公告 |
| 页内大纲 | data-page-outline | auto / left / right / off | 顶部条随滚动出现或以幽灵侧标尺呈现当前区 |
无障碍轴不影响品牌身份、页面结构或权限。高对比度与色觉覆写都基于 Reference 层重新映射 System 角色,不引入裸颜色。字号缩放与减弱动效尊重 prefers-reduced-motion 和系统辅助设置,但允许用户在偏好中显式覆盖。
外观三轴的本地持久化键则是 bitz.appearance.brand / bitz.appearance.color-mode / bitz.appearance.density——与无障碍的 bitz.accessibility.* 命名空间相互独立。
当前运行时事实
管理端当前接受六个 Brand、Light/Dark/System、四级 Density 与 Side/Top。首屏脚本只恢复 白名单内的本地缓存,登录后的类型化 Menu 偏好才是跨设备事实源。登录模板路由使用固定的单路由布局与密度;业务页面不能覆盖它。
Single Route 已用于当前管理页面。Managed Tabs 的稳定 URL、脏状态确认、跨登录恢复和失效 资源处理仍是符合性门禁,不应把页面 Local Tabs、浏览器多个标签页或固定视图当成替代实现。
Dark 模式纪律
- 暗色不是浅色的简单反色。
- 中性表面、文字、边界和 Shadow 使用独立 Dark 映射。
- 状态色有独立 Dark FG/BG/Border。
- Brand Light 主动作一般使用 700,Dark 使用 300;
legal-orange是登记例外(Light/Dark 都用 500)。仍须逐主题验证对比。 - 表格密度、壳层区域和字段数量不因 Dark 改变。
