@vobs/ui 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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app-shell-dom.d.ts +24 -0
  3. package/dist/app-shell-dom.js +573 -0
  4. package/dist/app-shell.d.ts +199 -0
  5. package/dist/app-shell.js +370 -0
  6. package/dist/base.css +52 -0
  7. package/dist/calendar-picker.d.ts +45 -0
  8. package/dist/calendar-picker.js +217 -0
  9. package/dist/calendar.d.ts +95 -0
  10. package/dist/calendar.js +194 -0
  11. package/dist/complex-inputs.d.ts +300 -0
  12. package/dist/complex-inputs.js +862 -0
  13. package/dist/components.css +4568 -0
  14. package/dist/data-display.d.ts +1063 -0
  15. package/dist/data-display.js +2298 -0
  16. package/dist/feedback.d.ts +88 -0
  17. package/dist/feedback.js +281 -0
  18. package/dist/forms.d.ts +378 -0
  19. package/dist/forms.js +1015 -0
  20. package/dist/icons-config.d.ts +25 -0
  21. package/dist/icons-config.js +14 -0
  22. package/dist/icons.d.ts +41 -0
  23. package/dist/icons.js +185 -0
  24. package/dist/index.d.ts +22 -0
  25. package/dist/index.js +32 -0
  26. package/dist/locale/en-US.d.ts +31 -0
  27. package/dist/locale/en-US.js +20 -0
  28. package/dist/locale/zh-CN.d.ts +31 -0
  29. package/dist/locale/zh-CN.js +20 -0
  30. package/dist/navigation.d.ts +609 -0
  31. package/dist/navigation.js +1707 -0
  32. package/dist/overlay.d.ts +304 -0
  33. package/dist/overlay.js +969 -0
  34. package/dist/primitives.d.ts +268 -0
  35. package/dist/primitives.js +764 -0
  36. package/dist/styles.css +3 -0
  37. package/dist/theme-data.d.ts +363 -0
  38. package/dist/theme-data.js +374 -0
  39. package/dist/theme.d.ts +79 -0
  40. package/dist/theme.js +262 -0
  41. package/dist/tokens.css +449 -0
  42. package/dist/tree.d.ts +144 -0
  43. package/dist/tree.js +469 -0
  44. package/dist/virtual-list.d.ts +190 -0
  45. package/dist/virtual-list.js +521 -0
  46. package/dist/workbench.d.ts +136 -0
  47. package/dist/workbench.js +156 -0
  48. package/package.json +113 -0
