@vestow/theme 0.1.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/README.md +157 -0
- package/css/README.md +90 -0
- package/css/app.css +100 -0
- package/css/bases.css +86 -0
- package/css/charts.css +152 -0
- package/css/components/button.css +143 -0
- package/css/index.css +63 -0
- package/css/menus.css +165 -0
- package/css/palettes.css +292 -0
- package/css/primitives.css +224 -0
- package/css/styles.css +203 -0
- package/css/surfaces.css +364 -0
- package/css/tailwind.css +163 -0
- package/css/tokens.css +627 -0
- package/css/typeset.css +274 -0
- package/dist/controller.d.ts +56 -0
- package/dist/controller.d.ts.map +1 -0
- package/dist/controller.js +256 -0
- package/dist/controller.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/preset.d.ts +90 -0
- package/dist/preset.d.ts.map +1 -0
- package/dist/preset.js +86 -0
- package/dist/preset.js.map +1 -0
- package/dist/registry.d.ts +252 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +238 -0
- package/dist/registry.js.map +1 -0
- package/dist/token-names.d.ts +512 -0
- package/dist/token-names.d.ts.map +1 -0
- package/dist/token-names.js +7 -0
- package/dist/token-names.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
TOKEN CỦA RIÊNG BUTTON — tầng token theo COMPONENT, kiểu PrimeVue.
|
|
3
|
+
|
|
4
|
+
Vì sao có tầng này. Cho tới nay Button đọc thẳng 42 token DÙNG CHUNG
|
|
5
|
+
(`--primary`, `--destructive-soft`…), tức muốn chỉnh riêng cái nút thì phải
|
|
6
|
+
đổi một token mà Badge, Alert và hai chục chỗ khác cũng đang đọc. PrimeVue
|
|
7
|
+
giải bằng cách cho mỗi component một không gian tên riêng — 176 token cho
|
|
8
|
+
riêng Button của họ. Đây là bản tương đương cho repo này.
|
|
9
|
+
|
|
10
|
+
MỖI TOKEN MẶC ĐỊNH TRỎ VÀO TOKEN NGỮ NGHĨA. Đó là điều kiện để tầng này
|
|
11
|
+
không phá thứ đang có: chín trục theme vẫn chảy qua (`--primary` đổi theo
|
|
12
|
+
bảng màu thì `--button-default-bg` đổi theo), và diện mạo không dịch một
|
|
13
|
+
pixel. Cái được thêm là một mặt phẳng để ghi đè RIÊNG nút.
|
|
14
|
+
|
|
15
|
+
VÌ SAO ÍT HƠN 176. Bên họ 8 severity × 11, cộng `outlined` và `text` mỗi cái
|
|
16
|
+
nhân 8 nữa. Ở đây `soft` là MỘT trục tone áp cho 5 sắc, và `outline`/`ghost`/
|
|
17
|
+
`link` không nhân theo sắc — nên cùng độ phủ mà còn 65 token.
|
|
18
|
+
|
|
19
|
+
Đếm lại, đừng tin con số trên (nó đã sai một lần, ghi 73):
|
|
20
|
+
|
|
21
|
+
grep -cP '^\s*--button-[a-z-]+:' css/components/button.css
|
|
22
|
+
|
|
23
|
+
Nhóm `--ui-control-*` KHÔNG chép vào đây: chiều cao và đệm ngang dùng chung
|
|
24
|
+
với Toggle theo đúng chủ ý đã ghi ở `CLAUDE.md`, tách ra là dựng lại đúng
|
|
25
|
+
thứ việc gom chúng sinh ra để dập.
|
|
26
|
+
========================================================================== */
|
|
27
|
+
|
|
28
|
+
:root {
|
|
29
|
+
/* --- cấu trúc --- */
|
|
30
|
+
--button-radius: var(--radius-lg);
|
|
31
|
+
--button-radius-sm: var(--radius-md);
|
|
32
|
+
--button-gap: calc(var(--spacing) * 1.5);
|
|
33
|
+
--button-gap-xs: var(--spacing);
|
|
34
|
+
--button-font-weight: 500;
|
|
35
|
+
--button-font-size: var(--text-sm);
|
|
36
|
+
--button-font-size-sm: 0.8rem;
|
|
37
|
+
--button-font-size-xs: var(--text-xs);
|
|
38
|
+
--button-icon-size: calc(var(--spacing) * 4);
|
|
39
|
+
--button-icon-size-xs: calc(var(--spacing) * 3);
|
|
40
|
+
--button-duration: var(--ui-control-duration);
|
|
41
|
+
|
|
42
|
+
/* Hai con số này TRƯỚC ĐÂY là literal nằm trong bảng cva — `active:scale-[0.97]`
|
|
43
|
+
và `disabled:opacity-50`. Đó đúng là thứ tầng token sinh ra để rút. */
|
|
44
|
+
--button-press-scale: 0.97;
|
|
45
|
+
--button-press-duration: var(--ui-control-duration-press);
|
|
46
|
+
--button-disabled-opacity: 0.5;
|
|
47
|
+
|
|
48
|
+
/* --- tone SOLID, sáu sắc ---
|
|
49
|
+
`-active` là nấc MỚI: repo chưa từng có token cho trạng thái nhấn, chỉ có
|
|
50
|
+
một phép thu nhỏ. Dẫn xuất theo đúng khuôn của `-fill-hover` (90% độ đục),
|
|
51
|
+
đi tiếp một nấc còn 80%. */
|
|
52
|
+
--button-default-bg: var(--primary-fill);
|
|
53
|
+
--button-default-bg-hover: var(--primary-fill-hover);
|
|
54
|
+
--button-default-bg-active: color-mix(in oklab, var(--primary) 80%, transparent);
|
|
55
|
+
--button-default-fg: var(--primary-foreground);
|
|
56
|
+
|
|
57
|
+
--button-secondary-bg: var(--secondary-fill);
|
|
58
|
+
--button-secondary-bg-hover: var(--secondary-fill-hover);
|
|
59
|
+
--button-secondary-bg-active: color-mix(in oklab, var(--secondary) 80%, transparent);
|
|
60
|
+
--button-secondary-fg: var(--secondary-foreground);
|
|
61
|
+
|
|
62
|
+
--button-destructive-bg: var(--destructive-fill);
|
|
63
|
+
--button-destructive-bg-hover: var(--destructive-fill-hover);
|
|
64
|
+
--button-destructive-bg-active: color-mix(in oklab, var(--destructive) 80%, transparent);
|
|
65
|
+
--button-destructive-fg: var(--destructive-foreground);
|
|
66
|
+
|
|
67
|
+
--button-success-bg: var(--success-fill);
|
|
68
|
+
--button-success-bg-hover: var(--success-fill-hover);
|
|
69
|
+
--button-success-bg-active: color-mix(in oklab, var(--success) 80%, transparent);
|
|
70
|
+
--button-success-fg: var(--success-foreground);
|
|
71
|
+
|
|
72
|
+
--button-warning-bg: var(--warning-fill);
|
|
73
|
+
--button-warning-bg-hover: var(--warning-fill-hover);
|
|
74
|
+
--button-warning-bg-active: color-mix(in oklab, var(--warning) 80%, transparent);
|
|
75
|
+
--button-warning-fg: var(--warning-foreground);
|
|
76
|
+
|
|
77
|
+
--button-info-bg: var(--info-fill);
|
|
78
|
+
--button-info-bg-hover: var(--info-fill-hover);
|
|
79
|
+
--button-info-bg-active: color-mix(in oklab, var(--info) 80%, transparent);
|
|
80
|
+
--button-info-fg: var(--info-foreground);
|
|
81
|
+
|
|
82
|
+
/* --- tone SOFT, năm sắc màu ---
|
|
83
|
+
Hover đổi THẲNG sang nền đặc và chữ trắng, không nội suy — lý do đo được ở
|
|
84
|
+
mục "Hover nút soft" trong CLAUDE.md: giữa transition tương phản sập còn
|
|
85
|
+
1,09:1. Vì vậy `-soft-bg-hover` trỏ vào màu đặc chứ không phải một nấc pha. */
|
|
86
|
+
--button-default-soft-bg: var(--primary-soft);
|
|
87
|
+
--button-default-soft-bg-hover: var(--primary);
|
|
88
|
+
--button-default-soft-fg: var(--primary-soft-foreground);
|
|
89
|
+
--button-default-soft-fg-hover: var(--primary-foreground);
|
|
90
|
+
|
|
91
|
+
--button-destructive-soft-bg: var(--destructive-soft);
|
|
92
|
+
--button-destructive-soft-bg-hover: var(--destructive);
|
|
93
|
+
--button-destructive-soft-fg: var(--destructive-soft-foreground);
|
|
94
|
+
--button-destructive-soft-fg-hover: var(--destructive-foreground);
|
|
95
|
+
|
|
96
|
+
--button-success-soft-bg: var(--success-soft);
|
|
97
|
+
--button-success-soft-bg-hover: var(--success);
|
|
98
|
+
--button-success-soft-fg: var(--success-soft-foreground);
|
|
99
|
+
--button-success-soft-fg-hover: var(--success-foreground);
|
|
100
|
+
|
|
101
|
+
--button-warning-soft-bg: var(--warning-soft);
|
|
102
|
+
--button-warning-soft-bg-hover: var(--warning);
|
|
103
|
+
--button-warning-soft-fg: var(--warning-soft-foreground);
|
|
104
|
+
--button-warning-soft-fg-hover: var(--warning-foreground);
|
|
105
|
+
|
|
106
|
+
--button-info-soft-bg: var(--info-soft);
|
|
107
|
+
--button-info-soft-bg-hover: var(--info);
|
|
108
|
+
--button-info-soft-fg: var(--info-soft-foreground);
|
|
109
|
+
--button-info-soft-fg-hover: var(--info-foreground);
|
|
110
|
+
|
|
111
|
+
/* --- ba variant không mang sắc --- */
|
|
112
|
+
--button-outline-bg: var(--background);
|
|
113
|
+
--button-outline-bg-hover: var(--accent);
|
|
114
|
+
--button-outline-fg-hover: var(--accent-foreground);
|
|
115
|
+
/* KHÔNG dùng `--input`. Viền của nút outline là RANH GIỚI của control — nút
|
|
116
|
+
đó không có nền, nên không còn gì khác để nhận ra nó — mà `--input` chỉ đạt
|
|
117
|
+
1,18 trên nền trang. Đo 20 tổ hợp (5 bảng màu × sáng/tối × trên nền trang
|
|
118
|
+
và trên card), WCAG 1.4.11 đòi 3:1:
|
|
119
|
+
|
|
120
|
+
--input 1,18 20/20 trượt
|
|
121
|
+
--border 1,03 20/20 trượt
|
|
122
|
+
--foreground 34% 2,23 10/20
|
|
123
|
+
--foreground 44% 3,22 0
|
|
124
|
+
--foreground 46% 3,45 0 <- chọn
|
|
125
|
+
--muted-foreground 4,57 0 (qua, nhưng đậm như chữ phụ)
|
|
126
|
+
|
|
127
|
+
Lấy 46% chứ không 44%: dư 0,22 là quá mỏng, repo từng bác đúng một biên như
|
|
128
|
+
vậy ở mục vòng focus. Và không lấy `--muted-foreground` vì viền đậm ngang
|
|
129
|
+
chữ phụ thì nút outline đọc ra như một cái khung.
|
|
130
|
+
|
|
131
|
+
Pha từ `--foreground` chứ không chốt một nấc xám — cùng cơ chế `styles.css`
|
|
132
|
+
dùng cho `--border`: một khai báo đúng cho cả hai chế độ, và tự ám theo
|
|
133
|
+
bảng màu.
|
|
134
|
+
|
|
135
|
+
`--input` GIỮ NGUYÊN cho ô nhập: ô nhập có nền riêng nên viền của nó không
|
|
136
|
+
phải thứ duy nhất nhận ra control. */
|
|
137
|
+
--button-outline-border: color-mix(in oklab, var(--foreground) 46%, transparent);
|
|
138
|
+
|
|
139
|
+
--button-ghost-bg-hover: var(--accent);
|
|
140
|
+
--button-ghost-fg-hover: var(--accent-foreground);
|
|
141
|
+
|
|
142
|
+
--button-link-fg: var(--primary);
|
|
143
|
+
}
|
package/css/index.css
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
Bộ Design Token của WoodBlock — CSS THUẦN, không phụ thuộc framework nào.
|
|
3
|
+
|
|
4
|
+
@import "@vestow/theme/css/index.css";
|
|
5
|
+
|
|
6
|
+
App dùng Tailwind v4 thì nạp `tailwind.css` thay cho file này: nó nạp lại
|
|
7
|
+
đúng bốn file dưới đây rồi thêm phần ánh xạ sang utility.
|
|
8
|
+
|
|
9
|
+
Thứ tự nạp là BẮT BUỘC, và mỗi lần đảo đều đã có lỗi thật:
|
|
10
|
+
1. primitives — nấc màu gốc, mọi token bên dưới trỏ vào đây.
|
|
11
|
+
2. tokens — token ngữ nghĩa của bảng màu mặc định.
|
|
12
|
+
3. palettes — ghi đè primary + nhóm trung tính theo `data-palette`.
|
|
13
|
+
4. surfaces — ghi đè token bề mặt theo `data-surface`, phải sau palettes
|
|
14
|
+
nếu không bảng màu sẽ đè token kính và mặt kính đục hoàn toàn.
|
|
15
|
+
5. bases — ghi đè HỌ TRUNG TÍNH theo `data-base`, tức chỉ `--tint-hue`
|
|
16
|
+
và `--tint-scale`. Phải sau palettes vì bảng màu cũng khai
|
|
17
|
+
hai token đó; cùng cái bẫy của (4).
|
|
18
|
+
6. menus — ghi đè highlight của mục menu theo `data-menu-accent`.
|
|
19
|
+
7. styles — ghi đè bo góc / đường kẻ / độ thoáng theo `data-style`.
|
|
20
|
+
Phải sau palettes vì hai bên khai chung `--radius`,
|
|
21
|
+
`--border`, `--input` ở cùng độ đặc hiệu (0,3,0), nên thứ
|
|
22
|
+
tự nạp mới là thứ quyết định. Cùng cái bẫy của (4).
|
|
23
|
+
|
|
24
|
+
HAI FILE CỐ Ý ĐỨNG NGOÀI danh sách này, và cùng một lý do: chúng chỉ có ích
|
|
25
|
+
cho app thật sự dùng tới, còn `index.css` thì mọi app đều nạp.
|
|
26
|
+
|
|
27
|
+
`charts.css` (trục `data-chart`, chọn bộ màu cho năm chuỗi biểu đồ) nạp riêng
|
|
28
|
+
bằng `@import "@vestow/theme/css/charts.css"`. Đo được **3.084 byte** CSS
|
|
29
|
+
thô — hơn cả `typeset.css`, mà app không có biểu đồ thì không dùng một dòng
|
|
30
|
+
nào. Bỏ qua nó KHÔNG làm gãy gì: biểu đồ vẫn lấy `--chart-*` theo bảng màu
|
|
31
|
+
như trước, chỉ là `data-chart` không còn tác dụng.
|
|
32
|
+
|
|
33
|
+
⚠ Hệ quả phải biết: `themeController` VẪN ghi `data-chart` lên `<html>` dù
|
|
34
|
+
app có nạp file này hay không — controller không đọc được CSS. Gọi
|
|
35
|
+
`setChart('neutral')` trong một app quên `@import` thì thuộc tính hiện ra mà
|
|
36
|
+
màu không đổi, và không có gì báo. App nào phơi ô chọn bộ màu biểu đồ ra giao
|
|
37
|
+
diện thì phải nạp file này.
|
|
38
|
+
|
|
39
|
+
`typeset.css` CỐ Ý ĐỨNG NGOÀI danh sách này — nó là lớp văn xuôi opt-in, nạp
|
|
40
|
+
riêng bằng `@import "@vestow/theme/css/typeset.css"`. Đo được: gộp vào
|
|
41
|
+
đây thì mọi app phải trả **2.703 byte** CSS thô cho một lớp mà hôm nay chỉ
|
|
42
|
+
`vue/apps/kit` dựng ra.
|
|
43
|
+
|
|
44
|
+
`bases.css` thì Ở LẠI: nó chỉ khai hai token mỗi khối nên rẻ, và nó đổi MỌI
|
|
45
|
+
mặt trung tính — nền trang, card, viền, chữ mờ — nên app nào cũng thấy.
|
|
46
|
+
|
|
47
|
+
`styles.css` thì Ở LẠI (1.061 byte). Nó cũng là một trục theme như
|
|
48
|
+
`charts.css`, nên ranh giới ở đây không phải "trục thì vào, lớp thì ra" mà là
|
|
49
|
+
GIÁ trên SỐ NGƯỜI DÙNG: `data-style` đổi bo góc và độ thoáng của MỌI
|
|
50
|
+
component nên app nào cũng thấy, còn `data-chart` chỉ chạm vào biểu đồ.
|
|
51
|
+
========================================================================== */
|
|
52
|
+
|
|
53
|
+
@import "./primitives.css";
|
|
54
|
+
@import "./tokens.css";
|
|
55
|
+
@import "./palettes.css";
|
|
56
|
+
@import "./surfaces.css";
|
|
57
|
+
@import "./bases.css";
|
|
58
|
+
@import "./menus.css";
|
|
59
|
+
@import "./styles.css";
|
|
60
|
+
|
|
61
|
+
/* 8. components — token của RIÊNG từng component, mỗi cái mặc định trỏ vào một
|
|
62
|
+
token ngữ nghĩa ở trên. Phải nạp SAU cả bảy file kia vì nó đọc chúng. */
|
|
63
|
+
@import "./components/button.css";
|
package/css/menus.css
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
Trục HIGHLIGHT CỦA MENU — `data-menu-accent`, trục theme thứ bảy.
|
|
3
|
+
|
|
4
|
+
Trục nhỏ nhất trong bảy: mỗi khối chỉ khai HAI token. Nó đổi cách mục menu
|
|
5
|
+
đang trỏ tới được tô — mục hover, mục đang mở submenu, mục đang giữ tiêu điểm
|
|
6
|
+
bàn phím.
|
|
7
|
+
|
|
8
|
+
VÌ SAO KHÔNG ĐỔI THẲNG `--accent`: token đó còn được Sidebar, ô ngày trong
|
|
9
|
+
Calendar và vài chỗ hover khác đọc. Đổi nó là đổi cả những chỗ không ai xin.
|
|
10
|
+
`tokens.css` vì vậy tách ra `--menu-accent` / `--menu-accent-foreground`, mặc
|
|
11
|
+
định trỏ vào `--accent` nên không dịch một pixel nào cho tới khi trục này bật.
|
|
12
|
+
Người đọc hai token đó là `menu-styles.ts` của `src/variants` — bốn
|
|
13
|
+
chỗ, dùng chung cho DropdownMenu, ContextMenu, Menubar và Select.
|
|
14
|
+
|
|
15
|
+
`subtle` là mặc định nên KHÔNG có khối — cùng lẽ với `hyperion` / `solid` /
|
|
16
|
+
`default` / `theme` / `slate`.
|
|
17
|
+
|
|
18
|
+
Tương phản: `solid` dùng cặp `--primary` / `--primary-foreground`, đã nằm
|
|
19
|
+
trong 150 tổ hợp đo ở mục "Số đo sau khi neo" (thấp nhất 4,56). `muted` dùng
|
|
20
|
+
`--muted` với `--foreground`, tức mặt nền nhạt nhất với chữ đậm nhất — không
|
|
21
|
+
có cách nào để nó trượt.
|
|
22
|
+
|
|
23
|
+
ĐỘ ĐẶC HIỆU: attribute lặp ba lần. `tokens.css` khai hai token này ở `:root`
|
|
24
|
+
và `.dark`; khối `.dark` là (0,1,0) ngang với một attribute trần, nên ở chế độ
|
|
25
|
+
tối một `[data-menu-accent]` trần sẽ hoà rồi thua theo thứ tự nạp. Cùng cái
|
|
26
|
+
bẫy của `styles.css`, `charts.css` và `bases.css`.
|
|
27
|
+
========================================================================== */
|
|
28
|
+
|
|
29
|
+
[data-menu-accent="solid"][data-menu-accent="solid"][data-menu-accent="solid"] {
|
|
30
|
+
--menu-accent: var(--primary);
|
|
31
|
+
--menu-accent-foreground: var(--primary-foreground);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Bản ĐẬM HƠN của `subtle`, không phải một màu khác.
|
|
35
|
+
|
|
36
|
+
Bản đầu của khối này viết `var(--muted)` và hoá ra là một no-op: đo được
|
|
37
|
+
`--muted` và `--accent` TRÙNG GIÁ TRỊ ở cả năm bảng màu (cùng nấc 100 của họ
|
|
38
|
+
trung tính). Một tuỳ chọn không đổi gì thì tệ hơn là không có tuỳ chọn — nó
|
|
39
|
+
bắt người dùng thử rồi tự hỏi mình bấm hụt chỗ nào.
|
|
40
|
+
|
|
41
|
+
Pha từ `--foreground` chứ không chốt một nấc xám, đúng cách `styles.css` làm
|
|
42
|
+
đường kẻ của style phẳng: một khai báo đúng cho cả hai chế độ, vì nền tối thì
|
|
43
|
+
`--foreground` gần trắng nên ra vệt sáng mờ. */
|
|
44
|
+
[data-menu-accent="muted"][data-menu-accent="muted"][data-menu-accent="muted"] {
|
|
45
|
+
--menu-accent: color-mix(in oklab, var(--foreground) 12%, transparent);
|
|
46
|
+
--menu-accent-foreground: var(--foreground);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* =============================================================================
|
|
50
|
+
Trục MÀU CỦA MẶT MENU — `data-menu-color`, trục theme thứ tám.
|
|
51
|
+
|
|
52
|
+
`inverted` lật tấm menu sang phía đối diện của chế độ đang bật: menu tối trên
|
|
53
|
+
giao diện sáng, menu sáng trên giao diện tối.
|
|
54
|
+
|
|
55
|
+
KHÔNG ĐẺ TOKEN MỚI, và đây là chỗ khác `--menu-accent` ở đầu file. Token đó
|
|
56
|
+
buộc phải tách vì `--accent` bị đọc bởi Sidebar và Calendar — những phần tử
|
|
57
|
+
NGOÀI menu. Ở đây thì phạm vi đã tự khoanh bằng cây DOM: khối này đặt lại
|
|
58
|
+
`--popover` và bạn bè NGAY TRÊN phần tử `.ui-menu`, nên Popover và Tooltip
|
|
59
|
+
không dịch một pixel nào.
|
|
60
|
+
|
|
61
|
+
ĐỘ ĐẶC HIỆU: KHÔNG phải lặp attribute ba lần như `styles.css` / `charts.css`
|
|
62
|
+
/ `bases.css`. Ba file đó khai lại token trên `:root`, tức đấu tay đôi với
|
|
63
|
+
khối `.dark` của `tokens.css`; còn ở đây khai trên một phần tử CON, mà khai
|
|
64
|
+
báo trực tiếp luôn thắng giá trị thừa kế bất kể độ đặc hiệu.
|
|
65
|
+
|
|
66
|
+
Giá trị lấy nguyên từ khối đối diện trong `tokens.css`, không nghĩ nấc mới —
|
|
67
|
+
nên cặp chữ/nền của menu lật đúng là cặp đã nằm trong 150 tổ hợp đã đo.
|
|
68
|
+
|
|
69
|
+
`--foreground` phải lật theo dù menu không dùng nó trực tiếp: `menu-accent`
|
|
70
|
+
ở giá trị `muted` pha từ chính nó, giữ nguyên là mục đang trỏ tới bị tô bằng
|
|
71
|
+
sắc của mặt nền BÊN NGOÀI menu.
|
|
72
|
+
|
|
73
|
+
`--border` thì KHÔNG chép: bản tối trong `tokens.css` là trắng 12% trong
|
|
74
|
+
suốt, mà một tấm menu tối nằm trên trang sáng thì viền đó tan mất. Pha từ
|
|
75
|
+
chính chữ của menu, đúng cách `styles.css` dựng đường kẻ của style phẳng. */
|
|
76
|
+
:root:not(.dark)[data-menu-color="inverted"] .ui-menu,
|
|
77
|
+
.light [data-menu-color="inverted"] .ui-menu {
|
|
78
|
+
--popover: oklch(from var(--color-slate-900) l var(--tint-c-900) var(--tint-hue));
|
|
79
|
+
--popover-foreground: oklch(from var(--color-slate-100) l var(--tint-c-100) var(--tint-hue));
|
|
80
|
+
--foreground: oklch(from var(--color-slate-100) l var(--tint-c-100) var(--tint-hue));
|
|
81
|
+
--muted-foreground: oklch(from var(--color-slate-400) l var(--tint-c-400) var(--tint-hue));
|
|
82
|
+
--accent: oklch(from var(--color-slate-800) l var(--tint-c-800) var(--tint-hue));
|
|
83
|
+
--accent-foreground: oklch(from var(--color-slate-100) l var(--tint-c-100) var(--tint-hue));
|
|
84
|
+
--menu-surface: oklch(from var(--color-slate-900) l var(--tint-c-900) var(--tint-hue));
|
|
85
|
+
--border: color-mix(in oklab, var(--popover-foreground) 16%, transparent);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
:root.dark[data-menu-color="inverted"] .ui-menu,
|
|
89
|
+
.dark [data-menu-color="inverted"] .ui-menu {
|
|
90
|
+
--popover: var(--color-white);
|
|
91
|
+
--popover-foreground: oklch(from var(--color-slate-900) l var(--tint-c-900) var(--tint-hue));
|
|
92
|
+
--foreground: oklch(from var(--color-slate-900) l var(--tint-c-900) var(--tint-hue));
|
|
93
|
+
--muted-foreground: oklch(from var(--color-slate-500) l var(--tint-c-500) var(--tint-hue));
|
|
94
|
+
--accent: oklch(from var(--color-slate-100) l var(--tint-c-100) var(--tint-hue));
|
|
95
|
+
--accent-foreground: oklch(from var(--color-slate-800) l var(--tint-c-800) var(--tint-hue));
|
|
96
|
+
--menu-surface: var(--color-white);
|
|
97
|
+
--border: color-mix(in oklab, var(--popover-foreground) 16%, transparent);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* =============================================================================
|
|
101
|
+
Trục VẬT LIỆU CỦA MẶT MENU — `data-menu-appearance`, trục theme thứ chín.
|
|
102
|
+
|
|
103
|
+
TỰ LOẠI MÌNH RA KHI THEME KÍNH ĐANG BẬT. Đó là điều tài liệu Liquid Glass của
|
|
104
|
+
Apple dặn thẳng: đừng chồng kính lên kính. Ở `data-surface="glass"` thì
|
|
105
|
+
`--popover` đã trong mờ và rule `[class~="bg-menu-surface"]` bên `surfaces.css`
|
|
106
|
+
đã gắn `backdrop-filter` cho đúng tấm menu này rồi — bật thêm ở đây là hai lớp
|
|
107
|
+
làm mờ chồng nhau, mà `backdrop-filter` không cộng dồn nên chỉ tổ đè mất bộ
|
|
108
|
+
lọc của theme kính.
|
|
109
|
+
|
|
110
|
+
Trộn từ `--popover` chứ không từ `--menu-surface`: một custom property tham
|
|
111
|
+
chiếu CHÍNH NÓ trên cùng phần tử là vòng lặp, CSS coi cả hai là không hợp lệ.
|
|
112
|
+
Đọc `--popover` thì vừa tránh được vòng lặp vừa tự ăn theo trục `inverted` ở
|
|
113
|
+
trên — hai trục ghép được, tấm menu lật màu vẫn trong mờ đúng nền của nó.
|
|
114
|
+
|
|
115
|
+
Độ đục 82%: dưới mức đó thì chữ mờ trong menu bắt đầu ăn màu của thứ nằm sau,
|
|
116
|
+
đúng ngưỡng mà mục "Tương phản trên nền kính" ở CLAUDE.md đã đo cho `--card`. */
|
|
117
|
+
:root:not([data-surface="glass"])[data-menu-appearance="translucent"] .ui-menu {
|
|
118
|
+
--menu-surface: color-mix(in oklab, var(--popover) 82%, transparent);
|
|
119
|
+
|
|
120
|
+
/* CHỮ MỜ PHẢI ĐẬM LÊN, nếu không trục này trượt AA.
|
|
121
|
+
|
|
122
|
+
Số đo trước khi sửa, lấy ở CẬN — tấm menu trong mờ nằm trên nội dung bất
|
|
123
|
+
kỳ nên phải kẹp giữa nền trắng thuần và đen thuần, không đo trên nền trang
|
|
124
|
+
tiện tay nhất:
|
|
125
|
+
|
|
126
|
+
| tổ hợp | chữ chính | chữ mờ |
|
|
127
|
+
| menu sáng (82%) | 11,68 | **3,12** |
|
|
128
|
+
| menu tối (82%) | 9,29 | **3,89** |
|
|
129
|
+
|
|
130
|
+
Hai đường chữa, đo cả hai rồi mới chọn:
|
|
131
|
+
|
|
132
|
+
| cách | chữ mờ |
|
|
133
|
+
| nâng độ đục 82 → 86% | 4,49 — **trượt** |
|
|
134
|
+
| nâng độ đục 82 → 90% | 5,14 — qua, nhưng hết trong |
|
|
135
|
+
| pha 68% về phía chữ chính | 4,19 — **vẫn trượt** |
|
|
136
|
+
| pha 78% về phía chữ chính | **5,48**, giữ nguyên 82% |
|
|
137
|
+
|
|
138
|
+
Chọn cách sau, đúng tiền lệ của mục "Tương phản trên nền kính": nâng độ đục
|
|
139
|
+
là hy sinh chính thứ trục này sinh ra để làm, còn màu chữ thì còn chỗ xoay.
|
|
140
|
+
Ở 5,48 chữ mờ vẫn nhạt hơn chữ chính rất xa (9,29–11,68) nên vẫn đọc ra là
|
|
141
|
+
"mờ".
|
|
142
|
+
|
|
143
|
+
Đừng chọn tỉ lệ bằng một phép quét viết tay trong JS: phép quét đó trộn
|
|
144
|
+
trong sRGB còn `color-mix(in oklab, …)` thì không, nên nó cho 4,57 ở mức
|
|
145
|
+
68% trong khi giá trị THẬT là 4,19. Đặt số vào CSS rồi đọc lại computed
|
|
146
|
+
style mới là phép đo đúng.
|
|
147
|
+
Pha từ `--popover-foreground` và `--popover`, KHÔNG pha từ chính
|
|
148
|
+
`--muted-foreground`: nó được khai ngay trên phần tử này, nên đọc lại chính
|
|
149
|
+
nó là vòng lặp và CSS coi cả hai khai báo là không hợp lệ — cùng cái bẫy đã
|
|
150
|
+
ghi cho `--menu-surface` ngay dưới đây. */
|
|
151
|
+
--muted-foreground: color-mix(in oklab, var(--popover-foreground) 78%, var(--popover));
|
|
152
|
+
|
|
153
|
+
-webkit-backdrop-filter: blur(12px) saturate(1.5);
|
|
154
|
+
backdrop-filter: blur(12px) saturate(1.5);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Cùng lý do với khối kính: người dùng tắt hiệu ứng trong suốt thì menu phải
|
|
158
|
+
đục hẳn, không chỉ bớt mờ. */
|
|
159
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
160
|
+
:root[data-menu-appearance="translucent"] .ui-menu {
|
|
161
|
+
--menu-surface: var(--popover);
|
|
162
|
+
-webkit-backdrop-filter: none;
|
|
163
|
+
backdrop-filter: none;
|
|
164
|
+
}
|
|
165
|
+
}
|
package/css/palettes.css
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/* =============================================================================
|
|
2
|
+
Bảng màu thay thế, chép từ mockup "Vue3 Shadcn UI mockups".
|
|
3
|
+
|
|
4
|
+
Mỗi bảng chỉ khai lại những token nó đổi; phần còn lại vẫn kế thừa từ
|
|
5
|
+
tokens.css. Chọn bảng bằng `usePalette()` — nó đặt `data-palette` lên
|
|
6
|
+
thẻ <html>.
|
|
7
|
+
|
|
8
|
+
Selector khoá theo `.dark` là bắt buộc: nếu để `[data-palette="x"]` trần
|
|
9
|
+
thì file này nạp sau tokens.css sẽ đè luôn cả khối `.dark`, và bản tối
|
|
10
|
+
quay về màu của bản sáng.
|
|
11
|
+
========================================================================== */
|
|
12
|
+
|
|
13
|
+
/* PHẠM VI: bảng màu chỉ đổi --primary và bộ trung tính (background, card,
|
|
14
|
+
secondary, muted, accent, border, sidebar…).
|
|
15
|
+
|
|
16
|
+
KHÔNG đụng tới --destructive / --success / --warning / --info. Hai lý do:
|
|
17
|
+
- Eclipse từng đặt chroma 0 cho chúng -> thông báo lỗi thành màu xám, mất
|
|
18
|
+
hết ý nghĩa. Bảng màu đơn sắc là nói về primary, không phải về trạng thái.
|
|
19
|
+
- Ba bảng kia ghi đè bằng giá trị riêng, vô hiệu hoá luôn phần chỉnh tương
|
|
20
|
+
phản làm ở tokens.css (--success sáng từng chỉ đạt 3.57:1).
|
|
21
|
+
|
|
22
|
+
Cũng không khai --code-* ở đây: xem ghi chú trong CLAUDE.md. */
|
|
23
|
+
|
|
24
|
+
/* MỘT HỌ TRUNG TÍNH cho mỗi bảng, ở CẢ khối sáng lẫn khối tối:
|
|
25
|
+
solar -> stone, nebula -> zinc, aurora -> mist, eclipse -> neutral.
|
|
26
|
+
Chỉ --primary / --accent / --sidebar-accent / --chart-* được ra khỏi họ đó.
|
|
27
|
+
|
|
28
|
+
Ở chroma 0,006 thì góc hue gần như vô nghĩa về mặt số học nên rất dễ mượn nhầm
|
|
29
|
+
họ mà không ai thấy: khối tối của nebula từng lấy gray + mauve, của aurora từng
|
|
30
|
+
lấy gray, và card lệch tông so với nền tới ΔE 0,03 (bốn ca đúng đều ≤ 0,002).
|
|
31
|
+
check-tokens.mjs KHÔNG bắt được — nó chỉ hỏi tên token, không hỏi họ màu. */
|
|
32
|
+
|
|
33
|
+
/* --- Solar: Cam nóng trên nền than ấm --- */
|
|
34
|
+
|
|
35
|
+
:root:not(.dark)[data-palette="solar"],
|
|
36
|
+
.light[data-palette="solar"] {
|
|
37
|
+
--tint-hue: 56.043;
|
|
38
|
+
--background:oklch(from var(--color-stone-50) l var(--tint-c-50) var(--tint-hue));
|
|
39
|
+
--foreground:oklch(from var(--color-stone-900) l var(--tint-c-900) var(--tint-hue));
|
|
40
|
+
--card:var(--color-white);
|
|
41
|
+
--popover:var(--color-white);
|
|
42
|
+
--primary:var(--color-orange-700);
|
|
43
|
+
--primary-foreground:oklch(from var(--color-stone-50) l var(--tint-c-50) var(--tint-hue));
|
|
44
|
+
--secondary:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
45
|
+
--secondary-foreground:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
46
|
+
--muted:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
47
|
+
--muted-foreground:oklch(from var(--color-stone-500) l var(--tint-c-500) var(--tint-hue));
|
|
48
|
+
--accent:var(--color-orange-100);
|
|
49
|
+
--accent-foreground:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
50
|
+
--border:oklch(from var(--color-stone-200) l var(--tint-c-200) var(--tint-hue));
|
|
51
|
+
--input:oklch(from var(--color-stone-200) l var(--tint-c-200) var(--tint-hue));
|
|
52
|
+
--ring:var(--color-orange-700);
|
|
53
|
+
--sidebar:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
54
|
+
--sidebar-accent:oklch(from var(--color-stone-200) l var(--tint-c-200) var(--tint-hue));
|
|
55
|
+
--radius:0.625rem;
|
|
56
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
57
|
+
Khoảng cách xám nhỏ nhất 0,048; thấp nhất 3,2:1 trên mặt card. */
|
|
58
|
+
--chart-1: var(--color-orange-700);
|
|
59
|
+
--chart-2: var(--color-yellow-800);
|
|
60
|
+
--chart-3: var(--color-rose-500);
|
|
61
|
+
--chart-4: var(--color-red-900);
|
|
62
|
+
--chart-5: var(--color-amber-600);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
:root.dark[data-palette="solar"],
|
|
66
|
+
.dark[data-palette="solar"] {
|
|
67
|
+
--tint-hue: 56.043;
|
|
68
|
+
/* Hue cam-vàng cũng hẹp ở vùng tối: nấc 950 trần 0,045 nên kẹp ở 85%. */
|
|
69
|
+
--tint-c-950: calc(0.038 * var(--tint-scale));
|
|
70
|
+
--background:oklch(from var(--color-stone-950) l var(--tint-c-950) var(--tint-hue));
|
|
71
|
+
--foreground:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
72
|
+
--card:oklch(from var(--color-stone-900) l var(--tint-c-900) var(--tint-hue));
|
|
73
|
+
--popover:oklch(from var(--color-stone-900) l var(--tint-c-900) var(--tint-hue));
|
|
74
|
+
--primary:var(--color-orange-700);
|
|
75
|
+
--primary-foreground:oklch(from var(--color-stone-50) l var(--tint-c-50) var(--tint-hue));
|
|
76
|
+
--secondary:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
77
|
+
--secondary-foreground:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
78
|
+
--muted:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
79
|
+
--muted-foreground:oklch(from var(--color-stone-400) l var(--tint-c-400) var(--tint-hue));
|
|
80
|
+
--accent:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
81
|
+
--accent-foreground:oklch(from var(--color-stone-100) l var(--tint-c-100) var(--tint-hue));
|
|
82
|
+
--border:color-mix(in oklab, var(--color-white) 13%, transparent);
|
|
83
|
+
--input:color-mix(in oklab, var(--color-white) 17%, transparent);
|
|
84
|
+
--ring:var(--color-orange-700);
|
|
85
|
+
--sidebar:oklch(from var(--color-stone-900) l var(--tint-c-900) var(--tint-hue));
|
|
86
|
+
--sidebar-accent:oklch(from var(--color-stone-800) l var(--tint-c-800) var(--tint-hue));
|
|
87
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
88
|
+
Khoảng cách xám nhỏ nhất 0,072; thấp nhất 3,67:1 trên mặt card. */
|
|
89
|
+
--chart-1: var(--color-orange-600);
|
|
90
|
+
--chart-2: var(--color-yellow-400);
|
|
91
|
+
--chart-3: var(--color-rose-400);
|
|
92
|
+
--chart-4: var(--color-red-600);
|
|
93
|
+
--chart-5: var(--color-amber-500);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* --- Nebula: Tím điện, nền trung tính lạnh --- */
|
|
97
|
+
|
|
98
|
+
:root:not(.dark)[data-palette="nebula"],
|
|
99
|
+
.light[data-palette="nebula"] {
|
|
100
|
+
--tint-hue: 285.885;
|
|
101
|
+
--background:var(--color-white);
|
|
102
|
+
--foreground:oklch(from var(--color-zinc-900) l var(--tint-c-900) var(--tint-hue));
|
|
103
|
+
--card:var(--color-white);
|
|
104
|
+
--popover:var(--color-white);
|
|
105
|
+
--primary:var(--color-purple-600);
|
|
106
|
+
--primary-foreground:oklch(from var(--color-zinc-50) l var(--tint-c-50) var(--tint-hue));
|
|
107
|
+
--secondary:oklch(from var(--color-zinc-100) l var(--tint-c-100) var(--tint-hue));
|
|
108
|
+
--secondary-foreground:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
109
|
+
--muted:oklch(from var(--color-zinc-100) l var(--tint-c-100) var(--tint-hue));
|
|
110
|
+
--muted-foreground:oklch(from var(--color-zinc-500) l var(--tint-c-500) var(--tint-hue));
|
|
111
|
+
--accent:var(--color-purple-100);
|
|
112
|
+
--accent-foreground:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
113
|
+
--border:oklch(from var(--color-zinc-200) l var(--tint-c-200) var(--tint-hue));
|
|
114
|
+
--input:oklch(from var(--color-zinc-200) l var(--tint-c-200) var(--tint-hue));
|
|
115
|
+
--ring:var(--color-purple-600);
|
|
116
|
+
--sidebar:oklch(from var(--color-zinc-50) l var(--tint-c-50) var(--tint-hue));
|
|
117
|
+
--sidebar-accent:var(--color-violet-100);
|
|
118
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
119
|
+
Khoảng cách xám nhỏ nhất 0,043; thấp nhất 3,13:1 trên mặt card. */
|
|
120
|
+
--chart-1: var(--color-purple-600);
|
|
121
|
+
--chart-2: var(--color-pink-500);
|
|
122
|
+
--chart-3: var(--color-indigo-400);
|
|
123
|
+
--chart-4: var(--color-fuchsia-800);
|
|
124
|
+
--chart-5: var(--color-violet-500);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
:root.dark[data-palette="nebula"],
|
|
128
|
+
.dark[data-palette="nebula"] {
|
|
129
|
+
--tint-hue: 285.885;
|
|
130
|
+
--background:oklch(from var(--color-zinc-950) l var(--tint-c-950) var(--tint-hue));
|
|
131
|
+
--foreground:oklch(from var(--color-zinc-100) l var(--tint-c-100) var(--tint-hue));
|
|
132
|
+
--card:oklch(from var(--color-zinc-900) l var(--tint-c-900) var(--tint-hue));
|
|
133
|
+
--popover:oklch(from var(--color-zinc-900) l var(--tint-c-900) var(--tint-hue));
|
|
134
|
+
--primary:var(--color-purple-600);
|
|
135
|
+
--primary-foreground:oklch(from var(--color-zinc-50) l var(--tint-c-50) var(--tint-hue));
|
|
136
|
+
--secondary:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
137
|
+
--secondary-foreground:oklch(from var(--color-zinc-100) l var(--tint-c-100) var(--tint-hue));
|
|
138
|
+
--muted:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
139
|
+
--muted-foreground:oklch(from var(--color-zinc-400) l var(--tint-c-400) var(--tint-hue));
|
|
140
|
+
--accent:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
141
|
+
--accent-foreground:oklch(from var(--color-zinc-100) l var(--tint-c-100) var(--tint-hue));
|
|
142
|
+
--border:color-mix(in oklab, var(--color-white) 13%, transparent);
|
|
143
|
+
--input:color-mix(in oklab, var(--color-white) 17%, transparent);
|
|
144
|
+
--ring:var(--color-purple-600);
|
|
145
|
+
--sidebar:oklch(from var(--color-zinc-900) l var(--tint-c-900) var(--tint-hue));
|
|
146
|
+
--sidebar-accent:oklch(from var(--color-zinc-800) l var(--tint-c-800) var(--tint-hue));
|
|
147
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
148
|
+
Khoảng cách xám nhỏ nhất 0,041; thấp nhất 4,31:1 trên mặt card. */
|
|
149
|
+
--chart-1: var(--color-purple-500);
|
|
150
|
+
--chart-2: var(--color-pink-300);
|
|
151
|
+
--chart-3: var(--color-indigo-300);
|
|
152
|
+
--chart-4: var(--color-fuchsia-500);
|
|
153
|
+
--chart-5: var(--color-violet-400);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* --- Aurora: Xanh mòng két trên navy sâu --- */
|
|
157
|
+
|
|
158
|
+
:root:not(.dark)[data-palette="aurora"],
|
|
159
|
+
.light[data-palette="aurora"] {
|
|
160
|
+
--tint-hue: 223.9;
|
|
161
|
+
--background:var(--color-white);
|
|
162
|
+
--foreground:oklch(from var(--color-mist-900) l var(--tint-c-900) var(--tint-hue));
|
|
163
|
+
--card:var(--color-white);
|
|
164
|
+
--popover:var(--color-white);
|
|
165
|
+
--primary:var(--color-teal-700);
|
|
166
|
+
--primary-foreground:oklch(from var(--color-mist-50) l var(--tint-c-50) var(--tint-hue));
|
|
167
|
+
--secondary:oklch(from var(--color-mist-100) l var(--tint-c-100) var(--tint-hue));
|
|
168
|
+
--secondary-foreground:oklch(from var(--color-mist-800) l var(--tint-c-800) var(--tint-hue));
|
|
169
|
+
--muted:oklch(from var(--color-mist-100) l var(--tint-c-100) var(--tint-hue));
|
|
170
|
+
--muted-foreground:oklch(from var(--color-mist-500) l var(--tint-c-500) var(--tint-hue));
|
|
171
|
+
--accent:var(--color-sky-100);
|
|
172
|
+
--accent-foreground:oklch(from var(--color-mist-800) l var(--tint-c-800) var(--tint-hue));
|
|
173
|
+
--border:oklch(from var(--color-mist-200) l var(--tint-c-200) var(--tint-hue));
|
|
174
|
+
--input:oklch(from var(--color-mist-200) l var(--tint-c-200) var(--tint-hue));
|
|
175
|
+
--ring:var(--color-teal-700);
|
|
176
|
+
--sidebar:oklch(from var(--color-mist-50) l var(--tint-c-50) var(--tint-hue));
|
|
177
|
+
--sidebar-accent:oklch(from var(--color-mist-200) l var(--tint-c-200) var(--tint-hue));
|
|
178
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
179
|
+
Khoảng cách xám nhỏ nhất 0,035; thấp nhất 3,22:1 trên mặt card. */
|
|
180
|
+
--chart-1: var(--color-teal-700);
|
|
181
|
+
--chart-2: var(--color-sky-900);
|
|
182
|
+
--chart-3: var(--color-green-600);
|
|
183
|
+
--chart-4: var(--color-cyan-800);
|
|
184
|
+
--chart-5: var(--color-emerald-600);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
:root.dark[data-palette="aurora"],
|
|
188
|
+
.dark[data-palette="aurora"] {
|
|
189
|
+
--tint-hue: 223.9;
|
|
190
|
+
/* Hue teal-lam nằm đúng đáy gamut sRGB ở vùng tối: trần chỉ 0,033 (950)
|
|
191
|
+
và 0,043 (900), nên hai nấc này kẹp ở 85% trần thay vì theo slate. */
|
|
192
|
+
--tint-c-900: calc(0.037 * var(--tint-scale));
|
|
193
|
+
--tint-c-950: calc(0.028 * var(--tint-scale));
|
|
194
|
+
--background:oklch(from var(--color-mist-950) l var(--tint-c-950) var(--tint-hue));
|
|
195
|
+
--foreground:oklch(from var(--color-mist-100) l var(--tint-c-100) var(--tint-hue));
|
|
196
|
+
--card:oklch(from var(--color-mist-900) l var(--tint-c-900) var(--tint-hue));
|
|
197
|
+
--popover:oklch(from var(--color-mist-900) l var(--tint-c-900) var(--tint-hue));
|
|
198
|
+
--primary:var(--color-teal-700);
|
|
199
|
+
--primary-foreground:oklch(from var(--color-mist-50) l var(--tint-c-50) var(--tint-hue));
|
|
200
|
+
--secondary:oklch(from var(--color-mist-800) l var(--tint-c-800) var(--tint-hue));
|
|
201
|
+
--secondary-foreground:oklch(from var(--color-mist-100) l var(--tint-c-100) var(--tint-hue));
|
|
202
|
+
--muted:oklch(from var(--color-mist-800) l var(--tint-c-800) var(--tint-hue));
|
|
203
|
+
--muted-foreground:oklch(from var(--color-mist-400) l var(--tint-c-400) var(--tint-hue));
|
|
204
|
+
--accent:var(--color-cyan-950);
|
|
205
|
+
--accent-foreground:oklch(from var(--color-mist-100) l var(--tint-c-100) var(--tint-hue));
|
|
206
|
+
--border:color-mix(in oklab, var(--color-white) 13%, transparent);
|
|
207
|
+
--input:color-mix(in oklab, var(--color-white) 17%, transparent);
|
|
208
|
+
--ring:var(--color-teal-700);
|
|
209
|
+
--sidebar:oklch(from var(--color-mist-900) l var(--tint-c-900) var(--tint-hue));
|
|
210
|
+
--sidebar-accent:var(--color-cyan-950);
|
|
211
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
212
|
+
Khoảng cách xám nhỏ nhất 0,074; thấp nhất 3,59:1 trên mặt card. */
|
|
213
|
+
--chart-1: var(--color-teal-600);
|
|
214
|
+
--chart-2: var(--color-sky-300);
|
|
215
|
+
--chart-3: var(--color-green-700);
|
|
216
|
+
--chart-4: var(--color-cyan-500);
|
|
217
|
+
--chart-5: var(--color-emerald-400);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* Eclipse = default theme của shadcn, chép nguyên. Cả chín giá trị xám shadcn
|
|
221
|
+
dùng đều trùng KHÍT một nấc của thang `neutral` trong Tailwind (0.145 -> 950,
|
|
222
|
+
0.205 -> 900, 0.269 -> 800, 0.371 -> 700, 0.556 -> 500, 0.708 -> 400,
|
|
223
|
+
0.922 -> 200, 0.97 -> 100, 0.985 -> 50) nên viết bằng token là khớp tuyệt đối,
|
|
224
|
+
không phải chép số. */
|
|
225
|
+
/* --- Eclipse: Đen trắng thuần, chroma bằng 0 --- */
|
|
226
|
+
|
|
227
|
+
:root:not(.dark)[data-palette="eclipse"],
|
|
228
|
+
.light[data-palette="eclipse"] {
|
|
229
|
+
/* Đơn sắc: tắt trục ám màu, xem --tint-scale trong tokens.css. */
|
|
230
|
+
--tint-scale: 0;
|
|
231
|
+
--background:var(--color-white);
|
|
232
|
+
--foreground:var(--color-black);
|
|
233
|
+
--card:var(--color-white);
|
|
234
|
+
--card-foreground:var(--color-black);
|
|
235
|
+
--popover:var(--color-white);
|
|
236
|
+
--popover-foreground:var(--color-black);
|
|
237
|
+
--primary:var(--color-black);
|
|
238
|
+
--primary-foreground:var(--color-neutral-50);
|
|
239
|
+
--secondary:var(--color-neutral-100);
|
|
240
|
+
--secondary-foreground:var(--color-neutral-900);
|
|
241
|
+
--muted:var(--color-neutral-100);
|
|
242
|
+
--muted-foreground:var(--color-neutral-500);
|
|
243
|
+
--accent:var(--color-neutral-100);
|
|
244
|
+
--accent-foreground:var(--color-neutral-900);
|
|
245
|
+
--border:var(--color-neutral-200);
|
|
246
|
+
--input:var(--color-neutral-200);
|
|
247
|
+
/* neutral-400 chỉ đạt 2.58:1 trên nền card — chỉ báo focus cần tối thiểu
|
|
248
|
+
3:1 (WCAG 2.4.11). neutral-500 lên 4.68 mà vẫn đơn sắc. Bốn bảng kia
|
|
249
|
+
dùng primary có màu nên không dính; Eclipse lấy chính sắc xám làm ring. */
|
|
250
|
+
--ring:var(--color-neutral-500);
|
|
251
|
+
--sidebar:var(--color-neutral-50);
|
|
252
|
+
--sidebar-accent:var(--color-neutral-100);
|
|
253
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
254
|
+
Khoảng cách xám nhỏ nhất 0,016; thấp nhất 4,74:1 trên mặt card. */
|
|
255
|
+
--chart-1: var(--color-neutral-800);
|
|
256
|
+
--chart-2: var(--color-neutral-500);
|
|
257
|
+
--chart-3: var(--color-neutral-600);
|
|
258
|
+
--chart-4: var(--color-neutral-700);
|
|
259
|
+
--chart-5: var(--color-neutral-950);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
:root.dark[data-palette="eclipse"],
|
|
263
|
+
.dark[data-palette="eclipse"] {
|
|
264
|
+
/* Đơn sắc: tắt trục ám màu, xem --tint-scale trong tokens.css. */
|
|
265
|
+
--tint-scale: 0;
|
|
266
|
+
--background:var(--color-neutral-950);
|
|
267
|
+
--foreground:var(--color-neutral-50);
|
|
268
|
+
--card:var(--color-neutral-900);
|
|
269
|
+
--card-foreground:var(--color-neutral-50);
|
|
270
|
+
--popover:var(--color-neutral-900);
|
|
271
|
+
--popover-foreground:var(--color-neutral-50);
|
|
272
|
+
--primary:var(--color-neutral-200);
|
|
273
|
+
--primary-foreground:var(--color-neutral-900);
|
|
274
|
+
--secondary:var(--color-neutral-800);
|
|
275
|
+
--secondary-foreground:var(--color-neutral-50);
|
|
276
|
+
--muted:var(--color-neutral-800);
|
|
277
|
+
--muted-foreground:var(--color-neutral-400);
|
|
278
|
+
--accent:var(--color-neutral-700);
|
|
279
|
+
--accent-foreground:var(--color-neutral-50);
|
|
280
|
+
--border:color-mix(in oklab, var(--color-white) 10%, transparent);
|
|
281
|
+
--input:color-mix(in oklab, var(--color-white) 15%, transparent);
|
|
282
|
+
--ring:var(--color-neutral-500);
|
|
283
|
+
--sidebar:var(--color-neutral-900);
|
|
284
|
+
--sidebar-accent:var(--color-neutral-800);
|
|
285
|
+
/* Màu chuỗi biểu đồ, lấy các họ lân cận sắc của --primary.
|
|
286
|
+
Khoảng cách xám nhỏ nhất 0,125; thấp nhất 3,78:1 trên mặt card. */
|
|
287
|
+
--chart-1: var(--color-neutral-300);
|
|
288
|
+
--chart-2: var(--color-neutral-100);
|
|
289
|
+
--chart-3: var(--color-neutral-200);
|
|
290
|
+
--chart-4: var(--color-neutral-400);
|
|
291
|
+
--chart-5: var(--color-neutral-500);
|
|
292
|
+
}
|