@comitor/ui 0.2.1 → 0.3.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.
Files changed (90) hide show
  1. package/README.md +236 -30
  2. package/dist/chart/chart-colors.d.ts +56 -0
  3. package/dist/chart/chart-colors.js +21 -0
  4. package/dist/chart/chart-colors.js.map +1 -0
  5. package/dist/chart/chart.d.ts +40 -0
  6. package/dist/chart/chart.js.map +1 -1
  7. package/dist/chart/comitor-chart.d.ts +21 -43
  8. package/dist/chart/comitor-chart.js +13 -24
  9. package/dist/chart/comitor-chart.js.map +1 -1
  10. package/dist/chart/index.d.ts +2 -1
  11. package/dist/chart/index.js +1 -0
  12. package/dist/chart/index.js.map +1 -1
  13. package/dist/components/composite/data-table-constants.d.ts +40 -0
  14. package/dist/components/composite/data-table-constants.js +13 -0
  15. package/dist/components/composite/data-table-constants.js.map +1 -0
  16. package/dist/components/composite/data-table.d.ts +2 -27
  17. package/dist/components/composite/data-table.js +1 -10
  18. package/dist/components/composite/data-table.js.map +1 -1
  19. package/dist/components/composite/date-picker-constants.d.ts +21 -0
  20. package/dist/components/composite/date-picker-constants.js +39 -0
  21. package/dist/components/composite/date-picker-constants.js.map +1 -0
  22. package/dist/components/composite/date-picker.d.ts +2 -18
  23. package/dist/components/composite/date-picker.js +6 -48
  24. package/dist/components/composite/date-picker.js.map +1 -1
  25. package/dist/components/composite/form-field-constants.d.ts +26 -0
  26. package/dist/components/composite/form-field-constants.js +13 -0
  27. package/dist/components/composite/form-field-constants.js.map +1 -0
  28. package/dist/components/composite/form-field.d.ts +1 -13
  29. package/dist/components/composite/form-field.js +1 -11
  30. package/dist/components/composite/form-field.js.map +1 -1
  31. package/dist/components/composite/search-filter-bar-constants.d.ts +52 -0
  32. package/dist/components/composite/search-filter-bar-constants.js +18 -0
  33. package/dist/components/composite/search-filter-bar-constants.js.map +1 -0
  34. package/dist/components/composite/search-filter-bar.d.ts +3 -37
  35. package/dist/components/composite/search-filter-bar.js +2 -15
  36. package/dist/components/composite/search-filter-bar.js.map +1 -1
  37. package/dist/components/composite/table-pagination-constants.d.ts +56 -0
  38. package/dist/components/composite/table-pagination-constants.js +18 -0
  39. package/dist/components/composite/table-pagination-constants.js.map +1 -0
  40. package/dist/components/composite/table-pagination.d.ts +2 -43
  41. package/dist/components/composite/table-pagination.js +4 -15
  42. package/dist/components/composite/table-pagination.js.map +1 -1
  43. package/dist/components/ui/badge.js +3 -3
  44. package/dist/components/ui/badge.js.map +1 -1
  45. package/dist/components/ui/button.js +4 -4
  46. package/dist/components/ui/button.js.map +1 -1
  47. package/dist/components/ui/calendar.js +1 -1
  48. package/dist/components/ui/calendar.js.map +1 -1
  49. package/dist/components/ui/checkbox.js +2 -2
  50. package/dist/components/ui/checkbox.js.map +1 -1
  51. package/dist/components/ui/command.js +1 -1
  52. package/dist/components/ui/command.js.map +1 -1
  53. package/dist/components/ui/input-group.js +1 -1
  54. package/dist/components/ui/input-group.js.map +1 -1
  55. package/dist/components/ui/input-otp.js +1 -1
  56. package/dist/components/ui/input-otp.js.map +1 -1
  57. package/dist/components/ui/navigation-menu.js +1 -1
  58. package/dist/components/ui/navigation-menu.js.map +1 -1
  59. package/dist/components/ui/radio-group.js +1 -1
  60. package/dist/components/ui/radio-group.js.map +1 -1
  61. package/dist/components/ui/resizable.js +1 -1
  62. package/dist/components/ui/resizable.js.map +1 -1
  63. package/dist/components/ui/slider.js +1 -1
  64. package/dist/components/ui/slider.js.map +1 -1
  65. package/dist/components/ui/switch.js +1 -1
  66. package/dist/components/ui/switch.js.map +1 -1
  67. package/dist/components/ui/textarea.js +1 -1
  68. package/dist/components/ui/textarea.js.map +1 -1
  69. package/dist/index.d.ts +11 -6
  70. package/dist/index.js +5 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/shell/contrast-constants.d.ts +30 -0
  73. package/dist/shell/contrast-constants.js +16 -0
  74. package/dist/shell/contrast-constants.js.map +1 -0
  75. package/dist/shell/contrast-provider.d.ts +60 -0
  76. package/dist/shell/contrast-provider.js +61 -0
  77. package/dist/shell/contrast-provider.js.map +1 -0
  78. package/dist/shell/contrast-toggle.d.ts +24 -0
  79. package/dist/shell/contrast-toggle.js +29 -0
  80. package/dist/shell/contrast-toggle.js.map +1 -0
  81. package/dist/shell/index.d.ts +3 -0
  82. package/dist/shell/index.js +3 -0
  83. package/dist/shell/index.js.map +1 -1
  84. package/dist/shell/shell-context.js +3 -2
  85. package/dist/shell/shell-context.js.map +1 -1
  86. package/dist/tokens.d.ts +170 -70
  87. package/dist/tokens.js +124 -47
  88. package/dist/tokens.js.map +1 -1
  89. package/package.json +3 -2
  90. package/styles.css +255 -120
package/dist/tokens.d.ts CHANGED
@@ -69,12 +69,14 @@ declare const accent: {
69
69
  readonly green: "#2EA56A";
70
70
  readonly yellow: "#F2C94C";
71
71
  };
