From 7bdf3f3bc18e300b18ddaf5059c0d14b3fa7521d Mon Sep 17 00:00:00 2001 From: Mohan Date: Wed, 12 Aug 2026 15:28:48 +0800 Subject: [PATCH] feat(type): add song semantic color tokens --- src/styles/base.css | 82 +++++++++++++++++++++++++++++++++++++ src/styles/tokens/dark.css | 37 +++++++++++++++++ src/styles/tokens/light.css | 71 ++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 src/styles/base.css create mode 100644 src/styles/tokens/dark.css create mode 100644 src/styles/tokens/light.css diff --git a/src/styles/base.css b/src/styles/base.css new file mode 100644 index 0000000..b8e6d3d --- /dev/null +++ b/src/styles/base.css @@ -0,0 +1,82 @@ +/* SongUI · 檐下 — 基础样式 */ +@import './tokens/light.css'; +@import './tokens/dark.css'; + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; +} + +body { + background: var(--song-bg); + color: var(--song-text); + font-family: var(--song-font-body); + font-size: 14px; + line-height: 22px; + -webkit-font-smoothing: antialiased; + transition: background-color 320ms var(--song-ease), color 320ms var(--song-ease); +} + +/* 字阶 §3.2 */ +.display { font-family: var(--song-font-display); font-size: 36px; line-height: 48px; } +.h1 { font-family: var(--song-font-display); font-size: 28px; line-height: 38px; } +.h2 { font-family: var(--song-font-serif); font-size: 22px; line-height: 30px; font-weight: 600; letter-spacing: 0.02em; } +.h3 { font-family: var(--song-font-serif); font-size: 18px; line-height: 26px; font-weight: 600; } +.caption { font-size: 12px; line-height: 18px; color: var(--song-text-secondary); } + +a { + color: var(--song-primary); + text-decoration: none; +} +a:hover { + text-decoration: underline; +} + +/* 焦点态 §9 — 主色 2px 轮廓 */ +:focus-visible { + outline: 2px solid var(--song-primary); + outline-offset: 2px; + border-radius: 2px; +} + +/* 纹样底纹基底(SVG 通过 mask 合成,置于内容之下) */ +.song-scrim { + position: fixed; + inset: 0; + z-index: -1; + pointer-events: none; +} + +/* 数字等宽 */ +.tnum { + font-variant-numeric: tabular-nums; +} + +/* 动效可关 §7 */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +/* 页面转场 — 雾隐淡入 §7 */ +.page-enter-active, +.page-leave-active { + transition: opacity 320ms var(--song-ease), transform 320ms var(--song-ease); +} +.page-enter-from, +.page-leave-to { + opacity: 0; + transform: translateY(8px); +} \ No newline at end of file diff --git a/src/styles/tokens/dark.css b/src/styles/tokens/dark.css new file mode 100644 index 0000000..2bbf11b --- /dev/null +++ b/src/styles/tokens/dark.css @@ -0,0 +1,37 @@ +/* SongUI · Dark (黛墨夜) — 设计契约 §2.2 */ +:root[data-theme='dark'] { + color-scheme: dark; + + --song-bg: #14181b; + --song-bg-elevated: #1d2326; + --song-surface-3: #232b2f; + + --song-text: #e6ecef; + --song-text-secondary: #a9b6be; + --song-text-disabled: #5e6a71; + + --song-primary: #9dbeee; + --song-primary-bg: rgba(113, 150, 203, 0.16); + --song-success: #94b989; + --song-success-bg: rgba(148, 185, 137, 0.14); + --song-warning: #d3bc6a; + --song-warning-bg: rgba(211, 188, 106, 0.14); + --song-danger: #d08a79; + --song-danger-bg: rgba(208, 138, 121, 0.14); + + --song-border: rgba(230, 236, 239, 0.12); + --song-border-strong: rgba(230, 236, 239, 0.26); + --song-hover: rgba(157, 190, 238, 0.1); + --song-active: rgba(157, 190, 238, 0.16); + + /* 实底按钮填充(暗色下压深同色相,白字 ≥ 4.6:1) */ + --song-btn-bg: #48689e; + --song-btn-text: #fff; + + /* 章印(印泥砂红,暗色下微提亮) */ + --song-seal: #c76a4f; + + --song-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3); + --song-shadow-2: 0 2px 8px rgba(0, 0, 0, 0.35); + --song-shadow-3: 0 8px 24px rgba(0, 0, 0, 0.45); +} \ No newline at end of file diff --git a/src/styles/tokens/light.css b/src/styles/tokens/light.css new file mode 100644 index 0000000..b7273d7 --- /dev/null +++ b/src/styles/tokens/light.css @@ -0,0 +1,71 @@ +/* SongUI · Light (天青昼) — 设计契约 §2.2 */ +:root, +:root[data-theme='light'] { + color-scheme: light; + + /* 底色 */ + --song-bg: #f7f4ec; + --song-bg-elevated: #fffdf8; + --song-surface-3: #ece6d8; + + /* 文字(墨色分层) */ + --song-text: #3a4a52; + --song-text-secondary: #5a6b74; + --song-text-disabled: #9aa7ad; + + /* 语义色 */ + --song-primary: #4f78b8; + --song-primary-bg: #e7eef9; + --song-success: #4e7a45; + --song-success-bg: #e9f0e4; + --song-warning: #8f7a1e; + --song-warning-bg: #f6f1df; + --song-danger: #a84635; + --song-danger-bg: #f6e9e2; + + /* 中性/线条(1px 墨线系统 §4.4) */ + --song-border: rgba(58, 74, 82, 0.14); + --song-border-strong: rgba(58, 74, 82, 0.28); + --song-hover: rgba(79, 120, 184, 0.08); + --song-active: rgba(79, 120, 184, 0.14); + + /* 实底按钮填充(保证文字对比度) */ + --song-btn-bg: #4f78b8; + --song-btn-text: #fff; + + /* 章印(印泥砂红) */ + --song-seal: #a84635; + + /* 阴影 §6 */ + --song-shadow-1: 0 1px 2px rgba(20, 24, 27, 0.06); + --song-shadow-2: 0 2px 8px rgba(20, 24, 27, 0.08); + --song-shadow-3: 0 8px 24px rgba(20, 24, 27, 0.12); + + /* 字体 §3 */ + --song-font-display: 'LXGW WenKai', 'Noto Serif SC', 'Songti SC', serif; + --song-font-serif: 'Noto Serif SC', 'Songti SC', serif; + --song-font-sans: 'Noto Sans SC', -apple-system, 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif; + --song-font-body: var(--song-font-sans); + + /* 圆角 §4.3 */ + --song-radius-s: 2px; + --song-radius-m: 4px; + --song-radius-l: 6px; + + /* 间距 §4.1(8pt 网格) */ + --song-space-1: 4px; + --song-space-2: 8px; + --song-space-3: 12px; + --song-space-4: 16px; + --song-space-5: 24px; + --song-space-6: 32px; + --song-space-8: 64px; + + /* 留白梯度 §4.2 */ + --song-density: 1; + + /* 动效 §7 */ + --song-ease: cubic-bezier(0.33, 1, 0.68, 1); + --song-dur-1: 200ms; + --song-dur-2: 320ms; +} \ No newline at end of file