package/dist/theme.js ADDED
@@ -0,0 +1,262 @@
1
+ /** @license MIT
2
+ * Copyright (c) 2026 vobsjs
3
+ * @vobs/ui
4
+ */
5
+ import { brandPresets, contrastRatio, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, resolveBrandColor, themeTokenValues, } from './theme-data.js';
6
+ export { brandPresets, contrastRatio, DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, normalizeHexColor, resolveBrandColor, } from './theme-data.js';
7
+ const brandVariableNames = [
8
+ '--bg-brand',
9
+ '--bg-brand-hover',
10
+ '--bg-brand-disabled',
11
+ '--bg-brand-popup',
12
+ '--bg-brand-overlay',
13
+ '--text-brand',
14
+ '--text-brand-hover',
15
+ '--icon-brand',
16
+ '--icon-brand-hover',
17
+ '--border-brand',
18
+ '--text-onbrand',
19
+ '--icon-onbrand',
20
+ '--color-primary',
21
+ '--color-primary-hover',
22
+ '--color-primary-disabled',
23
+ '--color-primary-soft',
24
+ '--color-accent',
25
+ '--color-on-primary',
26
+ ];
27
+ export function createThemeController(options) {
28
+ const listeners = new Set();
29
+ const persistedTheme = readPersistedTheme(options.persistence);
30
+ let followsSystem = persistedTheme === undefined && options.systemPreference !== undefined;
31
+ let theme = persistedTheme ?? options.systemPreference?.read() ?? options.initialTheme ?? DEFAULT_THEME;
32
+ let brand = readPersistedBrand(options.persistence, options.onWarning) ??
33
+ readBrand(options.initialBrand ?? DEFAULT_BRAND_ID, options.onWarning);
34
+ let stopSystemPreference;
35
+ let destroyed = false;
36
+ applyTheme(options.target, theme);
37
+ applyBrand(options.target, brand);
38
+ if (followsSystem) {
39
+ stopSystemPreference = options.systemPreference?.subscribe?.((nextTheme) => {
40
+ if (destroyed || !followsSystem)
41
+ return;
42
+ theme = nextTheme;
43
+ applyTheme(options.target, theme);
44
+ notify();
45
+ });
46
+ }
47
+ function state() {
48
+ return { theme, brand };
49
+ }
50
+ function notify() {
51
+ const value = state();
52
+ for (const listener of listeners)
53
+ listener(value);
54
+ }
55
+ function setTheme(nextTheme) {
56
+ assertTheme(nextTheme);
57
+ followsSystem = false;
58
+ stopSystemPreference?.();
59
+ stopSystemPreference = undefined;
60
+ theme = nextTheme;
61
+ applyTheme(options.target, theme);
62
+ options.persistence?.writeTheme?.(theme);
63
+ notify();
64
+ }
65
+ return {
66
+ get theme() {
67
+ return theme;
68
+ },
69
+ get brand() {
70
+ return brand;
71
+ },
72
+ get state() {
73
+ return state();
74
+ },
75
+ setTheme,
76
+ toggleTheme() {
77
+ const nextTheme = theme === 'dark' ? 'light' : 'dark';
78
+ setTheme(nextTheme);
79
+ return nextTheme;
80
+ },
81
+ setBrand(nextBrand) {
82
+ brand = readBrand(nextBrand, options.onWarning);
83
+ applyBrand(options.target, brand);
84
+ options.persistence?.writeBrand?.(brand);
85
+ notify();
86
+ return brand;
87
+ },
88
+ subscribe(listener) {
89
+ listeners.add(listener);
90
+ return () => listeners.delete(listener);
91
+ },
92
+ destroy() {
93
+ if (destroyed)
94
+ return;
95
+ destroyed = true;
96
+ followsSystem = false;
97
+ stopSystemPreference?.();
98
+ stopSystemPreference = undefined;
99
+ listeners.clear();
100
+ },
101
+ };
102
+ }
103
+ export function createStorageThemePersistence(storage, keys = {}) {
104
+ const themeKey = keys.theme ?? 'vobs-theme';
105
+ const brandKey = keys.brand ?? 'vobs-brand-color';
106
+ return {
107
+ readTheme() {
108
+ return storage.getItem(themeKey);
109
+ },
110
+ writeTheme(theme) {
111
+ storage.setItem(themeKey, theme);
112
+ },
113
+ readBrand() {
114
+ const stored = storage.getItem(brandKey);
115
+ if (stored === null)
116
+ return undefined;
117
+ try {
118
+ return JSON.parse(stored);
119
+ }
120
+ catch {
121
+ return stored;
122
+ }
123
+ },
124
+ writeBrand(brand) {
125
+ storage.setItem(brandKey, JSON.stringify(brand));
126
+ },
127
+ };
128
+ }
129
+ export function createMediaThemePreference(query) {
130
+ return {
131
+ read() {
132
+ return query.matches ? 'light' : 'dark';
133
+ },
134
+ subscribe(listener) {
135
+ const handleChange = (event) => {
136
+ listener(event.matches ? 'light' : 'dark');
137
+ };
138
+ query.addEventListener('change', handleChange);
139
+ return () => query.removeEventListener('change', handleChange);
140
+ },
141
+ };
142
+ }
143
+ export function createThemeState(theme = DEFAULT_THEME, brand = DEFAULT_BRAND_ID) {
144
+ assertTheme(theme);
145
+ return { theme, brand: resolveBrandColor(brand) };
146
+ }
147
+ export function createThemeAttributes(state) {
148
+ const attributes = {
149
+ 'data-theme': state.theme,
150
+ 'data-brand': state.brand.id,
151
+ ...(isPresetBrand(state.brand) ? {} : { style: serializeBrandStyle(state.brand) }),
152
+ };
153
+ return attributes;
154
+ }
155
+ export function createThemeBootstrapScript(state) {
156
+ const attributes = createThemeAttributes(state);
157
+ const variables = isPresetBrand(state.brand) ? {} : brandCssVariables(state.brand);
158
+ return `(function(){var d=document.documentElement;d.setAttribute("data-theme",${JSON.stringify(attributes['data-theme'])});d.setAttribute("data-brand",${JSON.stringify(attributes['data-brand'])});var v=${JSON.stringify(variables)};for(var k in v){d.style.setProperty(k,v[k])}})()`;
159
+ }
160
+ function readPersistedTheme(persistence) {
161
+ const value = persistence?.readTheme?.();
162
+ return value === 'dark' || value === 'light' ? value : undefined;
163
+ }
164
+ function readPersistedBrand(persistence, onWarning) {
165
+ const value = persistence?.readBrand?.();
166
+ try {
167
+ if (typeof value === 'string')
168
+ return readBrand(value, onWarning);
169
+ if (isBrandColorInput(value))
170
+ return readBrand(value, onWarning);
171
+ }
172
+ catch {
173
+ onWarning?.('Ignored invalid persisted brand color');
174
+ return undefined;
175
+ }
176
+ if (value !== undefined && value !== null)
177
+ onWarning?.('Ignored invalid persisted brand color');
178
+ return undefined;
179
+ }
180
+ function readBrand(value, onWarning) {
181
+ const brand = resolveBrandColor(value);
182
+ if (!isPresetBrand(brand)) {
183
+ const darkContrast = contrastRatio(brand.color, themeTokenValues.dark['--bg-base-default']);
184
+ const lightContrast = contrastRatio(brand.color, themeTokenValues.light['--bg-base-default']);
185
+ if (Math.min(darkContrast, lightContrast) < 3) {
186
+ onWarning?.(`Custom brand ${brand.color} has low contrast against a theme background`);
187
+ }
188
+ }
189
+ return brand;
190
+ }
191
+ function applyTheme(target, theme) {
192
+ target.setAttribute('data-theme', theme);
193
+ }
194
+ function applyBrand(target, brand) {
195
+ target.setAttribute('data-brand', brand.id);
196
+ if (isPresetBrand(brand)) {
197
+ for (const name of brandVariableNames)
198
+ target.style.removeProperty(name);
199
+ return;
200
+ }
201
+ for (const [name, value] of Object.entries(brandCssVariables(brand))) {
202
+ target.style.setProperty(name, value);
203
+ }
204
+ }
205
+ function brandCssVariables(brand) {
206
+ const tokens = deriveBrandTokens(brand.color);
207
+ return {
208
+ '--bg-brand': tokens.background,
209
+ '--bg-brand-hover': tokens.hover,
210
+ '--bg-brand-disabled': tokens.disabled,
211
+ '--bg-brand-popup': tokens.soft,
212
+ '--bg-brand-overlay': tokens.soft,
213
+ '--text-brand': tokens.background,
214
+ '--text-brand-hover': tokens.hover,
215
+ '--icon-brand': tokens.background,
216
+ '--icon-brand-hover': tokens.hover,
217
+ '--border-brand': tokens.background,
218
+ '--text-onbrand': tokens.onBrand,
219
+ '--icon-onbrand': tokens.onBrand,
220
+ '--color-primary': tokens.background,
221
+ '--color-primary-hover': tokens.hover,
222
+ '--color-primary-disabled': tokens.disabled,
223
+ '--color-primary-soft': tokens.soft,
224
+ '--color-accent': tokens.background,
225
+ '--color-on-primary': tokens.onBrand,
226
+ };
227
+ }
228
+ function serializeBrandStyle(brand) {
229
+ return Object.entries(brandCssVariables(brand))
230
+ .map(([name, value]) => `${name}:${value}`)
231
+ .join(';');
232
+ }
233
+ function isPresetBrand(brand) {
234
+ return brandPresets.some((preset) => preset.id === brand.id && preset.color === brand.color);
235
+ }
236
+ function isBrandColorInput(value) {
237
+ return (typeof value === 'object' &&
238
+ value !== null &&
239
+ 'color' in value &&
240
+ typeof value.color === 'string' &&
241
+ (!('id' in value) || value.id === undefined || typeof value.id === 'string') &&
242
+ (!('label' in value) || value.label === undefined || typeof value.label === 'string'));
243
+ }
244
+ function assertTheme(theme) {
245
+ if (theme !== 'dark' && theme !== 'light')
246
+ throw new TypeError(`Invalid theme: ${theme}`);
247
+ }
248
+ /**
249
+ * Reads a design-token value (CSS variable) for the active theme, for third-party adapters (contract ui-adapters.md §3.1).
250
+ * Data source: tokens.css variables on html[data-theme] (getComputedStyle reads the latest effective value).
251
+ * Returns undefined without a document (SSR/non-browser) or when the variable is undefined — adapters must degrade gracefully.
252
+ */
253
+ export function resolveUiToken(name) {
254
+ const doc = globalThis.document;
255
+ if (doc === undefined)
256
+ return undefined;
257
+ const value = doc.defaultView
258
+ ?.getComputedStyle(doc.documentElement)
259
+ .getPropertyValue(name)
260
+ .trim();
261
+ return value === undefined || value === '' ? undefined : value;
262
+ }
@@ -0,0 +1,449 @@
1
+ @layer vobs.tokens, vobs.base, vobs.components, vobs.utilities, vobs.application;
2
+ @layer vobs.tokens {
3
+ :root {
4
+ --radius-2: 2px;
5
+ --radius-4: 4px;
6
+ --radius-6: 6px;
7
+ --radius-8: 8px;
8
+ --radius-10: 10px;
9
+ --radius-full: 9999px;
10
+ --spacer-0: 0px;
11
+ --spacer-4: 4px;
12
+ --spacer-6: 6px;
13
+ --spacer-8: 8px;
14
+ --spacer-12: 12px;
15
+ --spacer-16: 16px;
16
+ --spacer-24: 24px;
17
+ --spacer-32: 32px;
18
+ --spacer-40: 40px;
19
+ --k-icon-xs: 14px;
20
+ --k-icon-sm: 16px;
21
+ --k-icon-md: 20px;
22
+ --k-icon-lg: 24px;
23
+ --font-family-default: SF Pro Text;
24
+ --font-family-heading: SF Pro;
25
+ --font-family-mono: JetBrains Mono;
26
+ --font-family-base: var(--font-family-default);
27
+ --font-family-heading-alias: var(--font-family-heading);
28
+ --font-family-mono-alias: var(--font-family-mono);
29
+ --body-xs-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
30
+ --body-xs-font-size: 10px;
31
+ --body-xs-font-weight: 400;
32
+ --body-xs-line-height: 14px;
33
+ --body-sm-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
34
+ --body-sm-font-size: 11px;
35
+ --body-sm-font-weight: 400;
36
+ --body-sm-line-height: 16px;
37
+ --body-sm-strong-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
38
+ --body-sm-strong-font-size: 11px;
39
+ --body-sm-strong-font-weight: 500;
40
+ --body-sm-strong-line-height: 16px;
41
+ --body-md-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
42
+ --body-md-font-size: 12px;
43
+ --body-md-font-weight: 400;
44
+ --body-md-line-height: 18px;
45
+ --body-md-strong-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
46
+ --body-md-strong-font-size: 12px;
47
+ --body-md-strong-font-weight: 500;
48
+ --body-md-strong-line-height: 18px;
49
+ --body-base-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
50
+ --body-base-font-size: 13px;
51
+ --body-base-font-weight: 400;
52
+ --body-base-line-height: 20px;
53
+ --body-base-strong-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
54
+ --body-base-strong-font-size: 13px;
55
+ --body-base-strong-font-weight: 500;
56
+ --body-base-strong-line-height: 20px;
57
+ --heading-3xs-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
58
+ --heading-3xs-font-size: 11px;
59
+ --heading-3xs-font-weight: 600;
60
+ --heading-3xs-line-height: 16px;
61
+ --heading-2xs-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
62
+ --heading-2xs-font-size: 12px;
63
+ --heading-2xs-font-weight: 600;
64
+ --heading-2xs-line-height: 18px;
65
+ --heading-xs-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
66
+ --heading-xs-font-size: 13px;
67
+ --heading-xs-font-weight: 600;
68
+ --heading-xs-line-height: 20px;
69
+ --heading-sm-font-family: "SF Pro Text", system-ui, -apple-system, sans-serif;
70
+ --heading-sm-font-size: 16px;
71
+ --heading-sm-font-weight: 600;
72
+ --heading-sm-line-height: 24px;
73
+ --heading-md-font-family: "SF Pro", system-ui, -apple-system, sans-serif;
74
+ --heading-md-font-size: 20px;
75
+ --heading-md-font-weight: 600;
76
+ --heading-md-line-height: 28px;
77
+ --heading-lg-font-family: "SF Pro", system-ui, -apple-system, sans-serif;
78
+ --heading-lg-font-size: 22px;
79
+ --heading-lg-font-weight: 600;
80
+ --heading-lg-line-height: 30px;
81
+ --heading-xl-font-family: "SF Pro", system-ui, -apple-system, sans-serif;
82
+ --heading-xl-font-size: 24px;
83
+ --heading-xl-font-weight: 600;
84
+ --heading-xl-line-height: 32px;
85
+ --heading-2xl-font-family: "SF Pro", system-ui, -apple-system, sans-serif;
86
+ --heading-2xl-font-size: 28px;
87
+ --heading-2xl-font-weight: 600;
88
+ --heading-2xl-line-height: 36px;
89
+ --heading-3xl-font-family: "SF Pro", system-ui, -apple-system, sans-serif;
90
+ --heading-3xl-font-size: 32px;
91
+ --heading-3xl-font-weight: 600;
92
+ --heading-3xl-line-height: 40px;
93
+ --code-editor-font-family: "JetBrains Mono", system-ui, -apple-system, sans-serif;
94
+ --code-editor-font-size: 13px;
95
+ --code-editor-font-weight: 450;
96
+ --code-editor-line-height: 20px;
97
+ --code-terminal-font-family: "JetBrains Mono", system-ui, -apple-system, sans-serif;
98
+ --code-terminal-font-size: 12px;
99
+ --code-terminal-font-weight: 450;
100
+ --code-terminal-line-height: 18px;
101
+ --font-weight-default: 400;
102
+ --font-weight-code: 450;
103
+ --font-weight-medium: 500;
104
+ --font-weight-strong: 600;
105
+ --z-index-dropdown: 2000;
106
+ --z-index-drawer: 2500;
107
+ --z-index-modal: 3000;
108
+ --z-index-notification: 3500;
109
+ --z-index-tooltip: 4000;
110
+ --transition-fast: 0.12s ease;
111
+ --transition-normal: 0.2s ease;
112
+ --transition-slow: 0.3s ease;
113
+ --breakpoint-sm: 576px;
114
+ --breakpoint-md: 768px;
115
+ --breakpoint-lg: 1024px;
116
+ --breakpoint-xl: 1280px;
117
+ }
118
+
119
+ :root,
120
+ [data-theme="dark"] {
121
+ color-scheme: dark;
122
+ --bg-base-default: #1A1B1D;
123
+ --bg-base-secondary: #222427;
124
+ --bg-base-tertiary: #2A2D31;
125
+ --bg-tooltip: #1A1B1D;
126
+ --bg-menu: #202123;
127
+ --bg-invert: #DADDE5;
128
+ --bg-invert-hover: #EDEFF2;
129
+ --bg-invert-active: #979AA4;
130
+ --bg-invert-disabled: rgba(224, 226, 242, 0.12);
131
+ --bg-overlay-l1: rgba(224, 226, 242, 0.04);
132
+ --bg-overlay-l2: rgba(224, 226, 242, 0.06);
133
+ --bg-overlay-l3: rgba(224, 226, 242, 0.08);
134
+ --bg-overlay-l4: rgba(224, 226, 242, 0.12);
135
+ --text-default: #D1D3DB;
136
+ --text-default-hover: #F5F9FE;
137
+ --text-default-active: #F5F9FE;
138
+ --text-secondary: #9599A6;
139
+ --text-secondary-hover: #D1D3DB;
140
+ --text-secondary-active: #D1D3DB;
141
+ --text-tertiary: #666B75;
142
+ --text-disabled: #666B75;
143
+ --text-onbrand: #0C0C0D;
144
+ --text-onaccent: #0C0C0D;
145
+ --icon-default: #D1D3DB;
146
+ --icon-default-hover: #F5F9FE;
147
+ --icon-default-active: #F5F9FE;
148
+ --icon-secondary: #9599A6;
149
+ --icon-secondary-hover: #D1D3DB;
150
+ --icon-secondary-active: #D1D3DB;
151
+ --icon-tertiary: #666B75;
152
+ --icon-disabled: #666B75;
153
+ --icon-onbrand: #0C0C0D;
154
+ --icon-onaccent: #0C0C0D;
155
+ --border-neutral-l1: rgba(224, 226, 242, 0.1);
156
+ --border-neutral-l2: rgba(224, 226, 242, 0.16);
157
+ --border-neutral-l3: rgba(224, 226, 242, 0.2);
158
+ --border-contrast: #FFFFFF;
159
+ --status-primary-default: #387BFF;
160
+ --status-primary-hover: #4C88FF;
161
+ --status-primary-active: #1759DD;
162
+ --status-primary-surface-l1: rgba(53, 121, 255, 0.18);
163
+ --status-primary-surface-l2: rgba(53, 121, 255, 0.28);
164
+ --status-primary-surface-l3: rgba(53, 121, 255, 0.36);
165
+ --status-info-default: var(--status-primary-default);
166
+ --status-info-surface-l1: var(--status-primary-surface-l1);
167
+ --status-success-default: #33C192;
168
+ --status-success-hover: #5ED4AD;
169
+ --status-success-active: #27B082;
170
+ --status-success-surface-l1: rgba(0, 165, 110, 0.18);
171
+ --status-success-surface-l2: rgba(0, 165, 110, 0.28);
172
+ --status-success-surface-l3: rgba(0, 165, 110, 0.36);
173
+ --status-alert-default: #D29D00;
174
+ --status-alert-hover: #DFB949;
175
+ --status-alert-active: #AB8820;
176
+ --status-alert-surface-l1: rgba(210, 157, 0, 0.16);
177
+ --status-alert-surface-l2: rgba(210, 157, 0, 0.28);
178
+ --status-alert-surface-l3: rgba(210, 157, 0, 0.36);
179
+ --status-warning-default: #D27E24;
180
+ --status-warning-hover: #D78B28;
181
+ --status-warning-active: #B46510;
182
+ --status-warning-surface-l1: rgba(210, 126, 36, 0.16);
183
+ --status-warning-surface-l2: rgba(210, 126, 36, 0.28);
184
+ --status-warning-surface-l3: rgba(210, 126, 36, 0.36);
185
+ --status-error-default: #F65A5A;
186
+ --status-error-hover: #F86262;
187
+ --status-error-active: #B33636;
188
+ --status-error-surface-l1: rgba(246, 70, 70, 0.18);
189
+ --status-error-surface-l2: rgba(246, 70, 70, 0.28);
190
+ --status-error-surface-l3: rgba(246, 70, 70, 0.36);
191
+ --code-text: #E0E3EE;
192
+ --code-doc: #7F838C;
193
+ --code-link: #3C7EFF;
194
+ --code-number: #F48CCA;
195
+ --code-action: #B38CFF;
196
+ --code-instruction: #F0D8FF;
197
+ --code-function: #F29D79;
198
+ --code-constant: #80BBFF;
199
+ --code-parameter: #82D99F;
200
+ --code-attribute: #DED47E;
201
+ --code-tag: #F2858C;
202
+ --color-background: var(--bg-base-default);
203
+ --color-surface: var(--bg-base-secondary);
204
+ --color-surface-variant: var(--bg-base-tertiary);
205
+ --color-overlay-1: var(--bg-overlay-l1);
206
+ --color-overlay-2: var(--bg-overlay-l2);
207
+ --color-overlay-3: var(--bg-overlay-l3);
208
+ --color-overlay-4: var(--bg-overlay-l4);
209
+ --color-card: var(--bg-base-secondary);
210
+ --color-tooltip: var(--bg-tooltip);
211
+ --color-menu: var(--bg-menu);
212
+ --color-foreground: var(--text-default);
213
+ --color-foreground-hover: var(--text-default-hover);
214
+ --color-on-surface: var(--text-default);
215
+ --color-on-surface-variant: var(--text-secondary);
216
+ --color-muted-foreground: var(--text-secondary);
217
+ --color-disabled-foreground: var(--text-disabled);
218
+ --color-border: var(--border-neutral-l1);
219
+ --color-border-strong: var(--border-neutral-l2);
220
+ --color-border-stronger: var(--border-neutral-l3);
221
+ --color-border-contrast: var(--border-contrast);
222
+ --color-outline: var(--border-neutral-l1);
223
+ --color-primary: var(--bg-brand);
224
+ --color-primary-hover: var(--bg-brand-hover);
225
+ --color-primary-disabled: var(--bg-brand-disabled);
226
+ --color-primary-soft: var(--bg-brand-popup);
227
+ --color-accent: var(--bg-brand);
228
+ --color-on-primary: var(--text-onbrand);
229
+ --color-info: var(--status-primary-default);
230
+ --color-success: var(--status-success-default);
231
+ --color-warning: var(--status-warning-default);
232
+ --color-error: var(--status-error-default);
233
+ --color-error-soft: var(--status-error-surface-l1);
234
+ }
235
+
236
+ [data-theme="light"] {
237
+ color-scheme: light;
238
+ --bg-base-default: #FFFFFF;
239
+ --bg-base-secondary: #F5F6F8;
240
+ --bg-base-tertiary: #EDF0F5;
241
+ --bg-overlay-l1: rgba(0, 0, 0, 0.04);
242
+ --bg-overlay-l2: rgba(0, 0, 0, 0.06);
243
+ --bg-overlay-l3: rgba(0, 0, 0, 0.08);
244
+ --bg-overlay-l4: rgba(0, 0, 0, 0.12);
245
+ --text-default: #0F1117;
246
+ --text-secondary: #4B5563;
247
+ --text-tertiary: #5B6370;
248
+ --text-disabled: #525A68;
249
+ --text-onbrand: #FFFFFF;
250
+ --icon-default: #0F1117;
251
+ --icon-secondary: #4B5563;
252
+ --icon-tertiary: #5B6370;
253
+ --icon-disabled: #525A68;
254
+ --border-neutral-l1: rgba(0, 0, 0, 0.12);
255
+ --border-neutral-l2: rgba(0, 0, 0, 0.18);
256
+ --border-neutral-l3: rgba(0, 0, 0, 0.25);
257
+ --status-success-default: #16A34A;
258
+ --status-warning-default: #CA8A04;
259
+ --status-error-default: #DC2626;
260
+ --status-info-default: #2E69FF;
261
+ --status-success-surface-l1: rgba(22, 163, 74, 0.08);
262
+ --status-warning-surface-l1: rgba(202, 138, 4, 0.08);
263
+ --status-error-surface-l1: rgba(220, 38, 38, 0.08);
264
+ --status-info-surface-l1: rgba(46, 105, 255, 0.08);
265
+ --color-background: var(--bg-base-default);
266
+ --color-surface: var(--bg-base-secondary);
267
+ --color-surface-variant: var(--bg-base-tertiary);
268
+ --color-overlay-1: var(--bg-overlay-l1);
269
+ --color-overlay-2: var(--bg-overlay-l2);
270
+ --color-overlay-3: var(--bg-overlay-l3);
271
+ --color-overlay-4: var(--bg-overlay-l4);
272
+ --color-card: var(--bg-base-secondary);
273
+ --color-tooltip: var(--bg-tooltip);
274
+ --color-menu: var(--bg-menu);
275
+ --color-foreground: var(--text-default);
276
+ --color-foreground-hover: var(--text-default-hover);
277
+ --color-on-surface: var(--text-default);
278
+ --color-on-surface-variant: var(--text-secondary);
279
+ --color-muted-foreground: var(--text-secondary);
280
+ --color-disabled-foreground: var(--text-disabled);
281
+ --color-border: var(--border-neutral-l1);
282
+ --color-border-strong: var(--border-neutral-l2);
283
+ --color-border-stronger: var(--border-neutral-l3);
284
+ --color-border-contrast: var(--border-contrast);
285
+ --color-outline: var(--border-neutral-l1);
286
+ --color-primary: var(--bg-brand);
287
+ --color-primary-hover: var(--bg-brand-hover);
288
+ --color-primary-disabled: var(--bg-brand-disabled);
289
+ --color-primary-soft: var(--bg-brand-popup);
290
+ --color-accent: var(--bg-brand);
291
+ --color-on-primary: var(--text-onbrand);
292
+ --color-info: var(--status-primary-default);
293
+ --color-success: var(--status-success-default);
294
+ --color-warning: var(--status-warning-default);
295
+ --color-error: var(--status-error-default);
296
+ --color-error-soft: var(--status-error-surface-l1);
297
+ }
298
+
299
+ :root,
300
+ [data-brand="green"] {
301
+ --bg-brand: #32F08C;
302
+ --bg-brand-hover: #0FDC78;
303
+ --bg-brand-disabled: rgba(50, 240, 140, 0.2);
304
+ --bg-brand-popup: rgba(50, 240, 140, 0.12);
305
+ --bg-brand-overlay: rgba(50, 240, 140, 0.12);
306
+ --text-brand: #32F08C;
307
+ --text-brand-hover: #0FDC78;
308
+ --icon-brand: #32F08C;
309
+ --icon-brand-hover: #0FDC78;
310
+ --border-brand: #32F08C;
311
+ --text-onbrand: #0C0C0D;
312
+ --icon-onbrand: #0C0C0D;
313
+ }
314
+
315
+ [data-brand="blue"] {
316
+ --bg-brand: #80C1FF;
317
+ --bg-brand-hover: #6EA6DB;
318
+ --bg-brand-disabled: rgba(128, 193, 255, 0.3);
319
+ --bg-brand-popup: rgba(128, 193, 255, 0.12);
320
+ --bg-brand-overlay: rgba(128, 193, 255, 0.12);
321
+ --text-brand: #80C1FF;
322
+ --text-brand-hover: #6EA6DB;
323
+ --icon-brand: #80C1FF;
324
+ --icon-brand-hover: #6EA6DB;
325
+ --border-brand: #80C1FF;
326
+ --text-onbrand: #0C0C0D;
327
+ --icon-onbrand: #0C0C0D;
328
+ }
329
+
330
+ [data-brand="purple"] {
331
+ --bg-brand: #8E80FF;
332
+ --bg-brand-hover: #9E92FF;
333
+ --bg-brand-disabled: rgba(142, 128, 255, 0.3);
334
+ --bg-brand-popup: rgba(142, 128, 255, 0.12);
335
+ --bg-brand-overlay: rgba(142, 128, 255, 0.12);
336
+ --text-brand: #8E80FF;
337
+ --text-brand-hover: #9E92FF;
338
+ --icon-brand: #8E80FF;
339
+ --icon-brand-hover: #9E92FF;
340
+ --border-brand: #8E80FF;
341
+ --text-onbrand: #0C0C0D;
342
+ --icon-onbrand: #0C0C0D;
343
+ }
344
+
345
+ [data-brand="yellow"] {
346
+ --bg-brand: #FFD080;
347
+ --bg-brand-hover: #DBB36E;
348
+ --bg-brand-disabled: rgba(255, 208, 128, 0.3);
349
+ --bg-brand-popup: rgba(255, 208, 128, 0.12);
350
+ --bg-brand-overlay: rgba(255, 208, 128, 0.12);
351
+ --text-brand: #FFD080;
352
+ --text-brand-hover: #DBB36E;
353
+ --icon-brand: #FFD080;
354
+ --icon-brand-hover: #DBB36E;
355
+ --border-brand: #FFD080;
356
+ --text-onbrand: #0C0C0D;
357
+ --icon-onbrand: #0C0C0D;
358
+ }
359
+
360
+ [data-brand="red"] {
361
+ --bg-brand: #FF8080;
362
+ --bg-brand-hover: #DB6E6E;
363
+ --bg-brand-disabled: rgba(255, 128, 128, 0.3);
364
+ --bg-brand-popup: rgba(255, 128, 128, 0.12);
365
+ --bg-brand-overlay: rgba(255, 128, 128, 0.12);
366
+ --text-brand: #FF8080;
367
+ --text-brand-hover: #DB6E6E;
368
+ --icon-brand: #FF8080;
369
+ --icon-brand-hover: #DB6E6E;
370
+ --border-brand: #FF8080;
371
+ --text-onbrand: #0C0C0D;
372
+ --icon-onbrand: #0C0C0D;
373
+ }
374
+
375
+ [data-brand="teal"] {
376
+ --bg-brand: #2DD288;
377
+ --bg-brand-hover: #27B575;
378
+ --bg-brand-disabled: rgba(45, 210, 136, 0.3);
379
+ --bg-brand-popup: rgba(45, 210, 136, 0.12);
380
+ --bg-brand-overlay: rgba(45, 210, 136, 0.12);
381
+ --text-brand: #2DD288;
382
+ --text-brand-hover: #27B575;
383
+ --icon-brand: #2DD288;
384
+ --icon-brand-hover: #27B575;
385
+ --border-brand: #2DD288;
386
+ --text-onbrand: #0C0C0D;
387
+ --icon-onbrand: #0C0C0D;
388
+ }
389
+
390
+ [data-brand="cyan"] {
391
+ --bg-brand: #04CBE5;
392
+ --bg-brand-hover: #27D2E9;
393
+ --bg-brand-disabled: rgba(4, 203, 229, 0.3);
394
+ --bg-brand-popup: rgba(4, 203, 229, 0.12);
395
+ --bg-brand-overlay: rgba(4, 203, 229, 0.12);
396
+ --text-brand: #04CBE5;
397
+ --text-brand-hover: #27D2E9;
398
+ --icon-brand: #04CBE5;
399
+ --icon-brand-hover: #27D2E9;
400
+ --border-brand: #04CBE5;
401
+ --text-onbrand: #0C0C0D;
402
+ --icon-onbrand: #0C0C0D;
403
+ }
404
+
405
+ [data-brand="violet"] {
406
+ --bg-brand: #BFA5FF;
407
+ --bg-brand-hover: #A48EDB;
408
+ --bg-brand-disabled: rgba(191, 165, 255, 0.3);
409
+ --bg-brand-popup: rgba(191, 165, 255, 0.12);
410
+ --bg-brand-overlay: rgba(191, 165, 255, 0.12);
411
+ --text-brand: #BFA5FF;
412
+ --text-brand-hover: #A48EDB;
413
+ --icon-brand: #BFA5FF;
414
+ --icon-brand-hover: #A48EDB;
415
+ --border-brand: #BFA5FF;
416
+ --text-onbrand: #0C0C0D;
417
+ --icon-onbrand: #0C0C0D;
418
+ }
419
+
420
+ [data-brand="slate"] {
421
+ --bg-brand: #AFB9CF;
422
+ --bg-brand-hover: #979FB2;
423
+ --bg-brand-disabled: rgba(175, 185, 207, 0.3);
424
+ --bg-brand-popup: rgba(175, 185, 207, 0.12);
425
+ --bg-brand-overlay: rgba(175, 185, 207, 0.12);
426
+ --text-brand: #AFB9CF;
427
+ --text-brand-hover: #979FB2;
428
+ --icon-brand: #AFB9CF;
429
+ --icon-brand-hover: #979FB2;
430
+ --border-brand: #AFB9CF;
431
+ --text-onbrand: #0C0C0D;
432
+ --icon-onbrand: #0C0C0D;
433
+ }
434
+
435
+ [data-brand="neutral"] {
436
+ --bg-brand: #BABABA;
437
+ --bg-brand-hover: #A0A0A0;
438
+ --bg-brand-disabled: rgba(186, 186, 186, 0.3);
439
+ --bg-brand-popup: rgba(186, 186, 186, 0.12);
440
+ --bg-brand-overlay: rgba(186, 186, 186, 0.12);
441
+ --text-brand: #BABABA;
442
+ --text-brand-hover: #A0A0A0;
443
+ --icon-brand: #BABABA;
444
+ --icon-brand-hover: #A0A0A0;
445
+ --border-brand: #BABABA;
446
+ --text-onbrand: #0C0C0D;
447
+ --icon-onbrand: #0C0C0D;
448
+ }
449
+ }