glasscn-core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/package.json +53 -0
- package/src/bridge/auto.css +589 -0
- package/src/headless.css +17 -0
- package/src/index.css +28 -0
- package/src/palettes/ember-slate.css +35 -0
- package/src/palettes/emerald-mist.css +35 -0
- package/src/palettes/liquid-light.css +99 -0
- package/src/palettes/ocean-frost.css +35 -0
- package/src/palettes/soft-bloom.css +35 -0
- package/src/palettes/switchable.css +129 -0
- package/src/palettes/warm-sunset.css +35 -0
- package/src/primitives/backdrop.css +128 -0
- package/src/primitives/fallback.css +220 -0
- package/src/primitives/interaction.css +159 -0
- package/src/primitives/reveal.css +168 -0
- package/src/primitives/surface.css +212 -0
- package/src/tokens/bridge.css +108 -0
- package/src/tokens/elevation.css +52 -0
- package/src/tokens/palette.css +47 -0
- package/src/tokens/primitives.css +103 -0
- package/src/tokens/typography.css +46 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — 表面原语 (Surface Primitives)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 一块玻璃 = 四件事,缺一件就露馅:
|
|
5
|
+
*
|
|
6
|
+
* 1. backdrop-filter: blur() saturate() 折射背后的光斑
|
|
7
|
+
* 2. background: rgba(255,255,255,N) 白色中性填充,绝不带色
|
|
8
|
+
* 3. box-shadow inset 顶边 1px 高光 玻璃厚度接到顶光 —— 不可省
|
|
9
|
+
* 4. 1px 描边 面板在背景上的可读边界 —— 不可省
|
|
10
|
+
*
|
|
11
|
+
* 第 3 条是"真玻璃"和"一块模糊的板子"之间唯一的区别。
|
|
12
|
+
* 第 4 条一去掉,面板边界会溶进背景,整个界面失去结构。
|
|
13
|
+
* ==========================================================================*/
|
|
14
|
+
|
|
15
|
+
@utility glass-surface {
|
|
16
|
+
background-color: rgb(var(--glass-white) / var(--glass-fill-current));
|
|
17
|
+
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
18
|
+
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
19
|
+
border: var(--glass-border-width) solid var(--glass-border);
|
|
20
|
+
box-shadow:
|
|
21
|
+
var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
22
|
+
var(--glass-underline),
|
|
23
|
+
var(--glass-shadow);
|
|
24
|
+
border-radius: var(--glass-radius-card);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* --- 高度档位:只改变量 --------------------------------------------------- */
|
|
28
|
+
|
|
29
|
+
@utility glass-flat {
|
|
30
|
+
--glass-blur: var(--glass-blur-flat);
|
|
31
|
+
--glass-fill-current: var(--glass-fill-flat);
|
|
32
|
+
--glass-shadow: var(--glass-shadow-flat);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@utility glass-raised {
|
|
36
|
+
--glass-blur: var(--glass-blur-raised);
|
|
37
|
+
--glass-fill-current: var(--glass-fill-raised);
|
|
38
|
+
--glass-shadow: var(--glass-shadow-raised);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@utility glass-overlay {
|
|
42
|
+
--glass-blur: var(--glass-blur-overlay);
|
|
43
|
+
--glass-fill-current: var(--glass-fill-overlay);
|
|
44
|
+
--glass-shadow: var(--glass-shadow-overlay);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@utility glass-modal {
|
|
48
|
+
--glass-blur: var(--glass-blur-modal);
|
|
49
|
+
--glass-fill-current: var(--glass-fill-modal);
|
|
50
|
+
--glass-shadow: var(--glass-shadow-modal);
|
|
51
|
+
--glass-saturate: var(--glass-saturate-modal);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* --- 形状 ----------------------------------------------------------------- */
|
|
55
|
+
|
|
56
|
+
@utility glass-panel {
|
|
57
|
+
border-radius: var(--glass-radius-panel);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@utility glass-pill {
|
|
61
|
+
border-radius: var(--glass-radius-pill);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* --- 遮罩层 --------------------------------------------------------------- */
|
|
65
|
+
|
|
66
|
+
@utility glass-scrim {
|
|
67
|
+
background-color: var(--glass-scrim);
|
|
68
|
+
-webkit-backdrop-filter: blur(var(--glass-scrim-blur)) saturate(140%);
|
|
69
|
+
backdrop-filter: blur(var(--glass-scrim-blur)) saturate(140%);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* --- 导航:只有下边框,没有投影 ------------------------------------------- */
|
|
73
|
+
/* 导航贴在视口顶部,投影会让它读作"浮在纸上的一条",
|
|
74
|
+
而它应该是视口本身的一部分。 */
|
|
75
|
+
|
|
76
|
+
@utility glass-nav {
|
|
77
|
+
background-color: rgb(var(--glass-white) / var(--glass-fill-nav));
|
|
78
|
+
-webkit-backdrop-filter: blur(var(--glass-blur-nav)) saturate(var(--glass-saturate));
|
|
79
|
+
backdrop-filter: blur(var(--glass-blur-nav)) saturate(var(--glass-saturate));
|
|
80
|
+
border: 0;
|
|
81
|
+
/* 描边和高光都比通用玻璃更收敛(0.08 / 0.06 对 0.12 / 0.20)——
|
|
82
|
+
导航横跨整个视口宽度,用通用强度会显得像一条亮带。 */
|
|
83
|
+
border-bottom: var(--glass-border-width) solid rgb(var(--glass-white) / 0.08);
|
|
84
|
+
border-radius: 0;
|
|
85
|
+
box-shadow: 0 1px 0 0 rgb(var(--glass-white) / 0.06) inset;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* --- 滚动边缘效果:内容掠过导航下缘时渐现 --------------------------------- */
|
|
89
|
+
/* Apple 材质规范:悬浮 chrome 和内容的交界不用常驻硬分隔线,
|
|
90
|
+
而是内容真正滚过导航下缘时,一道阴影从无到有渐现 --
|
|
91
|
+
「滚动边缘效果,不是硬分隔线」。静止在顶部时值为 0,天然干净。
|
|
92
|
+
scroll(root y) 时间轴驱动,0..80px 滚动距离映射整段渐现;
|
|
93
|
+
不支持 scroll-driven animation 的浏览器整块 @supports 忽略,
|
|
94
|
+
退回上面的静态 hairline,行为无回退悬崖。 */
|
|
95
|
+
|
|
96
|
+
@supports (animation-timeline: scroll()) {
|
|
97
|
+
.glass-nav {
|
|
98
|
+
animation: glass-nav-edge linear both;
|
|
99
|
+
animation-timeline: scroll(root y);
|
|
100
|
+
animation-range: 0 80px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@keyframes glass-nav-edge {
|
|
104
|
+
from { box-shadow: 0 1px 0 0 rgb(var(--glass-white) / 0.06) inset; }
|
|
105
|
+
to {
|
|
106
|
+
box-shadow:
|
|
107
|
+
0 1px 0 0 rgb(var(--glass-white) / 0.06) inset,
|
|
108
|
+
0 8px 16px -12px rgb(0 0 0 / 0.55),
|
|
109
|
+
0 1px 0 0 rgb(0 0 0 / 0.35);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* --- 菜单 / 上下文菜单 ----------------------------------------------------- */
|
|
115
|
+
/* 规范单列的一档:blur 28 saturate 200%,填充 0.10、描边 0.14。
|
|
116
|
+
比 modal 稍薄但饱和更高 —— 菜单浮在内容正上方很近的距离,
|
|
117
|
+
太厚会让下面的内容彻底消失,失去空间关系。 */
|
|
118
|
+
|
|
119
|
+
@utility glass-menu {
|
|
120
|
+
background-color: rgb(var(--glass-white) / 0.1);
|
|
121
|
+
-webkit-backdrop-filter: blur(28px) saturate(200%);
|
|
122
|
+
backdrop-filter: blur(28px) saturate(200%);
|
|
123
|
+
border: var(--glass-border-width) solid rgb(var(--glass-white) / 0.14);
|
|
124
|
+
border-radius: var(--glass-radius-card);
|
|
125
|
+
box-shadow:
|
|
126
|
+
0 1px 0 0 rgb(var(--glass-white) / 0.18) inset,
|
|
127
|
+
0 20px 60px rgb(0 0 0 / 0.4);
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* --- 高级卡片:渐变描边 ---------------------------------------------------- */
|
|
132
|
+
/* 光只打在左上角,向右下渐隐 —— 模拟单一光源打在一块有厚度的玻璃棱上。
|
|
133
|
+
用 mask 做描边而不是 border-image:border-image 不认 border-radius。 */
|
|
134
|
+
|
|
135
|
+
@utility glass-premium {
|
|
136
|
+
position: relative;
|
|
137
|
+
border-color: transparent;
|
|
138
|
+
|
|
139
|
+
&::before {
|
|
140
|
+
content: "";
|
|
141
|
+
position: absolute;
|
|
142
|
+
inset: 0;
|
|
143
|
+
z-index: 1;
|
|
144
|
+
border-radius: inherit;
|
|
145
|
+
padding: var(--glass-border-width);
|
|
146
|
+
pointer-events: none;
|
|
147
|
+
background: linear-gradient(
|
|
148
|
+
135deg,
|
|
149
|
+
rgb(var(--glass-white) / 0.45) 0%,
|
|
150
|
+
rgb(var(--glass-white) / 0.12) 32%,
|
|
151
|
+
rgb(var(--glass-white) / 0) 65%
|
|
152
|
+
);
|
|
153
|
+
mask:
|
|
154
|
+
linear-gradient(#000 0 0) content-box,
|
|
155
|
+
linear-gradient(#000 0 0);
|
|
156
|
+
mask-composite: exclude;
|
|
157
|
+
-webkit-mask:
|
|
158
|
+
linear-gradient(#000 0 0) content-box,
|
|
159
|
+
linear-gradient(#000 0 0);
|
|
160
|
+
-webkit-mask-composite: xor;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* --- 局部覆写 ------------------------------------------------------------- */
|
|
165
|
+
|
|
166
|
+
@utility glass-blur-* {
|
|
167
|
+
--glass-blur: --value([length], --blur- *);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@utility glass-fill-* {
|
|
171
|
+
/* glass-fill-12 → 填充不透明度 0.12 */
|
|
172
|
+
--glass-fill-current: calc(--value(integer) / 100);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* --- 通透度:独立于调色的一条轴 -------------------------------------------- */
|
|
176
|
+
/* <html data-glass-density="sheer"> 整站切换,或挂在任意子树上局部切换。
|
|
177
|
+
sheer 需要背景足够干净,否则文字会被背后的光斑洗掉;
|
|
178
|
+
heavy 可读性最好,数据密集界面用它。 */
|
|
179
|
+
|
|
180
|
+
:root[data-glass-density="sheer"],
|
|
181
|
+
[data-glass-density="sheer"] {
|
|
182
|
+
--glass-fill-flat: 0.03;
|
|
183
|
+
--glass-fill-raised: 0.05;
|
|
184
|
+
--glass-fill-overlay: 0.07;
|
|
185
|
+
--glass-fill-modal: 0.09;
|
|
186
|
+
--glass-blur-base: 24px;
|
|
187
|
+
--glass-saturate: 200%;
|
|
188
|
+
--glass-border-alpha: 0.08;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
:root[data-glass-density="heavy"],
|
|
192
|
+
[data-glass-density="heavy"] {
|
|
193
|
+
--glass-fill-flat: 0.16;
|
|
194
|
+
--glass-fill-raised: 0.2;
|
|
195
|
+
--glass-fill-overlay: 0.24;
|
|
196
|
+
--glass-fill-modal: 0.28;
|
|
197
|
+
--glass-blur-base: 14px;
|
|
198
|
+
--glass-saturate: 160%;
|
|
199
|
+
--glass-border-alpha: 0.2;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* --- 嵌套保护 ------------------------------------------------------------- */
|
|
203
|
+
/* 规范硬约束:模糊层最多叠三层。内层玻璃退回"薄玻璃"——
|
|
204
|
+
保留填充和棱边,去掉背景模糊。再模糊一次已经模糊过的结果,
|
|
205
|
+
画面会浑,边框也会叠成脏线。 */
|
|
206
|
+
|
|
207
|
+
@utility glass-nested {
|
|
208
|
+
-webkit-backdrop-filter: none;
|
|
209
|
+
backdrop-filter: none;
|
|
210
|
+
--glass-fill-current: 0.05;
|
|
211
|
+
--glass-shadow: none;
|
|
212
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — shadcn 变量桥 (Token Bridge)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 与 shadcn 集成的核心策略:接管变量,而不是覆写属性。
|
|
5
|
+
*
|
|
6
|
+
* shadcn 组件写的是 `bg-card` `border` `shadow-sm`,都是 Tailwind 工具类
|
|
7
|
+
* (0,1,0)。如果用 `[data-slot=card] { background: ... }` 去压它,
|
|
8
|
+
* 会连用户自己写的 `className="bg-white/70"` 一起压掉——库变得不可覆写。
|
|
9
|
+
*
|
|
10
|
+
* 所以:shadcn 已经设过的属性只改背后的变量;
|
|
11
|
+
* 它从不设的属性(backdrop-filter、微光)才由 bridge/auto.css 补。
|
|
12
|
+
* ==========================================================================*/
|
|
13
|
+
|
|
14
|
+
:root {
|
|
15
|
+
/* --- 页面底:不透明,玻璃需要底下有东西可折射 --------------------------- */
|
|
16
|
+
--background: var(--glass-bg-base);
|
|
17
|
+
--foreground: var(--glass-text-primary);
|
|
18
|
+
|
|
19
|
+
/* --- 表面类 token 全部换成白色中性玻璃 ---------------------------------- */
|
|
20
|
+
/* 注意这里没有一个是有色的。玻璃的颜色来自背后的光斑,不是这些变量。 */
|
|
21
|
+
--card: rgb(var(--glass-white) / var(--glass-fill-raised));
|
|
22
|
+
--card-foreground: var(--glass-text-primary);
|
|
23
|
+
--popover: rgb(var(--glass-white) / var(--glass-fill-overlay));
|
|
24
|
+
--popover-foreground: var(--glass-text-primary);
|
|
25
|
+
--secondary: rgb(var(--glass-white) / var(--glass-fill-raised));
|
|
26
|
+
--secondary-foreground: var(--glass-text-primary);
|
|
27
|
+
--muted: rgb(var(--glass-white) / var(--glass-fill-flat));
|
|
28
|
+
--accent: rgb(var(--glass-white) / var(--glass-fill-hover));
|
|
29
|
+
--accent-foreground: var(--glass-text-primary);
|
|
30
|
+
--input: rgb(var(--glass-white) / var(--glass-fill-flat));
|
|
31
|
+
--sidebar: rgb(var(--glass-white) / var(--glass-fill-overlay));
|
|
32
|
+
--sidebar-foreground: var(--glass-text-primary);
|
|
33
|
+
--sidebar-accent: rgb(var(--glass-white) / var(--glass-fill-hover));
|
|
34
|
+
--sidebar-accent-foreground: var(--glass-text-primary);
|
|
35
|
+
|
|
36
|
+
--border: var(--glass-border);
|
|
37
|
+
--sidebar-border: var(--glass-border);
|
|
38
|
+
--ring: var(--glass-accent);
|
|
39
|
+
|
|
40
|
+
/* --- 主操作是实心强调色,不是玻璃 --------------------------------------- */
|
|
41
|
+
/* 一屏全是半透明面板时,主按钮再做成玻璃,用户就找不到"该点哪个"。
|
|
42
|
+
这是规范里明确的一条,也是可供性问题,不是审美偏好。 */
|
|
43
|
+
--primary: var(--glass-accent);
|
|
44
|
+
--primary-foreground: var(--glass-accent-fg);
|
|
45
|
+
--sidebar-primary: var(--glass-accent);
|
|
46
|
+
--sidebar-primary-foreground: var(--glass-accent-fg);
|
|
47
|
+
|
|
48
|
+
--destructive: var(--glass-danger);
|
|
49
|
+
--destructive-foreground: var(--glass-danger-fg);
|
|
50
|
+
|
|
51
|
+
/* --- 次要文字 ----------------------------------------------------------- */
|
|
52
|
+
/* 映射到 text-secondary (0.68) 而不是 text-muted (0.38)。
|
|
53
|
+
muted 在 WCAG 下只有约 3.3:1,规范给它的定位是"占位符、标签",
|
|
54
|
+
但 shadcn 的 --muted-foreground 承担的是真正的次要正文
|
|
55
|
+
(CardDescription、表格副标题、表单说明),必须达到 4.5:1。
|
|
56
|
+
想要 muted 那一档,直接用 var(--glass-text-muted)。 */
|
|
57
|
+
--muted-foreground: var(--glass-text-secondary);
|
|
58
|
+
--sidebar-ring: var(--glass-accent);
|
|
59
|
+
|
|
60
|
+
/* --- 圆角:药丸是这套设计的形状签名 ------------------------------------- */
|
|
61
|
+
/* shadcn 用单个 --radius 派生整个量表:
|
|
62
|
+
sm = r-4, md = r-2, lg = r, xl = r+4
|
|
63
|
+
卡片写的是 rounded-xl,所以基准取 16px 让 xl 自然落在规范的 20px。
|
|
64
|
+
按钮/输入框那些药丸形状,在 auto 层里按元素改对应的 --radius-* 变量 ——
|
|
65
|
+
不能直接写 border-radius 属性,那是 @layer components,
|
|
66
|
+
会被组件自带的 rounded-md 工具类(@layer utilities)压掉。 */
|
|
67
|
+
--radius: 16px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ----------------------------------------------------------------------------
|
|
71
|
+
* 阴影量表接管
|
|
72
|
+
* ----------------------------------------------------------------------------
|
|
73
|
+
* shadcn 组件里散落着 shadow-xs / sm / md / lg。把整个量表换成
|
|
74
|
+
* "玻璃阴影 = 顶边高光 + 外投影",现有组件不改一行就有了正确的厚度感。
|
|
75
|
+
* 用户写 shadow-none 依然完全生效。
|
|
76
|
+
* ==========================================================================*/
|
|
77
|
+
|
|
78
|
+
@theme inline {
|
|
79
|
+
--shadow-2xs: var(--glass-specular-size) var(--glass-specular-color) inset;
|
|
80
|
+
|
|
81
|
+
--shadow-xs: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
82
|
+
var(--glass-underline), 0 2px 8px rgb(0 0 0 / 0.2);
|
|
83
|
+
|
|
84
|
+
--shadow-sm: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
85
|
+
var(--glass-underline), var(--glass-shadow-flat);
|
|
86
|
+
|
|
87
|
+
--shadow-md: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
88
|
+
var(--glass-underline), var(--glass-shadow-raised);
|
|
89
|
+
|
|
90
|
+
--shadow-lg: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
91
|
+
var(--glass-underline), var(--glass-shadow-overlay);
|
|
92
|
+
|
|
93
|
+
--shadow-xl: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
94
|
+
var(--glass-underline), var(--glass-shadow-modal);
|
|
95
|
+
|
|
96
|
+
--shadow-2xl: var(--glass-specular-size) var(--glass-specular-color) inset,
|
|
97
|
+
var(--glass-underline), var(--glass-shadow-modal);
|
|
98
|
+
|
|
99
|
+
/* 材质变量也暴露成 Tailwind 工具类 */
|
|
100
|
+
--blur-glass: var(--glass-blur-base);
|
|
101
|
+
--blur-glass-overlay: var(--glass-blur-overlay);
|
|
102
|
+
--blur-glass-modal: var(--glass-blur-modal);
|
|
103
|
+
--ease-glass: var(--glass-ease);
|
|
104
|
+
--ease-glass-out: var(--glass-ease-out);
|
|
105
|
+
--ease-glass-spring: var(--glass-ease-spring);
|
|
106
|
+
--radius-pill: var(--glass-radius-pill);
|
|
107
|
+
--color-glass-accent: var(--glass-accent);
|
|
108
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — 高度阶梯 (Elevation Scale)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 设计说明给的是按组件点名的数值(导航 blur 24、上下文菜单 blur 28 saturate 200%)。
|
|
5
|
+
* 这里把那些点整理成一条连续的阶梯,组件只声明自己在哪一档。
|
|
6
|
+
*
|
|
7
|
+
* flat 输入框 / 徽章 / 表格 blur 16 fill .06
|
|
8
|
+
* raised 卡片 / 次级按钮 / 标签页 blur 20 fill .08 ← 规范里的"默认玻璃"
|
|
9
|
+
* overlay 导航 / 浮层 / 侧边栏 blur 24 fill .10
|
|
10
|
+
* modal 对话框 / 抽屉 / 命令面板 blur 28 fill .12 saturate 200%
|
|
11
|
+
*
|
|
12
|
+
* 规范另一条硬约束:模糊层最多叠三层。再多性能会塌,画面也会浑。
|
|
13
|
+
* 嵌套保护在 bridge/auto.css 里,内层玻璃自动退回无模糊的薄玻璃。
|
|
14
|
+
* ==========================================================================*/
|
|
15
|
+
|
|
16
|
+
:root {
|
|
17
|
+
/* --- flat --------------------------------------------------------------- */
|
|
18
|
+
--glass-blur-flat: calc(var(--glass-blur-base) * 0.8);
|
|
19
|
+
--glass-fill-flat: 0.06;
|
|
20
|
+
--glass-shadow-flat: 0 2px 8px rgb(0 0 0 / 0.2);
|
|
21
|
+
|
|
22
|
+
/* --- raised ------------------------------------------------------------- */
|
|
23
|
+
--glass-blur-raised: var(--glass-blur-base);
|
|
24
|
+
--glass-fill-raised: var(--glass-fill);
|
|
25
|
+
--glass-shadow-raised: var(--glass-shadow-base);
|
|
26
|
+
|
|
27
|
+
/* --- overlay ------------------------------------------------------------ */
|
|
28
|
+
--glass-blur-overlay: calc(var(--glass-blur-base) * 1.2);
|
|
29
|
+
--glass-fill-overlay: 0.1;
|
|
30
|
+
--glass-shadow-overlay: 0 16px 48px rgb(0 0 0 / 0.42);
|
|
31
|
+
|
|
32
|
+
/* --- modal -------------------------------------------------------------- */
|
|
33
|
+
--glass-blur-modal: calc(var(--glass-blur-base) * 1.4);
|
|
34
|
+
--glass-fill-modal: 0.12;
|
|
35
|
+
--glass-saturate-modal: 200%;
|
|
36
|
+
--glass-shadow-modal: 0 24px 72px rgb(0 0 0 / 0.55);
|
|
37
|
+
|
|
38
|
+
/* --- 导航:规范里单列的一档 --------------------------------------------- */
|
|
39
|
+
/* 只有下边框、没有投影 —— 导航贴在视口顶部,投影会让它显得"浮在纸上",
|
|
40
|
+
而它应该读作视口本身的一部分。 */
|
|
41
|
+
--glass-fill-nav: 0.06;
|
|
42
|
+
--glass-blur-nav: calc(var(--glass-blur-base) * 1.2);
|
|
43
|
+
|
|
44
|
+
/* --- 遮罩层 ------------------------------------------------------------- */
|
|
45
|
+
--glass-scrim: rgb(0 0 0 / 0.55);
|
|
46
|
+
--glass-scrim-blur: calc(var(--glass-blur-base) * 0.4);
|
|
47
|
+
|
|
48
|
+
/* 默认档位:raised。各组件在 auto 层里覆写成自己的档。 */
|
|
49
|
+
--glass-blur: var(--glass-blur-raised);
|
|
50
|
+
--glass-fill-current: var(--glass-fill-raised);
|
|
51
|
+
--glass-shadow: var(--glass-shadow-raised);
|
|
52
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — 调色 (Palette)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 默认:Ember & Slate —— 带暖调的近黑炭灰底 + 琥珀/赭石光斑。
|
|
5
|
+
*
|
|
6
|
+
* 换调色换的是**背景光斑和强调色**,玻璃填充永远是白色中性。
|
|
7
|
+
* 每套调色只需要定义八个值:底色两级、三个光斑、强调色、文字色调。
|
|
8
|
+
* 见 palettes/ 目录里另外五套。
|
|
9
|
+
* ==========================================================================*/
|
|
10
|
+
|
|
11
|
+
:root {
|
|
12
|
+
/* --- 底 ----------------------------------------------------------------- */
|
|
13
|
+
--glass-bg-base: #100d0a;
|
|
14
|
+
--glass-bg-mid: #1c1510;
|
|
15
|
+
|
|
16
|
+
/* --- 光斑:整套视觉的颜色都来自这三团 ---------------------------------- */
|
|
17
|
+
/* 顺序有讲究:blob-1 是最大最亮的那团(650px, opacity .55),
|
|
18
|
+
整个画面的主色调由它决定,所以放琥珀而不是赭石。 */
|
|
19
|
+
--glass-blob-1: #f59e0b; /* 琥珀 */
|
|
20
|
+
--glass-blob-2: #c2410c; /* 赭石 */
|
|
21
|
+
--glass-blob-3: #78350f; /* 深琥珀棕 */
|
|
22
|
+
|
|
23
|
+
/* --- 强调色:只用于 CTA 和交互态 --------------------------------------- */
|
|
24
|
+
--glass-accent: #f59e0b;
|
|
25
|
+
--glass-accent-hover: #fbbf24;
|
|
26
|
+
--glass-accent-fg: #1a1206; /* 琥珀底上的文字必须是近黑,不是白 */
|
|
27
|
+
|
|
28
|
+
/* --- 文字 --------------------------------------------------------------- */
|
|
29
|
+
/* 暖白,永远不用纯 #ffffff —— 纯白在暖调背景上会显得脏且刺眼 */
|
|
30
|
+
--glass-text-rgb: 255 248 240;
|
|
31
|
+
--glass-text-primary: rgb(var(--glass-text-rgb) / 0.95);
|
|
32
|
+
|
|
33
|
+
/* 次要文字用 0.60。规范里 text-secondary 是 rgba(255,235,210,0.60),
|
|
34
|
+
这里统一走同一个 rgb 三元组,色相差异交给光斑去表达。 */
|
|
35
|
+
--glass-text-secondary: rgb(var(--glass-text-rgb) / 0.68);
|
|
36
|
+
|
|
37
|
+
/* 弱化文字 0.35 —— 规范定位是"占位符、标签"。
|
|
38
|
+
注意它在 WCAG 下只有约 3.3:1,达不到 4.5:1,
|
|
39
|
+
所以只能用于占位符和纯装饰性文字。真正的次要正文走 secondary。
|
|
40
|
+
bridge.css 里 --muted-foreground 映射到 secondary 而不是这里,
|
|
41
|
+
就是为了防止这一条被误用。 */
|
|
42
|
+
--glass-text-muted: rgb(var(--glass-text-rgb) / 0.38);
|
|
43
|
+
|
|
44
|
+
/* --- 语义色 ------------------------------------------------------------- */
|
|
45
|
+
--glass-danger: #f87171;
|
|
46
|
+
--glass-danger-fg: #1a0a0a;
|
|
47
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — 材质原语 (Material Primitives)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 核心规则,整套体系的地基:
|
|
5
|
+
*
|
|
6
|
+
* 玻璃本身没有颜色。它的颜色全部来自背后的背景,
|
|
7
|
+
* 经过模糊和提亮之后透过面板显出来。
|
|
8
|
+
*
|
|
9
|
+
* 所以 glass fill 永远是 rgba(255,255,255,N) —— 白色中性,绝不带色调。
|
|
10
|
+
* 想换整体气质,换的是背后光斑(blob)的颜色,不是玻璃的颜色。
|
|
11
|
+
* 这条一破,玻璃立刻变成"有色半透明塑料片"。
|
|
12
|
+
*
|
|
13
|
+
* 暗色优先:Ember & Slate 是默认,浅色是 palettes/liquid-light 的变体。
|
|
14
|
+
* ==========================================================================*/
|
|
15
|
+
|
|
16
|
+
:root {
|
|
17
|
+
color-scheme: dark;
|
|
18
|
+
|
|
19
|
+
/* --- 折射 -------------------------------------------------------------- */
|
|
20
|
+
/* 模糊基数。所有档位由它派生,改这一个值整体调厚度。 */
|
|
21
|
+
--glass-blur-base: 20px;
|
|
22
|
+
|
|
23
|
+
/* saturate 必须和 blur 一起用。只有 blur 的话,背后的颜色透过来会发灰,
|
|
24
|
+
看着像磨砂塑料;saturate 让颜色"绽"出来,这才是玻璃感的真正来源。 */
|
|
25
|
+
--glass-saturate: 180%;
|
|
26
|
+
--glass-brightness: 1;
|
|
27
|
+
|
|
28
|
+
/* --- 玻璃填充(白色中性,不可改成有色) -------------------------------- */
|
|
29
|
+
--glass-white: 255 255 255;
|
|
30
|
+
--glass-fill: 0.08;
|
|
31
|
+
--glass-fill-hover: 0.13;
|
|
32
|
+
|
|
33
|
+
/* 通透度是独立于调色的一条轴。三档,靠 data-glass-density 切换,
|
|
34
|
+
见 primitives/surface.css 末尾。
|
|
35
|
+
sheer 几乎全透,背景清晰可见
|
|
36
|
+
frosted 默认,背景读得出颜色和形状,细节丢失
|
|
37
|
+
heavy 接近不透明,戏剧化、可读性最好 */
|
|
38
|
+
|
|
39
|
+
/* --- 边缘光学 ---------------------------------------------------------- */
|
|
40
|
+
--glass-border-alpha: 0.12;
|
|
41
|
+
--glass-border-alpha-hover: 0.22;
|
|
42
|
+
--glass-border-width: 1px;
|
|
43
|
+
|
|
44
|
+
/* 高光 (specular):顶边 1px 内阴影,模拟玻璃的物理厚度接到顶光。
|
|
45
|
+
这是 Apple Liquid Glass 的签名,也是"真玻璃"和"一块模糊的板子"
|
|
46
|
+
之间唯一的区别。不可省。 */
|
|
47
|
+
--glass-specular: 0.2;
|
|
48
|
+
--glass-specular-size: 0 1px 0 0;
|
|
49
|
+
|
|
50
|
+
/* 底边暗线:暗色下不需要(背景本来就暗),浅色调色里会打开。
|
|
51
|
+
默认 none,靠调色覆写。 */
|
|
52
|
+
--glass-underline: 0 0 0 0 transparent;
|
|
53
|
+
|
|
54
|
+
/* --- 投影 --------------------------------------------------------------- */
|
|
55
|
+
/* 比常规暗色 UI 更深,玻璃需要更强的投影才能从背景里分离出来 */
|
|
56
|
+
--glass-shadow-base: 0 12px 40px rgb(0 0 0 / 0.35);
|
|
57
|
+
--glass-shadow-hover: 0 20px 60px rgb(0 0 0 / 0.5);
|
|
58
|
+
|
|
59
|
+
/* --- 运动 --------------------------------------------------------------- */
|
|
60
|
+
/* 缓动哲学对齐 Apple(阻尼比 + 响应,见 WWDC「流体界面」):
|
|
61
|
+
默认一切临界阻尼(阻尼比 1.0,无过冲)。悬停、入场、位移都不是
|
|
62
|
+
被甩出去的,不该弹;过冲只属于带着动量的手势(拨开关、倾斜回弹)。
|
|
63
|
+
旧版把过冲曲线用在所有 hover 上,手感是"弹跳的塑料",已废弃。 */
|
|
64
|
+
--glass-duration-fast: 80ms; /* active 要"啪"地一下,不能拖 */
|
|
65
|
+
--glass-duration: 240ms; /* 位移/投影:等效响应 ~0.35s 的弹簧 */
|
|
66
|
+
--glass-duration-slow: 600ms; /* 滚动揭示专用,只有它配用慢档 */
|
|
67
|
+
--glass-duration-color: 150ms; /* 颜色反馈比位移快一拍 */
|
|
68
|
+
--glass-duration-enter: 240ms; /* 浮层物化入场 */
|
|
69
|
+
--glass-duration-exit: 160ms; /* 退场比入场快 -- 离开不该有仪式感 */
|
|
70
|
+
|
|
71
|
+
/* 阻尼 1.0 · 响应 ~0.35s:transform 和投影的默认曲线 */
|
|
72
|
+
--glass-ease: cubic-bezier(0.22, 1, 0.36, 1);
|
|
73
|
+
/* 攻击更快收尾干净:颜色和淡入淡出用它 */
|
|
74
|
+
--glass-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
75
|
+
/* 阻尼 ~0.8,轻微过冲。仅限动量交互(开关拨杆、倾斜回弹)--
|
|
76
|
+
出现在 hover 上就是误用,verify 里有断言盯着。 */
|
|
77
|
+
--glass-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
78
|
+
--glass-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
79
|
+
|
|
80
|
+
/* --- 交互位移 ----------------------------------------------------------- */
|
|
81
|
+
--glass-lift: 4px;
|
|
82
|
+
--glass-press: 1px;
|
|
83
|
+
--glass-press-scale: 0.97;
|
|
84
|
+
|
|
85
|
+
/* --- 微光扫过 (shimmer) -------------------------------------------------- */
|
|
86
|
+
--glass-shimmer-alpha: 0.14;
|
|
87
|
+
--glass-shimmer-angle: -20deg;
|
|
88
|
+
--glass-shimmer-duration: 900ms;
|
|
89
|
+
|
|
90
|
+
/* --- 圆角:五级 ---------------------------------------------------------- */
|
|
91
|
+
--glass-radius-sm: 10px; /* 徽章内部、小控件 */
|
|
92
|
+
--glass-radius-md: 16px; /* 骨架屏、次级容器 */
|
|
93
|
+
--glass-radius-card: 20px; /* 卡片、菜单 */
|
|
94
|
+
--glass-radius-panel: 28px; /* 大面板、hero */
|
|
95
|
+
--glass-radius-pill: 999px; /* 按钮、输入框、标签 */
|
|
96
|
+
|
|
97
|
+
/* --- 由上面派生的可直接用的颜色 ------------------------------------------ */
|
|
98
|
+
--glass-bg: rgb(var(--glass-white) / var(--glass-fill));
|
|
99
|
+
--glass-bg-hover: rgb(var(--glass-white) / var(--glass-fill-hover));
|
|
100
|
+
--glass-border: rgb(var(--glass-white) / var(--glass-border-alpha));
|
|
101
|
+
--glass-border-hover: rgb(var(--glass-white) / var(--glass-border-alpha-hover));
|
|
102
|
+
--glass-specular-color: rgb(var(--glass-white) / var(--glass-specular));
|
|
103
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* glasscn-core — 字体 (Typography)
|
|
3
|
+
* ----------------------------------------------------------------------------
|
|
4
|
+
* 只定义 token,不加载字体。
|
|
5
|
+
*
|
|
6
|
+
* 这个库承诺零外部依赖,主题层里塞一个 Google Fonts 的 @import 会让每个
|
|
7
|
+
* 使用方都多一个跨域阻塞请求(国内网络尤其明显),而且没法退。
|
|
8
|
+
* 所以字体由消费方自己引,这里给出完整的 fallback 栈,
|
|
9
|
+
* 不引也不会崩,只是落到系统字体。
|
|
10
|
+
*
|
|
11
|
+
* 想要规范里的效果,在你自己的 HTML 里加:
|
|
12
|
+
*
|
|
13
|
+
* <link rel="preconnect" href="https://fonts.googleapis.com">
|
|
14
|
+
* <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
15
|
+
* <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Outfit:wght@600;700;800&family=DM+Sans:wght@400;500&display=swap">
|
|
16
|
+
*
|
|
17
|
+
* 自托管或用国内 CDN 时,把 font-family 的第一项换掉即可,别的不用动。
|
|
18
|
+
* ==========================================================================*/
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
--glass-font-heading: "Outfit", ui-sans-serif, system-ui, -apple-system,
|
|
22
|
+
"Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
23
|
+
--glass-font-body: "DM Sans", ui-sans-serif, system-ui, -apple-system,
|
|
24
|
+
"Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
25
|
+
|
|
26
|
+
/* 标题:几何感、字距收紧、随视口流体缩放 */
|
|
27
|
+
--glass-tracking-heading: -0.02em;
|
|
28
|
+
/* 小字排印:正字距。全大写的 eyebrow / 徽章字距必须拉开,
|
|
29
|
+
否则字母糊在一起 -- 这是 tracking 是尺寸函数的另一端。 */
|
|
30
|
+
--glass-tracking-caps: 0.14em;
|
|
31
|
+
--glass-text-h1: clamp(2.5rem, 5vw, 4.5rem);
|
|
32
|
+
--glass-text-h2: clamp(1.8rem, 3vw, 3rem);
|
|
33
|
+
--glass-text-h3: 1.5rem;
|
|
34
|
+
|
|
35
|
+
/* 行高随字号反向走(WWDC「UI 字体排印」):大标题收紧贴排,
|
|
36
|
+
正文给足呼吸。玻璃上的长文本需要更多行高。 */
|
|
37
|
+
--glass-leading-heading: 1.1;
|
|
38
|
+
--glass-leading-body: 1.75;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@theme inline {
|
|
42
|
+
--font-heading: var(--glass-font-heading);
|
|
43
|
+
--font-sans: var(--glass-font-body);
|
|
44
|
+
--text-display: var(--glass-text-h1);
|
|
45
|
+
--text-title: var(--glass-text-h2);
|
|
46
|
+
}
|