feat(portal-shell): v2.0 P0 shadcn standardization + security + streaming + error handling
- shadcn/ui 标准化:废弃纸感令牌,统一 bg-background/text-foreground 等 - Tailwind v4 + @theme inline,移除 tailwind.config.js - React 19 use() + Suspense 流式渲染,首屏骨架秒出 - 三级错误边界:Route → Section → Widget 层层兜底 - 错误上报:useErrorReport → sendBeacon → /api/log mock 端点 - 三层安全边界:L1 角色门禁 / L2 权限点门禁 / L3 数据范围 - 权限位图 base36 压缩:67 权限点 → ~14 字符,JWT 体积减少 ≥ 99% - notify 统一 Toast 封装,禁止业务直接 import sonner - PluginBoundary 替代 PluginLoader(错误边界 + Suspense + Skeleton 三件套) 验证:typecheck 0 错误 / lint 0 错误 / build 6 路由生成成功
This commit is contained in:
@@ -1,112 +1,116 @@
|
||||
/**
|
||||
* Layer 1: Primitive Tokens(原始色板/字号/间距/阴影)
|
||||
* Layer 1: Primitive Tokens(原始色板/字号/间距/阴影/字体家族)
|
||||
*
|
||||
* 业务代码不直接引用本层令牌,仅 Layer 2 Semantic 引用。
|
||||
* 维护者:ai13(teacher-portal)
|
||||
* 仅被 Layer 2 Semantic 引用,业务代码不直接使用。
|
||||
* 色板层不区分明暗,主题差异在 Semantic 层体现。
|
||||
*
|
||||
* 对齐:CICD 项目 src/app/styles/tokens/primitive.css
|
||||
* 关联:project_rules §3.10 设计令牌规范
|
||||
*
|
||||
* 命名规范:
|
||||
* - 颜色:--color-<hue>-<level>(HSL 分量,供 Layer 2 组合)
|
||||
* - 字号:--font-size-<n>(1-9 阶梯)
|
||||
* - 间距:--space-<n>(4px 基准阶梯)
|
||||
* - 阴影:--shadow-<n>
|
||||
* - 字重:--font-weight-<name>
|
||||
* - 圆角:--radius-<name>
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* ============ 颜色原始色板(HSL 分量,非完整颜色) ============ */
|
||||
/* 中性色(纸张/墨色) */
|
||||
--color-paper-h: 40;
|
||||
--color-paper-s: 20%;
|
||||
--color-paper-l-50: 50%;
|
||||
--color-paper-l-98: 98%;
|
||||
--color-paper-l-99: 99%;
|
||||
/* ============ 色板(HSL 分量,非完整颜色) ============ */
|
||||
|
||||
--color-ink-h: 25;
|
||||
--color-ink-s: 3%;
|
||||
--color-ink-l-15: 15%;
|
||||
--color-ink-l-45: 45%;
|
||||
--color-ink-l-60: 60%;
|
||||
/* Zinc 中性色板(shadcn 默认) */
|
||||
--color-zinc-50: 0 0% 99%;
|
||||
--color-zinc-100: 240 4.8% 95.9%;
|
||||
--color-zinc-200: 240 5.9% 90%;
|
||||
--color-zinc-300: 240 4.8% 83.9%;
|
||||
--color-zinc-400: 240 5% 64.9%;
|
||||
--color-zinc-500: 240 3.8% 46.1%;
|
||||
--color-zinc-600: 240 5.2% 33.9%;
|
||||
--color-zinc-700: 240 5.3% 26.1%;
|
||||
--color-zinc-800: 240 5.9% 10%;
|
||||
--color-zinc-900: 240 5.9% 3.9%;
|
||||
--color-zinc-950: 240 10% 3.9%;
|
||||
|
||||
/* 强调色(深蓝) */
|
||||
--color-accent-h: 220;
|
||||
--color-accent-s: 60%;
|
||||
--color-accent-l-35: 35%;
|
||||
--color-accent-l-50: 50%;
|
||||
/* Stone 暖灰(用于纸感业务扩展,如备课编辑器) */
|
||||
--color-stone-50: 60 4.8% 95.9%;
|
||||
--color-stone-100: 60 5.1% 90%;
|
||||
--color-stone-200: 20 5.9% 90%;
|
||||
--color-stone-300: 24 5.7% 82.9%;
|
||||
--color-stone-400: 24 5.4% 63.9%;
|
||||
--color-stone-500: 25 5.1% 44.7%;
|
||||
--color-stone-600: 33 5% 39.8%;
|
||||
--color-stone-700: 30 5.2% 32.7%;
|
||||
--color-stone-800: 12 6.5% 31.4%;
|
||||
--color-stone-900: 24 10% 10%;
|
||||
--color-stone-950: 20 14.3% 4.1%;
|
||||
|
||||
/* 分隔线(暖灰) */
|
||||
--color-rule-h: 30;
|
||||
--color-rule-s: 10%;
|
||||
--color-rule-l-85: 85%;
|
||||
--color-rule-l-90: 90%;
|
||||
/* Indigo 强调色(业务交互强调) */
|
||||
--color-indigo-500: 238.7 83.5% 66.7%;
|
||||
--color-indigo-600: 238.6 84.5% 59.8%;
|
||||
|
||||
/* 语义原始色 */
|
||||
--color-success-h: 142;
|
||||
--color-success-s: 71%;
|
||||
--color-success-l-45: 45%;
|
||||
/* ============ 字号阶梯(10 级,0 最小 9 最大) ============ */
|
||||
--font-size-0: 9px; /* 角色标签微字号 */
|
||||
--font-size-1: 12px; /* 元信息/角色标签 */
|
||||
--font-size-2: 13px; /* inline-node body */
|
||||
--font-size-3: 13.5px; /* inline-node 主文(纸感) */
|
||||
--font-size-4: 14px; /* 标题/按钮 */
|
||||
--font-size-5: 16px; /* 正文(Fraunces 16px) */
|
||||
--font-size-6: 18px; /* H2 */
|
||||
--font-size-7: 20px; /* H1 */
|
||||
--font-size-8: 24px; /* 区块标题 */
|
||||
--font-size-9: 32px; /* 页面标题 */
|
||||
|
||||
--color-warning-h: 38;
|
||||
--color-warning-s: 92%;
|
||||
--color-warning-l-50: 50%;
|
||||
/* ============ 间距阶梯 ============ */
|
||||
--space-0: 0;
|
||||
--space-0_5: 0.125rem; /* 2px */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-1_5: 0.375rem; /* 6px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-2_5: 0.625rem; /* 10px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-3_5: 0.875rem; /* 14px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-7: 1.75rem; /* 28px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--space-16: 4rem; /* 64px */
|
||||
--space-18: 4.5rem; /* 72px */
|
||||
|
||||
--color-danger-h: 0;
|
||||
--color-danger-s: 84%;
|
||||
--color-danger-l-60: 60%;
|
||||
/* ============ 阴影阶梯 ============ */
|
||||
--shadow-1: 0 1px 2px rgba(15, 15, 15, 0.04);
|
||||
--shadow-2: 0 1px 3px rgba(15, 15, 15, 0.06), 0 1px 2px rgba(15, 15, 15, 0.04);
|
||||
--shadow-3: 0 4px 6px rgba(15, 15, 15, 0.05), 0 2px 4px rgba(15, 15, 15, 0.04);
|
||||
--shadow-4: 0 1px 2px rgba(15, 15, 15, 0.04), 0 8px 24px rgba(15, 15, 15, 0.04);
|
||||
--shadow-5: 0 1px 2px rgba(15, 15, 15, 0.06), 0 12px 36px rgba(15, 15, 15, 0.08);
|
||||
--shadow-6: 0 10px 15px rgba(15, 15, 15, 0.1), 0 4px 6px rgba(15, 15, 15, 0.05);
|
||||
|
||||
--color-info-h: 199;
|
||||
--color-info-s: 89%;
|
||||
--color-info-l-48: 48%;
|
||||
/* ============ 字体家族 ============ */
|
||||
/* 引用 next/font 在 <html> 上注入的 CSS 变量(fallback 保证 SSR/无字体时降级) */
|
||||
--font-family-sans: var(--font-inter, 'Inter'), system-ui, sans-serif;
|
||||
--font-family-serif: var(--font-fraunces, 'Fraunces'), Georgia, serif;
|
||||
--font-family-mono: var(--font-jetbrains-mono, 'JetBrains Mono'), ui-monospace, monospace;
|
||||
|
||||
/* ============ 字号阶梯(1-9,1 最小 9 最大) ============ */
|
||||
--font-size-1: 0.75rem; /* 12px - 辅助说明 */
|
||||
--font-size-2: 0.875rem; /* 14px - 次要正文 */
|
||||
--font-size-3: 1rem; /* 16px - 正文 body */
|
||||
--font-size-4: 1.125rem; /* 18px - 强调正文 */
|
||||
--font-size-5: 1.25rem; /* 20px - 小标题 */
|
||||
--font-size-6: 1.5rem; /* 24px - 区块标题 */
|
||||
--font-size-7: 1.875rem; /* 30px - 页面标题 */
|
||||
--font-size-8: 2.25rem; /* 36px - Hero */
|
||||
--font-size-9: 3rem; /* 48px - 大数字 */
|
||||
/* ============ 行高阶梯 ============ */
|
||||
--leading-tight: 1.2;
|
||||
--leading-snug: 1.35;
|
||||
--leading-normal: 1.5;
|
||||
--leading-relaxed: 1.65;
|
||||
--leading-loose: 1.8;
|
||||
|
||||
/* ============ 间距阶梯(4px 基准) ============ */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--space-16: 4rem; /* 64px */
|
||||
--space-20: 5rem; /* 80px */
|
||||
/* ============ 字重阶梯 ============ */
|
||||
--weight-regular: 400;
|
||||
--weight-medium: 500;
|
||||
--weight-semibold: 600;
|
||||
--weight-bold: 700;
|
||||
|
||||
/* ============ 阴影 ============ */
|
||||
--shadow-1: 0 1px 2px 0 hsl(25 3% 15% / 0.05);
|
||||
--shadow-2: 0 1px 3px 0 hsl(25 3% 15% / 0.1), 0 1px 2px -1px hsl(25 3% 15% / 0.1);
|
||||
--shadow-3: 0 4px 6px -1px hsl(25 3% 15% / 0.1), 0 2px 4px -2px hsl(25 3% 15% / 0.1);
|
||||
--shadow-4: 0 10px 15px -3px hsl(25 3% 15% / 0.1), 0 4px 6px -4px hsl(25 3% 15% / 0.1);
|
||||
/* ============ 动效 ============ */
|
||||
--duration-fast: 150ms;
|
||||
--duration-normal: 200ms;
|
||||
--duration-slow: 300ms;
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
/* ============ 字重 ============ */
|
||||
--font-weight-regular: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
||||
/* ============ 圆角 ============ */
|
||||
--radius-sm: 0.25rem; /* 4px */
|
||||
--radius-md: 0.375rem; /* 6px */
|
||||
--radius-lg: 0.5rem; /* 8px */
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* ============ 行高 ============ */
|
||||
--line-height-tight: 1.25;
|
||||
--line-height-normal: 1.5;
|
||||
--line-height-relaxed: 1.75;
|
||||
|
||||
/* ============ 字间距 ============ */
|
||||
--letter-spacing-tight: -0.01em;
|
||||
--letter-spacing-normal: 0;
|
||||
--letter-spacing-wide: 0.025em;
|
||||
/* ============ z-index ============ */
|
||||
--z-dropdown: 1000;
|
||||
--z-sticky: 1100;
|
||||
--z-modal: 1300;
|
||||
--z-popover: 1400;
|
||||
--z-toast: 1500;
|
||||
}
|
||||
|
||||
@@ -1,66 +1,73 @@
|
||||
/**
|
||||
* Layer 2: Semantic Tokens - Dark Theme(暗色语义令牌)
|
||||
*
|
||||
* 维护者:ai13(teacher-portal)
|
||||
* 关联:project_rules §3.10
|
||||
* 通过 .dark class 激活(由 next-themes 切换)。
|
||||
* 所有令牌都有 :root (light) 对应定义。
|
||||
*
|
||||
* 暗色主题覆盖,通过 [data-theme="dark"] 或 prefers-color-scheme: dark 激活。
|
||||
* 对齐:CICD 项目 src/app/styles/tokens/semantic-dark.css
|
||||
*/
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
color-scheme: dark;
|
||||
|
||||
--bg-paper: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
|
||||
--bg-surface: hsl(var(--color-ink-h) var(--color-ink-s) 20%);
|
||||
--bg-subtle: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
|
||||
|
||||
--color-ink: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
|
||||
--color-ink-muted: hsl(var(--color-paper-h) var(--color-paper-s) 70%);
|
||||
--color-ink-subtle: hsl(var(--color-paper-h) var(--color-paper-s) 60%);
|
||||
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
|
||||
|
||||
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
|
||||
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) 60%);
|
||||
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) 25%);
|
||||
|
||||
--color-rule: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
|
||||
--color-rule-strong: hsl(var(--color-ink-h) var(--color-ink-s) 30%);
|
||||
|
||||
--color-border: var(--color-rule);
|
||||
--color-input-bg: var(--bg-surface);
|
||||
|
||||
--shadow-sm: 0 1px 2px 0 hsl(0 0% 0% / 0.3);
|
||||
--shadow-md: 0 1px 3px 0 hsl(0 0% 0% / 0.4), 0 1px 2px -1px hsl(0 0% 0% / 0.4);
|
||||
--shadow-lg: 0 4px 6px -1px hsl(0 0% 0% / 0.4), 0 2px 4px -2px hsl(0 0% 0% / 0.4);
|
||||
--shadow-xl: 0 10px 15px -3px hsl(0 0% 0% / 0.5), 0 4px 6px -4px hsl(0 0% 0% / 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
.dark {
|
||||
color-scheme: dark;
|
||||
|
||||
--bg-paper: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
|
||||
--bg-surface: hsl(var(--color-ink-h) var(--color-ink-s) 20%);
|
||||
--bg-subtle: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
|
||||
/* ============ shadcn 标准令牌 ============ */
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
--color-ink: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
|
||||
--color-ink-muted: hsl(var(--color-paper-h) var(--color-paper-s) 70%);
|
||||
--color-ink-subtle: hsl(var(--color-paper-h) var(--color-paper-s) 60%);
|
||||
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
|
||||
/* ============ chart 令牌 ============ */
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
|
||||
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
|
||||
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) 60%);
|
||||
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) 25%);
|
||||
/* ============ sidebar 令牌 ============ */
|
||||
--sidebar-background: 240 5.9% 10%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 240 3.7% 15.9%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
|
||||
--color-rule: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
|
||||
--color-rule-strong: hsl(var(--color-ink-h) var(--color-ink-s) 30%);
|
||||
/* ============ 语义层扩展 ============ */
|
||||
--background-elevated: 240 6% 10%;
|
||||
--background-sunken: 240 6% 8%;
|
||||
--text-primary: 0 0% 98%; /* = --foreground */
|
||||
--text-secondary: 240 5% 64.9%; /* = --muted-foreground */
|
||||
--text-tertiary: 240 5% 50%;
|
||||
--border-strong: 240 5% 40%;
|
||||
--border-subtle: 240 5% 18%;
|
||||
|
||||
--color-border: var(--color-rule);
|
||||
--color-input-bg: var(--bg-surface);
|
||||
/* ============ 业务语义令牌 ============ */
|
||||
--diff-add: 142 71% 55%;
|
||||
--diff-add-bg: 142 71% 55% / 0.15;
|
||||
--diff-remove: 0 84% 70%;
|
||||
--diff-remove-bg: 0 84% 70% / 0.15;
|
||||
|
||||
--shadow-sm: 0 1px 2px 0 hsl(0 0% 0% / 0.3);
|
||||
--shadow-md: 0 1px 3px 0 hsl(0 0% 0% / 0.4), 0 1px 2px -1px hsl(0 0% 0% / 0.4);
|
||||
--shadow-lg: 0 4px 6px -1px hsl(0 0% 0% / 0.4), 0 2px 4px -2px hsl(0 0% 0% / 0.4);
|
||||
--shadow-xl: 0 10px 15px -3px hsl(0 0% 0% / 0.5), 0 4px 6px -4px hsl(0 0% 0% / 0.4);
|
||||
--graph-node-1: 220 70% 50%;
|
||||
--graph-node-2: 160 60% 45%;
|
||||
--graph-node-3: 30 80% 55%;
|
||||
--graph-node-4: 280 65% 60%;
|
||||
--graph-node-5: 340 75% 55%;
|
||||
--graph-node-6: 200 80% 60%;
|
||||
}
|
||||
|
||||
@@ -1,82 +1,76 @@
|
||||
/**
|
||||
* Layer 2: Semantic Tokens - Light Theme(亮色语义令牌)
|
||||
*
|
||||
* 业务代码唯一引用入口:业务 TSX/CSS 引用 var(--color-*) / var(--font-*) 等。
|
||||
* 维护者:ai13(teacher-portal)
|
||||
* 关联:project_rules §3.10、03-long-term-architecture.md §1.5
|
||||
* 业务代码唯一引用入口:业务 TSX/CSS 引用 hsl(var(--*)) 或 Tailwind bg-* 类。
|
||||
* 所有令牌都有 .dark 对应定义。
|
||||
*
|
||||
* 引用 Layer 1 Primitive 组合成完整语义值。
|
||||
* 对齐:CICD 项目 src/app/styles/tokens/semantic-light.css
|
||||
* 关联:project_rules §3.10
|
||||
*/
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
|
||||
/* ============ 背景与表面 ============ */
|
||||
--bg-paper: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
|
||||
--bg-surface: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
|
||||
--bg-subtle: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-90));
|
||||
/* ============ shadcn 标准令牌 ============ */
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5.9% 10%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* ============ 文字 ============ */
|
||||
--color-ink: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
|
||||
--color-ink-muted: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-45));
|
||||
--color-ink-subtle: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-60));
|
||||
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
|
||||
/* ============ chart 令牌 ============ */
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
|
||||
/* ============ 强调色 ============ */
|
||||
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-35));
|
||||
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
|
||||
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-rule-l-90));
|
||||
/* ============ sidebar 令牌 ============ */
|
||||
--sidebar-background: 0 0% 98%;
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
--sidebar-border: 220 13% 91%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
|
||||
/* ============ 分隔线 ============ */
|
||||
--color-rule: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-90));
|
||||
--color-rule-strong: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-85));
|
||||
/* ============ 语义层扩展(新增层级) ============ */
|
||||
--background-elevated: 0 0% 100%;
|
||||
--background-sunken: 240 4.8% 95.9%;
|
||||
--text-primary: 240 10% 3.9%; /* = --foreground */
|
||||
--text-secondary: 240 3.8% 46.1%; /* = --muted-foreground */
|
||||
--text-tertiary: 240 4% 65%;
|
||||
--border-strong: 240 5.9% 70%;
|
||||
--border-subtle: 240 5.9% 95%;
|
||||
|
||||
/* ============ 语义色 ============ */
|
||||
--color-success: hsl(var(--color-success-h) var(--color-success-s) var(--color-success-l-45));
|
||||
--color-warning: hsl(var(--color-warning-h) var(--color-warning-s) var(--color-warning-l-50));
|
||||
--color-danger: hsl(var(--color-danger-h) var(--color-danger-s) var(--color-danger-l-60));
|
||||
--color-info: hsl(var(--color-info-h) var(--color-info-s) var(--color-info-l-48));
|
||||
/* ============ 业务语义令牌 ============ */
|
||||
/* 版本对比 */
|
||||
--diff-add: 142 71% 45%;
|
||||
--diff-add-bg: 142 71% 45% / 0.1;
|
||||
--diff-remove: 0 84% 60%;
|
||||
--diff-remove-bg: 0 84% 60% / 0.1;
|
||||
|
||||
/* ============ 边框/输入 ============ */
|
||||
--color-border: var(--color-rule);
|
||||
--color-border-focus: var(--color-accent);
|
||||
--color-input-bg: var(--bg-surface);
|
||||
|
||||
/* ============ 字体族(通过 var 引用,禁止字面量) ============ */
|
||||
--font-family-sans: var(--font-inter, system-ui), -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
--font-family-serif: var(--font-fraunces, Georgia), "Times New Roman", serif;
|
||||
--font-family-mono: var(--font-jetbrains-mono, "SF Mono"), Monaco, Consolas, monospace;
|
||||
|
||||
/* ============ 语义字号 ============ */
|
||||
--font-size-body: var(--font-size-3);
|
||||
--font-size-small: var(--font-size-2);
|
||||
--font-size-tiny: var(--font-size-1);
|
||||
--font-size-heading-1: var(--font-size-7);
|
||||
--font-size-heading-2: var(--font-size-6);
|
||||
--font-size-heading-3: var(--font-size-5);
|
||||
--font-size-display: var(--font-size-9);
|
||||
--font-size-large-number: var(--font-size-8);
|
||||
|
||||
/* ============ 语义间距 ============ */
|
||||
--space-xs: var(--space-1);
|
||||
--space-sm: var(--space-2);
|
||||
--space-md: var(--space-4);
|
||||
--space-lg: var(--space-6);
|
||||
--space-xl: var(--space-8);
|
||||
--space-2xl: var(--space-12);
|
||||
|
||||
/* ============ 语义阴影 ============ */
|
||||
--shadow-sm: var(--shadow-1);
|
||||
--shadow-md: var(--shadow-2);
|
||||
--shadow-lg: var(--shadow-3);
|
||||
--shadow-xl: var(--shadow-4);
|
||||
|
||||
/* ============ 语义圆角 ============ */
|
||||
--radius-default: var(--radius-md);
|
||||
--radius-card: var(--radius-lg);
|
||||
--radius-button: var(--radius-md);
|
||||
|
||||
/* ============ 过渡 ============ */
|
||||
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
/* 知识图谱节点色 */
|
||||
--graph-node-1: 12 76% 61%; /* = --chart-1 */
|
||||
--graph-node-2: 173 58% 39%; /* = --chart-2 */
|
||||
--graph-node-3: 197 37% 24%; /* = --chart-3 */
|
||||
--graph-node-4: 43 74% 66%; /* = --chart-4 */
|
||||
--graph-node-5: 27 87% 67%; /* = --chart-5 */
|
||||
--graph-node-6: 280 65% 60%;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,129 @@
|
||||
/**
|
||||
* Layer 3: Tailwind Theme Mapping(Tailwind 主题映射)
|
||||
* Layer 3: Tailwind Theme Mapping(Tailwind v4 @theme inline)
|
||||
*
|
||||
* 将 Layer 2 Semantic 令牌映射为 Tailwind 类名(bg-* / text-* / font-* 等)。
|
||||
* 维护者:ai13(teacher-portal)
|
||||
* 关联:project_rules §3.10、03-long-term-architecture.md §1.5
|
||||
* 将 Layer 2 Semantic 令牌暴露为 Tailwind 类(bg-background / text-foreground / ...)。
|
||||
* 业务代码使用 bg-background / text-foreground / font-sans 等。
|
||||
*
|
||||
* Tailwind 3.4 通过 tailwind.config.js 的 theme.extend 映射;
|
||||
* Tailwind 4 将改用 @theme inline 指令(未来升级时本文件可转为 @theme 块)。
|
||||
*
|
||||
* 使用方式(业务组件):
|
||||
* <div className="bg-paper text-ink font-serif">...</div>
|
||||
* <p className="text-sm text-ink-muted">...</p>
|
||||
*
|
||||
* 对应 tailwind.config.js 中:
|
||||
* colors: { paper: 'var(--bg-paper)', ink: 'var(--color-ink)', ... }
|
||||
* fontFamily: { sans: 'var(--font-family-sans)', serif: 'var(--font-family-serif)', ... }
|
||||
* 对齐:CICD 项目 src/app/styles/tokens/tailwind-theme.css
|
||||
* 关联:project_rules §3.10
|
||||
*/
|
||||
|
||||
/* 显式引用语义令牌,确保 CSS 变量在构建产物中可用 */
|
||||
:root {
|
||||
/* Tailwind 颜色类映射(与 tailwind.config.js theme.extend.colors 对齐) */
|
||||
--tw-color-paper: var(--bg-paper);
|
||||
--tw-color-surface: var(--bg-surface);
|
||||
--tw-color-ink: var(--color-ink);
|
||||
--tw-color-ink-muted: var(--color-ink-muted);
|
||||
--tw-color-accent: var(--color-accent);
|
||||
--tw-color-rule: var(--color-rule);
|
||||
@theme inline {
|
||||
/* ============ shadcn 标准颜色 ============ */
|
||||
--color-background: hsl(var(--background));
|
||||
--color-foreground: hsl(var(--foreground));
|
||||
--color-card: hsl(var(--card));
|
||||
--color-card-foreground: hsl(var(--card-foreground));
|
||||
--color-popover: hsl(var(--popover));
|
||||
--color-popover-foreground: hsl(var(--popover-foreground));
|
||||
--color-primary: hsl(var(--primary));
|
||||
--color-primary-foreground: hsl(var(--primary-foreground));
|
||||
--color-secondary: hsl(var(--secondary));
|
||||
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
||||
--color-muted: hsl(var(--muted));
|
||||
--color-muted-foreground: hsl(var(--muted-foreground));
|
||||
--color-accent: hsl(var(--accent));
|
||||
--color-accent-foreground: hsl(var(--accent-foreground));
|
||||
--color-destructive: hsl(var(--destructive));
|
||||
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
||||
--color-border: hsl(var(--border));
|
||||
--color-input: hsl(var(--input));
|
||||
--color-ring: hsl(var(--ring));
|
||||
|
||||
/* ============ chart 颜色 ============ */
|
||||
--color-chart-1: hsl(var(--chart-1));
|
||||
--color-chart-2: hsl(var(--chart-2));
|
||||
--color-chart-3: hsl(var(--chart-3));
|
||||
--color-chart-4: hsl(var(--chart-4));
|
||||
--color-chart-5: hsl(var(--chart-5));
|
||||
|
||||
/* ============ sidebar 颜色 ============ */
|
||||
--color-sidebar: hsl(var(--sidebar-background));
|
||||
--color-sidebar-foreground: hsl(var(--sidebar-foreground));
|
||||
--color-sidebar-primary: hsl(var(--sidebar-primary));
|
||||
--color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
|
||||
--color-sidebar-accent: hsl(var(--sidebar-accent));
|
||||
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
|
||||
--color-sidebar-border: hsl(var(--sidebar-border));
|
||||
--color-sidebar-ring: hsl(var(--sidebar-ring));
|
||||
|
||||
/* ============ 扩展语义颜色 ============ */
|
||||
--color-background-elevated: hsl(var(--background-elevated));
|
||||
--color-background-sunken: hsl(var(--background-sunken));
|
||||
--color-text-primary: hsl(var(--text-primary));
|
||||
--color-text-secondary: hsl(var(--text-secondary));
|
||||
--color-text-tertiary: hsl(var(--text-tertiary));
|
||||
--color-border-strong: hsl(var(--border-strong));
|
||||
--color-border-subtle: hsl(var(--border-subtle));
|
||||
--color-diff-add: hsl(var(--diff-add));
|
||||
--color-diff-add-bg: hsl(var(--diff-add-bg));
|
||||
--color-diff-remove: hsl(var(--diff-remove));
|
||||
--color-diff-remove-bg: hsl(var(--diff-remove-bg));
|
||||
--color-graph-node-1: hsl(var(--graph-node-1));
|
||||
--color-graph-node-2: hsl(var(--graph-node-2));
|
||||
--color-graph-node-3: hsl(var(--graph-node-3));
|
||||
--color-graph-node-4: hsl(var(--graph-node-4));
|
||||
--color-graph-node-5: hsl(var(--graph-node-5));
|
||||
--color-graph-node-6: hsl(var(--graph-node-6));
|
||||
|
||||
/* ============ 字体家族 ============ */
|
||||
--font-sans: var(--font-family-sans);
|
||||
--font-serif: var(--font-family-serif);
|
||||
--font-mono: var(--font-family-mono);
|
||||
|
||||
/* ============ 字号阶梯 ============ */
|
||||
--text-size-0: var(--font-size-0);
|
||||
--text-size-1: var(--font-size-1);
|
||||
--text-size-2: var(--font-size-2);
|
||||
--text-size-3: var(--font-size-3);
|
||||
--text-size-4: var(--font-size-4);
|
||||
--text-size-5: var(--font-size-5);
|
||||
--text-size-6: var(--font-size-6);
|
||||
--text-size-7: var(--font-size-7);
|
||||
--text-size-8: var(--font-size-8);
|
||||
--text-size-9: var(--font-size-9);
|
||||
|
||||
/* ============ 圆角阶梯 ============ */
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--radius-2xl: calc(var(--radius) + 8px);
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* ============ 阴影阶梯 ============ */
|
||||
--shadow-1: var(--shadow-1);
|
||||
--shadow-2: var(--shadow-2);
|
||||
--shadow-3: var(--shadow-3);
|
||||
--shadow-4: var(--shadow-4);
|
||||
--shadow-5: var(--shadow-5);
|
||||
--shadow-6: var(--shadow-6);
|
||||
|
||||
/* ============ 动效 ============ */
|
||||
--duration-fast: var(--duration-fast);
|
||||
--duration-normal: var(--duration-normal);
|
||||
--duration-slow: var(--duration-slow);
|
||||
--ease-in: var(--ease-in);
|
||||
--ease-out: var(--ease-out);
|
||||
--ease-in-out: var(--ease-in-out);
|
||||
|
||||
/* ============ z-index ============ */
|
||||
--z-dropdown: var(--z-dropdown);
|
||||
--z-sticky: var(--z-sticky);
|
||||
--z-modal: var(--z-modal);
|
||||
--z-popover: var(--z-popover);
|
||||
--z-toast: var(--z-toast);
|
||||
|
||||
/* ============ 动画 ============ */
|
||||
--animate-accordion-down: accordion-down 0.2s ease-out;
|
||||
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||
|
||||
@keyframes accordion-down {
|
||||
from { height: 0; }
|
||||
to { height: var(--radix-accordion-content-height); }
|
||||
}
|
||||
@keyframes accordion-up {
|
||||
from { height: var(--radix-accordion-content-height); }
|
||||
to { height: 0; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user