72
+ /** Bảng MẶC ĐỊNH (comitor-ds) không khai lại màu phụ ở dark — cùng hex với light. Bản sáng
73
+ * dành cho nền tối nằm ở `highContrast.dark`. */
72
74
  readonly dark: {
73
75
  readonly navy: "#0F1E3D";
74
- readonly teal: "#2DD4BF";
75
- readonly red: "#F87171";
76
- readonly green: "#4ADE80";
77
- readonly yellow: "#FACC15";
76
+ readonly teal: "#1F8A8B";
77
+ readonly red: "#D64545";
78
+ readonly green: "#2EA56A";
79
+ readonly yellow: "#F2C94C";
78
80
  };
79
81
  };
80
82
  /**
@@ -86,10 +88,12 @@ declare const accent: {
86
88
  * `--x-ink` là chính màu đó ĐI LÊN nền trang.
87
89
  *
88
90
  * Bản `light` là bậc tối đã đóng băng (kết quả của `color-mix(in srgb, --<màu>, --ink 30/40%)`
89
- * mà trước đây mỗi component tự tính lấy); bản `dark` chính là `accent.dark` vì bên đó màu phụ
90
- * đã đủ sáng để làm chữ. Đo trên tint 15% của chính nó — nền thật mà chữ initials avatar và
91
- * badge tonal đứng lên: teal 5,54 · green 5,60 · red 5,83:1 ở light (bản chưa có ink: 3,44 /
92
- * 2,69 / 3,57:1 ✗); 7,12 / 7,44 / 5,18:1 ở dark.
91
+ * mà trước đây mỗi component tự tính lấy); bản `dark` chính là `accent.dark`. Đo trên tint 15%
92
+ * của chính nó — nền thật mà chữ initials avatar và badge tonal đứng lên: teal 5,54 · green 5,60
93
+ * · red 5,83:1 ở light (bản chưa có ink: 3,44 / 2,69 / 3,57:1 ✗).
94
+ *
95
+ * ⚠ Ở bảng MẶC ĐỊNH, `accent.dark` bằng hex của light nên bậc ink ở dark cũng vậy — đúng thứ
96
+ * comitor-ds render. Bậc sáng cho nền tối nằm ở `highContrast.dark`.
93
97
  */
94
98
  declare const accentInk: {
95
99
  readonly light: {
@@ -103,10 +107,10 @@ declare const accentInk: {
103
107
  readonly dark: {
104
108
  /** navy nguyên bản chìm vào nền dark (1,15:1) → bậc sáng riêng; cũng là `--chart-3` ở dark. */
105
109
  readonly navy: "#7EA2E8";
106
- readonly teal: "#2DD4BF";
107
- readonly red: "#F87171";
108
- readonly green: "#4ADE80";
109
- readonly yellow: "#FACC15";
110
+ readonly teal: "#1F8A8B";
111
+ readonly red: "#D64545";
112
+ readonly green: "#2EA56A";
113
+ readonly yellow: "#F2C94C";
110
114
  };
111
115
  };
112
116
  /**
@@ -118,9 +122,10 @@ declare const accentInk: {
118
122
  * theme, một giá trị đủ dùng: teal 4,56:1 (light) / 10,16:1 (dark) · green 6,04 / 10,85 ·
119
123
  * yellow 11,92 / 12,35. Navy thì ngược lại — chữ TRẮNG, 16,49:1 ở cả hai theme.
120
124
  *
121
- * ⚠ CỐ Ý KHÔNG có `red`: nền `accent.light.red` #D64545 đặc không mang được chữ ở light — trắng
122
- * 4,38:1 ✗ và mực 4,32:1 ✗. Nền đỏ đặc có chữ phải dùng `status.*.destructive` (#C93B3B) cùng
123
- * `destructiveForeground` = 5,03:1 ✓. `accent.*.red` chỉ để tô TINT và làm màu chart.
125
+ * ⚠ CỐ Ý KHÔNG có `red`: nền đỏ đặc không mang được chữ tốt ở light — trắng trên #D64545 được
126
+ * 4,38:1 và mực 4,32:1, cả hai đều dưới AA. Nền đỏ đặc có chữ phải dùng `status.*.destructive`;
127
+ * ở bảng tương phản cao token đó là #C93B3B và đạt 5,03:1. `accent.*.red` chỉ để tô TINT và làm
128
+ * màu chart.
124
129
  */
125
130
  declare const accentForeground: {
126
131
  readonly light: {
@@ -147,43 +152,54 @@ declare const semantic: {
147
152
  readonly popoverForeground: "#0E1116";
148
153
  readonly primary: "#E8B824";
149
154
  readonly primaryForeground: "#0E1116";
150
- /** Bậc INK của brand — gold khi phải ĐI LÊN nền trang (rãnh Switch khi BẬT, ô Checkbox đã
151
- * chọn). `primary` #E8B824 chỉ 1,86:1 với nền trắng ✗; bậc này = `gold[500]` = 6,51:1 ✓. */
152
- readonly primaryInk: "#7A5800";
155
+ /** Bậc INK của brand. Ở bảng MẶC ĐỊNH nó BẰNG `primary`: comitor-ds tô gold cho cả những vai
156
+ * trò mà 1.4.11 đòi 3:1 (rãnh Switch BẬT, gạch active của Tabs) — 1,86:1, đã biết và chấp
157
+ * nhận. Bậc tối #7A5800 nằm ở `highContrast.light.primaryInk`. */
158
+ readonly primaryInk: "#E8B824";
153
159
  readonly secondary: "#EDE8D8";
154
160
  readonly secondaryForeground: "#0E1116";
155
161
  readonly muted: "#F7F7F8";
156
- /** Bậc chữ phụ — là CHỮ nên ngưỡng AA 4,5:1: 5,23:1 trên nền trắng, 4,89:1 trên `muted`.
157
- * KHÔNG còn bằng `ash[500]` (#7E8290 chỉ 3,83:1 ✗) — bậc bảng màu và token semantic tách nhau. */
158
- readonly mutedForeground: "#686C7A";
162
+ /** Bậc chữ phụ — giá trị của comitor-ds, bằng đúng `ash[500]`. 3,83:1 trên nền trắng và
163
+ * 3,58:1 trên `muted`, tức dưới AA 4,5:1: đã biết và chấp nhận, bản đạt chuẩn nằm ở
164
+ * `highContrast.light.mutedForeground`. */
165
+ readonly mutedForeground: "#7E8290";
159
166
  readonly accent: "#FBF5DC";
160
167
  readonly accentForeground: "#0E1116";
161
- readonly destructive: "#C93B3B";
168
+ /** Nền nút xoá. Chữ trắng trên nó được 4,38:1 — thiếu 0,12 so với AA, đã biết và chấp nhận. */
169
+ readonly destructive: "#D64545";
162
170
  readonly destructiveForeground: "#FFFFFF";
163
- /** Chữ báo lỗi trên nền trang — KHÁC `destructive` (nền) và `destructiveForeground` (chữ
164
- * trắng trên nền đó). 7,15:1 trên nền trắng. */
165
- readonly destructiveInk: "#9A3537";
171
+ /** Nền nút xoá lúc HOVER = `destructive` ở 90% trên nền trắng, đúng thứ `hover:bg-red/90`
172
+ * của comitor-ds render. Ghim hex vì `/90` phụ thuộc nền phía sau. */
173
+ readonly destructiveHover: "#DA5A5A";
174
+ /** Chữ báo lỗi trên nền trang. comitor-ds viết `text-destructive` cho vai trò này, tức cùng
175
+ * hex với nền — 4,38:1 trên nền trắng. */
176
+ readonly destructiveInk: "#D64545";
166
177
  /** RANH GIỚI TRANG TRÍ (vạch chia, viền thẻ nghỉ) — 1,16:1, cố ý: 1.4.11 không đòi tương
167
178
  * phản cho thứ không mang thông tin. Ranh giới của CONTROL đi qua `controlEdge`. */
168
179
  readonly border: "#EDEEF1";
169
- /** = `controlEdge`: viền ô nhập là ranh giới nhận dạng control (1.4.11) → 3,83:1 ✓. */
170
- readonly input: "#7E8290";
180
+ /** Viền ô nhập — comitor-ds cho nó cùng bậc với `border`. 1,16:1, đã biết và chấp nhận. */
181
+ readonly input: "#EDEEF1";
171
182
  readonly ring: "#E8B824";
172
- /** Ranh giới của control lúc NGHỈ (viền Input, ô Checkbox chưa chọn, rãnh Switch khi TẮT) —
173
- * WCAG 1.4.11, ràng buộc HAI PHÍA. Một giá trị cho cả hai theme: 3,83:1 với nền trắng và
174
- * 3,83:1 với `controlKnob` (trắng ở light); 4,94:1 với nền dark và với knob #0E1116. */
175
- readonly controlEdge: "#7E8290";
176
- /** Cùng vai trò nhưng ở HOVER/ACTIVE — phải ĐẬM hơn lúc nghỉ. = `ash[700]`, 10,55:1 trên nền
177
- * trắng · 9,86:1 trên `muted`. */
178
- readonly controlEdgeStrong: "#3A3F4A";
179
- /** Nền control khi BẬT/ĐÃ CHỌN (rãnh Switch bật, ô Checkbox đã chọn, chấm Radio) = `primaryInk`.
180
- * Ràng buộc hai phía: 6,51:1 với nền trang VÀ 6,51:1 với `controlKnob` ở light. `primary`
181
- * #E8B824 chỉ 1,86:1 cả hai phía ✗. */
182
- readonly controlOn: "#7A5800";
183
- /** Núm Switch / dấu check / chấm Radio — mang màu NỀN TRANG nên luôn tương phản đúng chiều
184
- * với cả rãnh BẬT (6,51:1) lẫn rãnh TẮT (3,83:1). KHÔNG dùng `primaryForeground` (mực): mực
185
- * trên `controlOn` #7A5800 chỉ 1,86:1 ✗. */
183
+ /** Ranh giới của control lúc NGHỈ — ở bảng mặc định bằng đúng `input`. */
184
+ readonly controlEdge: "#EDEEF1";
185
+ /** Cùng vai trò nhưng ở HOVER/ACTIVE. comitor-ds dùng `hover:border-gray-300` = `ash[300]`. */
186
+ readonly controlEdgeStrong: "#C8CBD3";
187
+ /** Nền control khi BẬT/ĐÃ CHỌN (rãnh Switch bật, ô Checkbox đã chọn, chấm Radio). comitor-ds
188
+ * tô gold: 1,86:1 với nền trang và với núm — đã biết và chấp nhận. */
189
+ readonly controlOn: "#E8B824";
190
+ /** Núm Switch / chấm Radio — TRẮNG ở cả hai theme, đúng `bg-white` của comitor-ds. */
186
191
  readonly controlKnob: "#FFFFFF";
192
+ /** DẤU CHECK của Checkbox và chữ trên ngày ĐANG CHỌN của Calendar — tách khỏi `controlKnob`
193
+ * vì trên nền gold SÁNG thì dấu phải là MỰC (10,19:1), còn ở bảng tương phản cao nền là
194
+ * gold-500 TỐI nên dấu lật thành màu nền trang. */
195
+ readonly controlCheck: "#0E1116";
196
+ /** Rãnh Switch khi TẮT — comitor-ds dùng `bg-gray-300` / `dark:bg-gray-700`. */
197
+ readonly switchTrack: "#C8CBD3";
198
+ /** Rãnh Slider — comitor-ds dùng `bg-muted`, khác bậc với rãnh Switch. */
199
+ readonly sliderTrack: "#F7F7F8";
200
+ /** Button variant `link`. comitor-ds dùng `gold[400]` — 3,15:1, dưới AA, đã biết và chấp nhận. */
201
+ readonly linkInk: "#B88A00";
202
+ readonly linkInkHover: "#E8B824";
187
203
  readonly sidebar: "#FAFAF9";
188
204
  readonly sidebarForeground: "#0E1116";
189
205
  readonly sidebarBorder: "#EDEEF1";
@@ -204,28 +220,36 @@ declare const semantic: {
204
220
  readonly secondary: "#1E2128";
205
221
  readonly secondaryForeground: "#F7F7F8";
206
222
  readonly muted: "#1E2128";
207
- /** Sáng hơn bản light: chữ phụ ở dark hay nằm trên `card`/`muted`. 5,35:1 trên `card`,
208
- * 4,86:1 trên `muted` (giá trị cũ #7E8290 chỉ 4,21:1 trên `muted` ✗). */
209
- readonly mutedForeground: "#888D9B";
223
+ /** comitor-ds không khai lại token này ở dark — cùng hex với light. 4,21:1 trên `muted`,
224
+ * dưới AA: đã biết và chấp nhận. */
225
+ readonly mutedForeground: "#7E8290";
210
226
  readonly accent: "#1E2128";
211
227
  readonly accentForeground: "#F7F7F8";
212
- readonly destructive: "#C93B3B";
228
+ /** Ghim đúng giá trị của light — comitor-ds dùng chung một hex cho cả hai theme. */
229
+ readonly destructive: "#D64545";
213
230
  readonly destructiveForeground: "#FFFFFF";
214
- /** 6,42:1 trên `card` — `destructive` dùng làm chữ ở dark chỉ được 3,53:1 ✗. */
215
- readonly destructiveInk: "#F87171";
231
+ readonly destructiveHover: "#DA5A5A";
232
+ /** 4,06:1 trên `card` — cùng hex với nền, đúng `text-destructive` của comitor-ds. */
233
+ readonly destructiveInk: "#D64545";
216
234
  /** TRANG TRÍ, 1,17:1 trên `background` và 1,10:1 trên `card` — cố ý, xem nhánh light. */
217
235
  readonly border: "#1E2128";
218
- /** = `controlEdge`, ghim một giá trị cho cả hai theme — 4,94:1 trên `background` ✓. */
219
- readonly input: "#7E8290";
236
+ /** Viền ô nhập bản dark của comitor-ds — cùng bậc với `border`. */
237
+ readonly input: "#1E2128";
220
238
  readonly ring: "#F5D060";
221
- /** Ghim đúng giá trị của light — xem chú thích ở nhánh light. */
222
- readonly controlEdge: "#7E8290";
223
- /** = `ash[300]` (lật chiều so với light): 11,65:1 trên `background` · 10,94:1 trên `card`. */
224
- readonly controlEdgeStrong: "#C8CBD3";
225
- /** = `primaryInk` của dark; 12,67:1 với nền trang VÀ với `controlKnob` (#0E1116). */
239
+ readonly controlEdge: "#1E2128";
240
+ /** comitor-ds dùng `dark:hover:border-gray-500` = `ash[500]` (lật chiều so với light). */
241
+ readonly controlEdgeStrong: "#7E8290";
242
+ /** comitor-ds tô `dark:data-[state=checked]:bg-gold-300`, nhưng token `primary` của chính nó
243
+ * ở dark là #F5D060; gói theo token, nên control BẬT ở dark là bậc sáng. */
226
244
  readonly controlOn: "#F5D060";
227
- /** = `background` của dark. Núm trắng cứng sẽ chỉ được 1,49:1 với rãnh BẬT ✗. */
228
- readonly controlKnob: "#0E1116";
245
+ /** TRẮNG ở cả hai theme, đúng `bg-white` của comitor-ds. */
246
+ readonly controlKnob: "#FFFFFF";
247
+ /** comitor-ds vẽ dấu check bằng `text-ink` ở CẢ hai theme. */
248
+ readonly controlCheck: "#0E1116";
249
+ readonly switchTrack: "#3A3F4A";
250
+ readonly sliderTrack: "#1E2128";
251
+ readonly linkInk: "#B88A00";
252
+ readonly linkInkHover: "#E8B824";
229
253
  readonly sidebar: "#16181D";
230
254
  readonly sidebarForeground: "#F7F7F8";
231
255
  readonly sidebarBorder: "#1E2128";
@@ -233,14 +257,90 @@ declare const semantic: {
233
257
  readonly sidebarAccentForeground: "#F7F7F8";
234
258
  };
235
259
  };
260
+ /**
261
+ * BẢNG MÀU THỨ HAI — TƯƠNG PHẢN CAO. Mirror khối `[data-contrast="high"]` /
262
+ * `.dark[data-contrast="high"]` trong styles.css.
263
+ *
264
+ * Chỉ chứa những token KHÁC bảng mặc định, đúng như CSS: hợp lên trên để có bảng đầy đủ.
265
+ *
266
+ * ```ts
267
+ * const mau = { ...semantic.light, ...highContrast.light };
268
+ * ```
269
+ *
270
+ * Bảng mặc định là comitor-ds (bản duyệt, có những cặp dưới ngưỡng — đã liệt kê ở từng token).
271
+ * Bảng này là bảng đã đo, do NGƯỜI DÙNG bật qua `<ContrastProvider>` + `<ContrastToggle>`.
272
+ * `accent` là màu phụ bản sáng dành cho nền tối — bảng mặc định không có, xem `accent.dark`.
273
+ */
274
+ declare const highContrast: {
275
+ readonly light: {
276
+ /** 5,23:1 trên `background` · 4,89:1 trên `muted` (bảng mặc định: 3,83 / 3,58) */
277
+ readonly mutedForeground: "#686C7A";
278
+ /** Chữ trắng trên nền này được 5,03:1 (bảng mặc định #D64545 chỉ 4,38:1) */
279
+ readonly destructive: "#C93B3B";
280
+ /** = color-mix(destructive, ink 15%) — ĐẬM thêm khi hover, ngược chiều bảng mặc định. */
281
+ readonly destructiveHover: "#AD3535";
282
+ /** 7,15:1 trên nền trắng (bảng mặc định dùng chính #D64545, 4,38:1) */
283
+ readonly destructiveInk: "#9A3537";
284
+ /** 3,83:1 trên nền trắng (bảng mặc định #EDEEF1 chỉ 1,16:1) */
285
+ readonly input: "#7E8290";
286
+ readonly controlEdge: "#7E8290";
287
+ readonly controlEdgeStrong: "#3A3F4A";
288
+ /** Rãnh ⇄ nền 6,51:1 và rãnh ⇄ núm 6,51:1 (bảng mặc định: 1,86 / 1,86) */
289
+ readonly controlOn: "#7A5800";
290
+ /** = `background`, nên luôn tương phản đúng chiều với cả rãnh BẬT lẫn rãnh TẮT. */
291
+ readonly controlKnob: "#FFFFFF";
292
+ readonly controlCheck: "#FFFFFF";
293
+ readonly switchTrack: "#7E8290";
294
+ readonly sliderTrack: "#7E8290";
295
+ readonly primaryInk: "#7A5800";
296
+ readonly linkInk: "#7A5800";
297
+ readonly linkInkHover: "#5C4006";
298
+ readonly accent: {
299
+ readonly navy: "#0F1E3D";
300
+ readonly teal: "#1F8A8B";
301
+ readonly red: "#D64545";
302
+ readonly green: "#2EA56A";
303
+ readonly yellow: "#F2C94C";
304
+ };
305
+ };
306
+ readonly dark: {
307
+ /** 5,70:1 trên `background` · 5,35:1 trên `card` · 4,86:1 trên `muted` */
308
+ readonly mutedForeground: "#888D9B";
309
+ readonly destructive: "#C93B3B";
310
+ readonly destructiveHover: "#AD3535";
311
+ readonly destructiveInk: "#F87171";
312
+ /** Ghim một giá trị cho cả hai theme — 4,94:1 trên `background` */
313
+ readonly input: "#7E8290";
314
+ readonly controlEdge: "#7E8290";
315
+ readonly controlEdgeStrong: "#C8CBD3";
316
+ /** 12,67:1 với nền trang VÀ với `controlKnob` (#0E1116) */
317
+ readonly controlOn: "#F5D060";
318
+ readonly controlKnob: "#0E1116";
319
+ readonly controlCheck: "#0E1116";
320
+ readonly switchTrack: "#7E8290";
321
+ readonly sliderTrack: "#7E8290";
322
+ readonly primaryInk: "#F5D060";
323
+ readonly linkInk: "#F5D060";
324
+ readonly linkInkHover: "#F8E89D";
325
+ /** Màu phụ bản SÁNG cho nền tối — bảng mặc định không có bản dark cho nhóm này. */
326
+ readonly accent: {
327
+ readonly navy: "#0F1E3D";
328
+ readonly teal: "#2DD4BF";
329
+ readonly red: "#F87171";
330
+ readonly green: "#4ADE80";
331
+ readonly yellow: "#FACC15";
332
+ };
333
+ };
334
+ };
236
335
  /**
237
336
  * Alias trạng thái — success/warning/info trỏ vào màu phụ, destructive giữ nguyên 2 chế độ.
238
337
  *
239
338
  * Ba lớp KHÁC nhau, đừng gộp:
240
- * • `destructive` (#C93B3B) — màu NỀN (nút xoá), đủ đậm cho chữ trắng ở cả hai theme (5,03:1);
339
+ * • `destructive` — màu NỀN (nút xoá): #D64545 ở bảng mặc định (chữ trắng 4,38:1, dưới AA và đã
340
+ * chấp nhận), #C93B3B ở bảng tương phản cao (5,03:1 ✓);
241
341
  * • `destructiveForeground` (#FFFFFF) — chữ NẰM TRÊN nền đó;
242
- * • `destructiveInk` — màu CHỮ đỏ trên nền trang (dòng lỗi). Dùng nhầm `destructive` cho vai
243
- * trò này thì ở dark chỉ được 3,53:1, dùng `accent.light.red` thì ở light chỉ 4,38:1.
342
+ * • `destructiveInk` — màu CHỮ đỏ trên nền trang (dòng lỗi). Bảng mặc định cho nó cùng hex với
343
+ * nền (đúng `text-destructive` của comitor-ds); bảng tương phản cao tách thành bậc tối riêng.
244
344
  *
245
345
  * `successForeground` / `warningForeground` / `infoForeground` là MỰC ở CẢ hai theme (không phải
246
346
  * trắng ở light rồi lật ở dark như bản 0.1.0): ba nền trạng thái đều là sắc sáng.
@@ -257,7 +357,7 @@ declare const status: {
257
357
  readonly warningForeground: "#0E1116";
258
358
  readonly info: "#1F8A8B";
259
359
  readonly infoForeground: "#0E1116";
260
- readonly destructive: "#C93B3B";
360
+ readonly destructive: "#D64545";
261
361
  readonly destructiveForeground: "#FFFFFF";
262
362
  readonly successInk: "#216A48";
263
363
  readonly warningInk: "#7A5800";
@@ -265,24 +365,24 @@ declare const status: {
265
365
  readonly destructiveInk: "#9A3537";
266
366
  };
267
367
  readonly dark: {
268
- readonly success: "#4ADE80";
368
+ readonly success: "#2EA56A";
269
369
  readonly successForeground: "#0E1116";
270
- readonly warning: "#FACC15";
370
+ readonly warning: "#F2C94C";
271
371
  readonly warningForeground: "#0E1116";
272
- readonly info: "#2DD4BF";
372
+ readonly info: "#1F8A8B";
273
373
  readonly infoForeground: "#0E1116";
274
- readonly destructive: "#C93B3B";
374
+ readonly destructive: "#D64545";
275
375
  readonly destructiveForeground: "#FFFFFF";
276
- readonly successInk: "#4ADE80";
277
- readonly warningInk: "#FACC15";
278
- readonly infoInk: "#2DD4BF";
279
- readonly destructiveInk: "#F87171";
376
+ readonly successInk: "#2EA56A";
377
+ readonly warningInk: "#F2C94C";
378
+ readonly infoInk: "#1F8A8B";
379
+ readonly destructiveInk: "#D64545";
280
380
  };
281
381
  };
282
382
  /** Bảng màu biểu đồ (chart-1…chart-5). Thứ tự = thứ tự series mặc định. */
283
383
  declare const chart: {
284
384
  readonly light: readonly ["#E8B824", "#1F8A8B", "#0F1E3D", "#2EA56A", "#D64545"];
285
- readonly dark: readonly ["#F5D060", "#2DD4BF", "#7EA2E8", "#4ADE80", "#F87171"];
385
+ readonly dark: readonly ["#F5D060", "#1F8A8B", "#7EA2E8", "#2EA56A", "#D64545"];
286
386
  };
287
387
  /**
288
388
  * Cặp nền/chữ (hex) của avatar cho một tên, theo theme.
@@ -318,4 +418,4 @@ declare const typography: {
318
418
  };
319
419
  type ThemeMode = "light" | "dark";
320
420
 
321
- export { AvatarToneColors, type ThemeMode, accent, accentForeground, accentInk, ash, brandNeutral, chart, getAvatarToneColors, gold, layout, semantic, status, typography };
421
+ export { AvatarToneColors, type ThemeMode, accent, accentForeground, accentInk, ash, brandNeutral, chart, getAvatarToneColors, gold, highContrast, layout, semantic, status, typography };
package/dist/tokens.js CHANGED
@@ -31,12 +31,14 @@ const accent = {
31
31
  green: "#2EA56A",
32
32
  yellow: "#F2C94C"
33
33
  },
34
+ /** Bảng MẶC ĐỊNH (comitor-ds) không khai lại màu phụ ở dark — cùng hex với light. Bản sáng
35
+ * dành cho nền tối nằm ở `highContrast.dark`. */
34
36
  dark: {
35
37
  navy: "#0F1E3D",
36
- teal: "#2DD4BF",
37
- red: "#F87171",
38
- green: "#4ADE80",
39
- yellow: "#FACC15"
38
+ teal: "#1F8A8B",
39
+ red: "#D64545",
40
+ green: "#2EA56A",
41
+ yellow: "#F2C94C"
40
42
  }
41
43
  };
42
44
  const accentInk = {
@@ -81,43 +83,54 @@ const semantic = {
81
83
  popoverForeground: "#0E1116",
82
84
  primary: "#E8B824",
83
85
  primaryForeground: "#0E1116",
84
- /** Bậc INK của brand — gold khi phải ĐI LÊN nền trang (rãnh Switch khi BẬT, ô Checkbox đã
85
- * chọn). `primary` #E8B824 chỉ 1,86:1 với nền trắng ✗; bậc này = `gold[500]` = 6,51:1 ✓. */
86
- primaryInk: gold[500],
86
+ /** Bậc INK của brand. Ở bảng MẶC ĐỊNH nó BẰNG `primary`: comitor-ds tô gold cho cả những vai
87
+ * trò mà 1.4.11 đòi 3:1 (rãnh Switch BẬT, gạch active của Tabs) — 1,86:1, đã biết và chấp
88
+ * nhận. Bậc tối #7A5800 nằm ở `highContrast.light.primaryInk`. */
89
+ primaryInk: "#E8B824",
87
90
  secondary: "#EDE8D8",
88
91
  secondaryForeground: "#0E1116",
89
92
  muted: "#F7F7F8",
90
- /** Bậc chữ phụ — là CHỮ nên ngưỡng AA 4,5:1: 5,23:1 trên nền trắng, 4,89:1 trên `muted`.
91
- * KHÔNG còn bằng `ash[500]` (#7E8290 chỉ 3,83:1 ✗) — bậc bảng màu và token semantic tách nhau. */
92
- mutedForeground: "#686C7A",
93
+ /** Bậc chữ phụ — giá trị của comitor-ds, bằng đúng `ash[500]`. 3,83:1 trên nền trắng và
94
+ * 3,58:1 trên `muted`, tức dưới AA 4,5:1: đã biết và chấp nhận, bản đạt chuẩn nằm ở
95
+ * `highContrast.light.mutedForeground`. */
96
+ mutedForeground: ash[500],
93
97
  accent: "#FBF5DC",
94
98
  accentForeground: "#0E1116",
95
- destructive: "#C93B3B",
99
+ /** Nền nút xoá. Chữ trắng trên nó được 4,38:1 — thiếu 0,12 so với AA, đã biết và chấp nhận. */
100
+ destructive: "#D64545",
96
101
  destructiveForeground: "#FFFFFF",
97
- /** Chữ báo lỗi trên nền trang — KHÁC `destructive` (nền) và `destructiveForeground` (chữ
98
- * trắng trên nền đó). 7,15:1 trên nền trắng. */
99
- destructiveInk: accentInk.light.red,
102
+ /** Nền nút xoá lúc HOVER = `destructive` ở 90% trên nền trắng, đúng thứ `hover:bg-red/90`
103
+ * của comitor-ds render. Ghim hex vì `/90` phụ thuộc nền phía sau. */
104
+ destructiveHover: "#DA5A5A",
105
+ /** Chữ báo lỗi trên nền trang. comitor-ds viết `text-destructive` cho vai trò này, tức cùng
106
+ * hex với nền — 4,38:1 trên nền trắng. */
107
+ destructiveInk: "#D64545",
100
108
  /** RANH GIỚI TRANG TRÍ (vạch chia, viền thẻ nghỉ) — 1,16:1, cố ý: 1.4.11 không đòi tương
101
109
  * phản cho thứ không mang thông tin. Ranh giới của CONTROL đi qua `controlEdge`. */
102
110
  border: "#EDEEF1",
103
- /** = `controlEdge`: viền ô nhập là ranh giới nhận dạng control (1.4.11) → 3,83:1 ✓. */
104
- input: "#7E8290",
111
+ /** Viền ô nhập — comitor-ds cho nó cùng bậc với `border`. 1,16:1, đã biết và chấp nhận. */
112
+ input: "#EDEEF1",
105
113
  ring: "#E8B824",
106
- /** Ranh giới của control lúc NGHỈ (viền Input, ô Checkbox chưa chọn, rãnh Switch khi TẮT) —
107
- * WCAG 1.4.11, ràng buộc HAI PHÍA. Một giá trị cho cả hai theme: 3,83:1 với nền trắng và
108
- * 3,83:1 với `controlKnob` (trắng ở light); 4,94:1 với nền dark và với knob #0E1116. */
109
- controlEdge: "#7E8290",
110
- /** Cùng vai trò nhưng ở HOVER/ACTIVE — phải ĐẬM hơn lúc nghỉ. = `ash[700]`, 10,55:1 trên nền
111
- * trắng · 9,86:1 trên `muted`. */
112
- controlEdgeStrong: ash[700],
113
- /** Nền control khi BẬT/ĐÃ CHỌN (rãnh Switch bật, ô Checkbox đã chọn, chấm Radio) = `primaryInk`.
114
- * Ràng buộc hai phía: 6,51:1 với nền trang VÀ 6,51:1 với `controlKnob` ở light. `primary`
115
- * #E8B824 chỉ 1,86:1 cả hai phía ✗. */
116
- controlOn: gold[500],
117
- /** Núm Switch / dấu check / chấm Radio — mang màu NỀN TRANG nên luôn tương phản đúng chiều
118
- * với cả rãnh BẬT (6,51:1) lẫn rãnh TẮT (3,83:1). KHÔNG dùng `primaryForeground` (mực): mực
119
- * trên `controlOn` #7A5800 chỉ 1,86:1 ✗. */
114
+ /** Ranh giới của control lúc NGHỈ — ở bảng mặc định bằng đúng `input`. */
115
+ controlEdge: "#EDEEF1",
116
+ /** Cùng vai trò nhưng ở HOVER/ACTIVE. comitor-ds dùng `hover:border-gray-300` = `ash[300]`. */
117
+ controlEdgeStrong: ash[300],
118
+ /** Nền control khi BẬT/ĐÃ CHỌN (rãnh Switch bật, ô Checkbox đã chọn, chấm Radio). comitor-ds
119
+ * tô gold: 1,86:1 với nền trang và với núm — đã biết và chấp nhận. */
120
+ controlOn: "#E8B824",
121
+ /** Núm Switch / chấm Radio — TRẮNG ở cả hai theme, đúng `bg-white` của comitor-ds. */
120
122
  controlKnob: "#FFFFFF",
123
+ /** DẤU CHECK của Checkbox và chữ trên ngày ĐANG CHỌN của Calendar — tách khỏi `controlKnob`
124
+ * vì trên nền gold SÁNG thì dấu phải là MỰC (10,19:1), còn ở bảng tương phản cao nền là
125
+ * gold-500 TỐI nên dấu lật thành màu nền trang. */
126
+ controlCheck: brandNeutral.ink,
127
+ /** Rãnh Switch khi TẮT — comitor-ds dùng `bg-gray-300` / `dark:bg-gray-700`. */
128
+ switchTrack: ash[300],
129
+ /** Rãnh Slider — comitor-ds dùng `bg-muted`, khác bậc với rãnh Switch. */
130
+ sliderTrack: "#F7F7F8",
131
+ /** Button variant `link`. comitor-ds dùng `gold[400]` — 3,15:1, dưới AA, đã biết và chấp nhận. */
132
+ linkInk: gold[400],
133
+ linkInkHover: gold[300],
121
134
  sidebar: "#FAFAF9",
122
135
  sidebarForeground: "#0E1116",
123
136
  sidebarBorder: "#EDEEF1",
@@ -138,28 +151,36 @@ const semantic = {
138
151
  secondary: "#1E2128",
139
152
  secondaryForeground: "#F7F7F8",
140
153
  muted: "#1E2128",
141
- /** Sáng hơn bản light: chữ phụ ở dark hay nằm trên `card`/`muted`. 5,35:1 trên `card`,
142
- * 4,86:1 trên `muted` (giá trị cũ #7E8290 chỉ 4,21:1 trên `muted` ✗). */
143
- mutedForeground: "#888D9B",
154
+ /** comitor-ds không khai lại token này ở dark — cùng hex với light. 4,21:1 trên `muted`,
155
+ * dưới AA: đã biết và chấp nhận. */
156
+ mutedForeground: ash[500],
144
157
  accent: "#1E2128",
145
158
  accentForeground: "#F7F7F8",
146
- destructive: "#C93B3B",
159
+ /** Ghim đúng giá trị của light — comitor-ds dùng chung một hex cho cả hai theme. */
160
+ destructive: "#D64545",
147
161
  destructiveForeground: "#FFFFFF",
148
- /** 6,42:1 trên `card` — `destructive` dùng làm chữ ở dark chỉ được 3,53:1 ✗. */
149
- destructiveInk: accentInk.dark.red,
162
+ destructiveHover: "#DA5A5A",
163
+ /** 4,06:1 trên `card` — cùng hex với nền, đúng `text-destructive` của comitor-ds. */
164
+ destructiveInk: "#D64545",
150
165
  /** TRANG TRÍ, 1,17:1 trên `background` và 1,10:1 trên `card` — cố ý, xem nhánh light. */
151
166
  border: "#1E2128",
152
- /** = `controlEdge`, ghim một giá trị cho cả hai theme — 4,94:1 trên `background` ✓. */
153
- input: "#7E8290",
167
+ /** Viền ô nhập bản dark của comitor-ds — cùng bậc với `border`. */
168
+ input: "#1E2128",
154
169
  ring: "#F5D060",
155
- /** Ghim đúng giá trị của light — xem chú thích ở nhánh light. */
156
- controlEdge: "#7E8290",
157
- /** = `ash[300]` (lật chiều so với light): 11,65:1 trên `background` · 10,94:1 trên `card`. */
158
- controlEdgeStrong: ash[300],
159
- /** = `primaryInk` của dark; 12,67:1 với nền trang VÀ với `controlKnob` (#0E1116). */
170
+ controlEdge: "#1E2128",
171
+ /** comitor-ds dùng `dark:hover:border-gray-500` = `ash[500]` (lật chiều so với light). */
172
+ controlEdgeStrong: ash[500],
173
+ /** comitor-ds tô `dark:data-[state=checked]:bg-gold-300`, nhưng token `primary` của chính nó
174
+ * ở dark là #F5D060; gói theo token, nên control BẬT ở dark là bậc sáng. */
160
175
  controlOn: "#F5D060",
161
- /** = `background` của dark. Núm trắng cứng sẽ chỉ được 1,49:1 với rãnh BẬT ✗. */
162
- controlKnob: "#0E1116",
176
+ /** TRẮNG ở cả hai theme, đúng `bg-white` của comitor-ds. */
177
+ controlKnob: "#FFFFFF",
178
+ /** comitor-ds vẽ dấu check bằng `text-ink` ở CẢ hai theme. */
179
+ controlCheck: brandNeutral.ink,
180
+ switchTrack: ash[700],
181
+ sliderTrack: "#1E2128",
182
+ linkInk: gold[400],
183
+ linkInkHover: gold[300],
163
184
  sidebar: "#16181D",
164
185
  sidebarForeground: "#F7F7F8",
165
186
  sidebarBorder: "#1E2128",
@@ -167,6 +188,61 @@ const semantic = {
167
188
  sidebarAccentForeground: "#F7F7F8"
168
189
  }
169
190
  };
191
+ const highContrast = {
192
+ light: {
193
+ /** 5,23:1 trên `background` · 4,89:1 trên `muted` (bảng mặc định: 3,83 / 3,58) */
194
+ mutedForeground: "#686C7A",
195
+ /** Chữ trắng trên nền này được 5,03:1 (bảng mặc định #D64545 chỉ 4,38:1) */
196
+ destructive: "#C93B3B",
197
+ /** = color-mix(destructive, ink 15%) — ĐẬM thêm khi hover, ngược chiều bảng mặc định. */
198
+ destructiveHover: "#AD3535",
199
+ /** 7,15:1 trên nền trắng (bảng mặc định dùng chính #D64545, 4,38:1) */
200
+ destructiveInk: accentInk.light.red,
201
+ /** 3,83:1 trên nền trắng (bảng mặc định #EDEEF1 chỉ 1,16:1) */
202
+ input: "#7E8290",
203
+ controlEdge: "#7E8290",
204
+ controlEdgeStrong: ash[700],
205
+ /** Rãnh ⇄ nền 6,51:1 và rãnh ⇄ núm 6,51:1 (bảng mặc định: 1,86 / 1,86) */
206
+ controlOn: gold[500],
207
+ /** = `background`, nên luôn tương phản đúng chiều với cả rãnh BẬT lẫn rãnh TẮT. */
208
+ controlKnob: "#FFFFFF",
209
+ controlCheck: "#FFFFFF",
210
+ switchTrack: "#7E8290",
211
+ sliderTrack: "#7E8290",
212
+ primaryInk: gold[500],
213
+ linkInk: gold[500],
214
+ linkInkHover: gold[600],
215
+ accent: accent.light
216
+ },
217
+ dark: {
218
+ /** 5,70:1 trên `background` · 5,35:1 trên `card` · 4,86:1 trên `muted` */
219
+ mutedForeground: "#888D9B",
220
+ destructive: "#C93B3B",
221
+ destructiveHover: "#AD3535",
222
+ destructiveInk: "#F87171",
223
+ /** Ghim một giá trị cho cả hai theme — 4,94:1 trên `background` */
224
+ input: "#7E8290",
225
+ controlEdge: "#7E8290",
226
+ controlEdgeStrong: ash[300],
227
+ /** 12,67:1 với nền trang VÀ với `controlKnob` (#0E1116) */
228
+ controlOn: "#F5D060",
229
+ controlKnob: "#0E1116",
230
+ controlCheck: "#0E1116",
231
+ switchTrack: "#7E8290",
232
+ sliderTrack: "#7E8290",
233
+ primaryInk: "#F5D060",
234
+ linkInk: gold[200],
235
+ linkInkHover: gold[100],
236
+ /** Màu phụ bản SÁNG cho nền tối — bảng mặc định không có bản dark cho nhóm này. */
237
+ accent: {
238
+ navy: "#0F1E3D",
239
+ teal: "#2DD4BF",
240
+ red: "#F87171",
241
+ green: "#4ADE80",
242
+ yellow: "#FACC15"
243
+ }
244
+ }
245
+ };
170
246
  const status = {
171
247
  light: {
172
248
  success: accent.light.green,
@@ -175,7 +251,7 @@ const status = {
175
251
  warningForeground: "#0E1116",
176
252
  info: accent.light.teal,
177
253
  infoForeground: "#0E1116",
178
- destructive: "#C93B3B",
254
+ destructive: "#D64545",
179
255
  destructiveForeground: "#FFFFFF",
180
256
  successInk: accentInk.light.green,
181
257
  warningInk: accentInk.light.yellow,
@@ -189,7 +265,7 @@ const status = {
189
265
  warningForeground: "#0E1116",
190
266
  info: accent.dark.teal,
191
267
  infoForeground: "#0E1116",
192
- destructive: "#C93B3B",
268
+ destructive: "#D64545",
193
269
  destructiveForeground: "#FFFFFF",
194
270
  successInk: accentInk.dark.green,
195
271
  warningInk: accentInk.dark.yellow,
@@ -250,6 +326,7 @@ export {
250
326
  getAvatarToneColors,
251
327
  getAvatarToneIndex,
252
328
  gold,
329
+ highContrast,
253
330
  layout,
254
331
  semantic,
255
332
  status,