@filipgutica/ui 1.0.0 → 1.1.1

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 CHANGED
@@ -1,7 +1,11 @@
1
1
  # @filipgutica/ui
2
2
 
3
- A compact Vue 3.5+ design system built on [Reka UI](https://reka-ui.com), with
4
- Tailwind CSS 4 tokens and safe VS Code/Open VSX color-theme normalization.
3
+ Compact Vue 3.5+ components built on [Reka UI](https://reka-ui.com), with
4
+ Tailwind CSS 4 and VS Code theme support.
5
+
6
+ [Docs and playground](https://filipgutica.github.io/ui/) ·
7
+ [GitHub](https://github.com/filipgutica/ui) ·
8
+ [npm](https://www.npmjs.com/package/@filipgutica/ui)
5
9
 
6
10
  ## Install
7
11
 
@@ -9,7 +13,7 @@ Tailwind CSS 4 tokens and safe VS Code/Open VSX color-theme normalization.
9
13
  pnpm add @filipgutica/ui
10
14
  ```
11
15
 
12
- Import Tailwind and the shared theme files from your application stylesheet:
16
+ Import the styles from your application stylesheet:
13
17
 
14
18
  ```css
15
19
  @import "tailwindcss";
@@ -17,93 +21,27 @@ Import Tailwind and the shared theme files from your application stylesheet:
17
21
  @import "@filipgutica/ui/components.css";
18
22
  ```
19
23
 
20
- The theme exposes Tailwind utilities such as `bg-ui-bg`, `bg-ui-surface`,
21
- `text-ui-text`, `text-ui-muted`, `border-ui-border`, and `text-ui-error`.
22
-
23
- ## Vue components
24
-
25
- The first application-focused set includes:
26
-
27
- - `UiButton` with primary, secondary, ghost, danger, and text variants
28
- - `UiInput`, `UiSelect`, and `UiField` for consistent form controls
29
- - `UiCheckbox`, `UiSlider`, `UiRadioCard`, and `UiRadioCardGroup` for user input
30
- - `UiBadge`, `UiAlert`, and `UiProgress` for state and feedback
31
- - `UiCard` for structured content, actions, and footer metadata
32
- - `UiCodeBlock` for copyable, theme-aware source snippets
33
- - `UiDialog`, built on Reka UI, for accessible modal interaction
34
-
35
- Place `UiInput` or `UiSelect` inside `UiField`. The field supplies the control ID
36
- and automatically connects its description or error through the corresponding
37
- ARIA relationship.
24
+ ## Use
38
25
 
39
26
  ```vue
27
+ <script setup lang="ts">
28
+ import { UiButton } from '@filipgutica/ui'
29
+ </script>
30
+
40
31
  <template>
41
32
  <UiButton variant="secondary" size="sm">
42
- Inspect evidence
33
+ Save changes
43
34
  </UiButton>
44
35
  </template>
45
-
46
- <script setup lang="ts">
47
- import { UiButton } from '@filipgutica/ui'
48
- </script>
49
36
  ```
50
37
 
51
- `UiButton`, `UiInput`, `UiSelect`, `UiCheckbox`, and `UiSlider` share
52
- `size="sm | md | lg"`
53
- and default to the tighter `md` density. Existing `UiButton` values remain
54
- compatible: `compact` retains its former compact treatment and `default` maps
55
- to `lg`.
38
+ The [component docs](https://filipgutica.github.io/ui/#/components/button)
39
+ cover examples, props, slots, and events. Place inputs and selects inside
40
+ `UiField` to connect labels, descriptions, and errors automatically.
56
41
 
57
- `UiCodeBlock` accepts source text through `code`, shows a copy action by default,
58
- and highlights the selected language using the active theme. It can display a
59
- title, line numbers, or wrapped lines; unknown languages stay readable as plain text:
42
+ ## Themes
60
43
 
61
- ```vue
62
- <UiCodeBlock
63
- title="Example.vue"
64
- language="vue"
65
- :code="snippet"
66
- :line-numbers="true"
67
- />
68
- ```
69
-
70
- Highlighting supports Vue, JavaScript (`js`), TypeScript (`ts`), HTML, CSS,
71
- JSON, and Bash (`sh`/`shell`). Imported TextMate `tokenColors` are normalized
72
- into a shared syntax palette; language-specific overrides and font styles are
73
- not reproduced exactly. Themes saved before syntax support should be re-imported
74
- to recover their syntax colors. Existing saved themes remain usable with themed fallbacks.
75
-
76
- `UiSurface` remains exported for compatibility. New structured containers
77
- should use `UiCard`.
78
-
79
- ## Design conventions
80
-
81
- Use a compact, Geist-inspired hierarchy: 14px for UI body text, 13px for
82
- secondary text, and 18px for dialog titles. Treat Open VSX/VS Code themes as
83
- the color authority, and use semantic tokens and package components instead of
84
- hard-coded provider color keys.
85
- Typography is package-owned through `--font-ui` and `--font-mono`; override
86
- these once at the application root rather than restyling each component.
87
-
88
- - Use shared control sizes `sm`, `md`, and `lg` (32px, 36px, and 44px); the
89
- default is `md`. Keep layout on a 4px rhythm, with 12px, 16px, and 24px as
90
- common gaps and insets.
91
- - Choose `UiCard` for structured content and optional actions or footer data.
92
- Choose `UiRadioCardGroup` with `UiRadioCard` for one-of-many rich options;
93
- choose `UiDialog` for modal tasks that need focus management.
94
- - Use one primary action per task, secondary buttons for supporting actions,
95
- and danger styling only for destructive actions. Use `UiBadge` for a short
96
- status, `UiAlert` for feedback, and `UiCodeBlock` for source code.
97
- - Put `UiInput` and `UiSelect` in `UiField` with a visible label. Supply help
98
- text or an error when needed so the field exposes the matching ARIA relationship.
99
- - Keep borders quiet and skip decorative grids. Preserve visible
100
- `:focus-visible` states, use 44px targets for touch-oriented actions, and provide
101
- an accessible name for every interactive control.
102
-
103
- ## VS Code themes
104
-
105
- The browser-safe theme entry point parses VS Code JSON/JSONC and maps supported
106
- workbench colors into the package's finite semantic token contract:
44
+ Import a VS Code JSON or JSONC theme in the browser:
107
45
 
108
46
  ```ts
109
47
  import { applySemanticTheme, parseVsCodeTheme } from '@filipgutica/ui/theme'
@@ -112,73 +50,14 @@ const theme = parseVsCodeTheme({ source, fileName })
112
50
  applySemanticTheme({ root: document.documentElement, theme })
113
51
  ```
114
52
 
115
- The Node-only Open VSX entry point searches and imports theme extensions without
116
- executing extension code:
117
-
118
- ```ts
119
- import { createOpenVsxThemeService } from '@filipgutica/ui/open-vsx'
120
-
121
- const themes = await createOpenVsxThemeService().search('Catppuccin')
122
- ```
123
-
124
- Open VSX packages are untrusted input. The importer restricts origins, validates
125
- identifiers and archive paths, caps downloaded and expanded sizes, checks the
126
- advertised SHA-256 checksum, and retains only normalized colors. Consumers that
127
- redistribute theme assets remain responsible for their licenses.
128
-
129
- ## Boundaries
130
-
131
- - Open VSX themes control color and light/dark/high-contrast appearance only.
132
- - Typography, spacing, radius, motion, and component structure remain owned by
133
- this package so applications keep a consistent design language.
134
- - `@filipgutica/ui/open-vsx` is Node-only. Do not import it into browser bundles.
135
-
136
- ## Docs and sandbox
137
-
138
- Start the component docs and sandbox:
139
-
140
- ```sh
141
- pnpm docs:dev
142
- ```
143
-
144
- Build the provider-neutral static assets:
145
-
146
- ```sh
147
- pnpm docs:build
148
- ```
149
-
150
- The docs use hash routes, so the static assets do not require rewrite rules.
151
- The local Vite server also provides the same-origin `/api/open-vsx` endpoint.
152
- The theme picker uses this endpoint to search and import Open VSX themes.
153
-
154
- A production host must provide the same API endpoint for live Open VSX imports.
155
- Netlify and Amplify can use a serverless adapter. GitHub Pages needs an external
156
- API or a catalog of normalized themes built in advance.
53
+ Themes supply colors; the library keeps typography, spacing, and component
54
+ structure consistent. Open VSX search and imports are available through
55
+ `@filipgutica/ui/open-vsx`, which must run on a Node server.
157
56
 
158
57
  ## Development
159
58
 
160
59
  ```sh
161
60
  pnpm install
61
+ pnpm docs:dev
162
62
  pnpm verify
163
63
  ```
164
-
165
- Commits follow the Conventional Commits format. Releases run from `main`:
166
-
167
- - `fix:` publishes a patch release
168
- - `feat:` publishes a minor release
169
- - `feat!:` publishes a major release
170
- - `BREAKING CHANGE:` or `[BREAKING CHANGE]` anywhere in a commit body publishes
171
- a major release
172
- - the same markers anywhere in an associated merged PR body publish a major
173
- release
174
-
175
- The `release.yml` workflow runs on every push to `main`. When semantic-release
176
- finds qualifying commits, it publishes the next version to npm, creates the
177
- matching `v<version>` tag, and creates a GitHub Release. Configure an `NPM_TOKEN`
178
- Actions secret with permission to publish `@filipgutica/ui`; contributors do not
179
- publish locally or add a token to the repository.
180
-
181
- Before the first token-backed release, remove the package's existing trusted
182
- publisher in npm. The workflow retains `id-token: write` only for the provenance
183
- attestations enabled in `package.json`; npm registry authentication comes from
184
- the `NPM_TOKEN` secret.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@filipgutica/ui",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "A compact Vue design system with Tailwind CSS and VS Code theme support",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -4,9 +4,9 @@
4
4
  .fg-radio-card, .fg-badge, .fg-alert, .fg-surface, .fg-card,
5
5
  .fg-dialog__content, .fg-code-block {
6
6
  font-family: var(--font-ui);
7
- font-size: 0.875rem;
8
- font-weight: 400;
9
- line-height: 1.5;
7
+ font-size: var(--text-md);
8
+ font-weight: var(--weight-regular);
9
+ line-height: var(--leading);
10
10
  }
11
11
 
12
12
  .fg-code-block {
@@ -62,12 +62,7 @@
62
62
  border: 1px solid transparent;
63
63
  border-radius: var(--radius-control);
64
64
  font-family: var(--font-ui);
65
- transition:
66
- background-color var(--duration-fast) ease,
67
- border-color var(--duration-fast) ease,
68
- color var(--duration-fast) ease,
69
- box-shadow var(--duration-fast) ease,
70
- transform var(--duration-fast) ease;
65
+ transition: transform var(--duration-fast) var(--ease-out);
71
66
  }
72
67
 
73
68
  .fg-button {
@@ -133,15 +128,15 @@
133
128
  font-size: 1rem;
134
129
  }
135
130
 
136
- .fg-button[data-size="sm"] { min-height: 2rem; }
137
- .fg-button[data-size="md"] { min-height: 2.25rem; }
138
- .fg-button[data-size="lg"] { min-height: 2.75rem; }
131
+ .fg-button[data-size="sm"] { min-height: var(--control-sm); }
132
+ .fg-button[data-size="md"] { min-height: var(--control-md); }
133
+ .fg-button[data-size="lg"] { min-height: var(--control-lg); }
139
134
  .fg-input[data-size="sm"],
140
- .fg-select[data-size="sm"] { height: 2rem; }
135
+ .fg-select[data-size="sm"] { height: var(--control-sm); }
141
136
  .fg-input[data-size="md"],
142
- .fg-select[data-size="md"] { height: 2.25rem; }
137
+ .fg-select[data-size="md"] { height: var(--control-md); }
143
138
  .fg-input[data-size="lg"],
144
- .fg-select[data-size="lg"] { height: 2.75rem; }
139
+ .fg-select[data-size="lg"] { height: var(--control-lg); }
145
140
 
146
141
  .fg-button[data-size="sm"] { padding: 0 0.6rem; }
147
142
  .fg-button[data-size="md"] { padding: 0 0.75rem; }
@@ -149,13 +144,13 @@
149
144
 
150
145
  /* Deprecated UiButton aliases retained for existing consumers. */
151
146
  .fg-button[data-size="compact"] {
152
- min-height: 2.25rem;
147
+ min-height: var(--control-md);
153
148
  padding: 0 0.7rem;
154
149
  font-size: 0.8125rem;
155
150
  }
156
151
 
157
152
  .fg-button[data-size="default"] {
158
- min-height: 2.75rem;
153
+ min-height: var(--control-lg);
159
154
  padding: 0 1rem;
160
155
  font-size: 1rem;
161
156
  }
@@ -163,7 +158,7 @@
163
158
  .fg-button[data-variant="secondary"] {
164
159
  border-color: var(--color-border);
165
160
  color: var(--color-text);
166
- background: var(--color-surface-raised);
161
+ background: transparent;
167
162
  }
168
163
 
169
164
  .fg-button[data-variant="secondary"]:hover:not(:disabled),
@@ -188,7 +183,7 @@
188
183
  border-color: var(--color-error);
189
184
  color: var(--color-error);
190
185
  background: var(--color-error-surface);
191
- box-shadow: inset 0 0 0 1px var(--color-error);
186
+ box-shadow: none;
192
187
  }
193
188
 
194
189
  .fg-button[data-variant="text"] {
@@ -229,6 +224,61 @@
229
224
  background-size: 0.3rem 0.3rem;
230
225
  }
231
226
 
227
+ /* Keep native form semantics; older browsers retain the native picker. */
228
+ @supports (appearance: base-select) {
229
+ .fg-select:not([multiple]):not([size]),
230
+ .fg-select:not([multiple]):not([size])::picker(select) {
231
+ appearance: base-select;
232
+ }
233
+ .fg-select:not([multiple]):not([size]) {
234
+ position: relative;
235
+ align-items: center;
236
+ background-image: none;
237
+ cursor: pointer;
238
+ }
239
+ .fg-select:not([multiple]):not([size]):disabled { cursor: not-allowed; }
240
+ .fg-select:not([multiple]):not([size])::picker-icon { display: none; }
241
+ .fg-select:not([multiple]):not([size])::after {
242
+ position: absolute;
243
+ right: var(--space-3);
244
+ width: var(--space-2);
245
+ height: var(--space-2);
246
+ border-right: 1.5px solid var(--color-muted);
247
+ border-bottom: 1.5px solid var(--color-muted);
248
+ transform: translateY(-2px) rotate(45deg);
249
+ content: "";
250
+ }
251
+ .fg-select:not([multiple]):not([size])::picker(select) {
252
+ min-width: anchor-size(width);
253
+ max-height: min(20rem, 50dvh);
254
+ overflow: auto;
255
+ margin-block: var(--space-1);
256
+ padding: var(--space-1);
257
+ border: 1px solid var(--color-border-subtle);
258
+ border-radius: var(--radius-panel);
259
+ color: var(--color-text);
260
+ background: var(--color-input-bg);
261
+ box-shadow: var(--shadow-dialog);
262
+ font: var(--weight-regular) var(--text-md) / var(--leading) var(--font-ui);
263
+ }
264
+ .fg-select:not([multiple]):not([size]) option {
265
+ min-height: var(--control-sm);
266
+ gap: var(--space-2);
267
+ padding: var(--space-2) var(--space-3);
268
+ border-radius: var(--radius-control);
269
+ color: var(--color-text);
270
+ background: transparent;
271
+ cursor: pointer;
272
+ }
273
+ .fg-select:not([multiple]):not([size]) option:checked { color: var(--color-row-selected-text); background: var(--color-row-selected); }
274
+ .fg-select:not([multiple]):not([size]) option:hover:not(:disabled), .fg-select:not([multiple]):not([size]) option:focus-visible { background: var(--color-row-hover); outline: 2px solid var(--color-focus); outline-offset: -2px; }
275
+ .fg-select:not([multiple]):not([size]) option:disabled { color: var(--color-muted); opacity: 0.58; cursor: not-allowed; }
276
+ .fg-select:not([multiple]):not([size]) option::checkmark { order: 1; margin-left: auto; color: var(--color-link); }
277
+ @media (pointer: coarse) {
278
+ .fg-select:not([multiple]):not([size]) option { min-height: var(--control-lg); }
279
+ }
280
+ }
281
+
232
282
  .fg-input[data-size="sm"] { padding: 0 0.55rem; }
233
283
  .fg-input[data-size="md"] { padding: 0 0.65rem; }
234
284
  .fg-input[data-size="lg"] { padding: 0 0.7rem; }
@@ -304,21 +354,21 @@
304
354
  .fg-checkbox__label { line-height: 1.4; }
305
355
 
306
356
  .fg-checkbox[data-size="sm"] {
307
- min-height: 2rem;
357
+ min-height: var(--control-sm);
308
358
  align-items: center;
309
359
  gap: 0.45rem;
310
360
  font-size: 0.8125rem;
311
361
  }
312
362
 
313
363
  .fg-checkbox[data-size="md"] {
314
- min-height: 2.25rem;
364
+ min-height: var(--control-md);
315
365
  align-items: center;
316
366
  gap: 0.55rem;
317
367
  font-size: 0.875rem;
318
368
  }
319
369
 
320
370
  .fg-checkbox[data-size="lg"] {
321
- min-height: 2.75rem;
371
+ min-height: var(--control-lg);
322
372
  align-items: center;
323
373
  gap: 0.65rem;
324
374
  font-size: 1rem;
@@ -365,10 +415,7 @@
365
415
  box-shadow: none;
366
416
  text-align: left;
367
417
  cursor: pointer;
368
- transition:
369
- border-color var(--duration-fast) ease,
370
- box-shadow var(--duration-fast) ease,
371
- transform var(--duration-fast) ease;
418
+ transition: transform var(--duration-fast) var(--ease-out);
372
419
  }
373
420
 
374
421
  .fg-radio-card:hover:not([data-disabled]) {
@@ -377,7 +424,8 @@
377
424
 
378
425
  .fg-radio-card[data-state="checked"] {
379
426
  border-color: var(--color-link);
380
- box-shadow: 0 0 0 1px var(--color-link);
427
+ outline: 1px solid var(--color-link);
428
+ outline-offset: -2px;
381
429
  }
382
430
 
383
431
  .fg-radio-card[data-disabled] {
@@ -461,30 +509,48 @@
461
509
  .fg-surface[data-padding="default"] { padding: 1rem; }
462
510
 
463
511
  .fg-card {
512
+ min-width: 0;
464
513
  overflow: hidden;
465
514
  border: 1px solid var(--color-border-subtle);
466
515
  border-radius: var(--radius-panel);
516
+ color: var(--color-text);
467
517
  background: var(--color-surface-raised);
468
518
  box-shadow: none;
469
519
  }
470
520
 
471
- .fg-card__header,
472
- .fg-card__footer {
521
+ .fg-card__header {
473
522
  display: flex;
474
523
  align-items: center;
475
524
  justify-content: space-between;
476
- gap: 0.75rem;
477
- padding: 0.75rem 1rem;
525
+ gap: var(--space-3);
526
+ padding: var(--space-4);
478
527
  }
479
528
 
529
+ .fg-card__title {
530
+ min-width: 0;
531
+ margin: 0;
532
+ color: var(--color-text);
533
+ font-size: var(--text-md);
534
+ font-weight: var(--weight-medium);
535
+ line-height: var(--leading);
536
+ overflow-wrap: anywhere;
537
+ }
538
+ .fg-card__actions { display: flex; flex: none; align-items: center; gap: var(--space-2); margin-left: auto; }
539
+ .fg-card__body { min-width: 0; padding: var(--space-4); }
540
+ .fg-card__header + .fg-card__body { padding-top: 0; }
480
541
  .fg-card__footer {
481
- background: var(--color-surface);
542
+ display: flex;
543
+ flex-wrap: wrap;
544
+ align-items: center;
545
+ justify-content: space-between;
546
+ gap: var(--space-3);
547
+ margin-inline: var(--space-4);
548
+ padding-block: var(--space-3);
549
+ border-top: 1px solid var(--color-border-subtle);
550
+ color: var(--color-muted);
551
+ font-size: var(--text-sm);
482
552
  }
483
553
 
484
- .fg-card__title { margin: 0; font-size: 0.875rem; font-weight: 600; line-height: 1.4; }
485
- .fg-card__actions { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }
486
- .fg-card__body { padding: 1rem; }
487
-
488
554
  .fg-progress {
489
555
  position: relative;
490
556
  height: 0.55rem;
@@ -511,9 +577,9 @@
511
577
  user-select: none;
512
578
  }
513
579
 
514
- .fg-slider[data-size="sm"] { min-height: 2rem; }
515
- .fg-slider[data-size="md"] { min-height: 2.25rem; }
516
- .fg-slider[data-size="lg"] { min-height: 2.75rem; }
580
+ .fg-slider[data-size="sm"] { min-height: var(--control-sm); }
581
+ .fg-slider[data-size="md"] { min-height: var(--control-md); }
582
+ .fg-slider[data-size="lg"] { min-height: var(--control-lg); }
517
583
 
518
584
  .fg-slider__track {
519
585
  position: relative;
@@ -606,7 +672,7 @@
606
672
  display: inline-grid;
607
673
  flex: none;
608
674
  width: 2.75rem;
609
- min-height: 2.75rem;
675
+ min-height: var(--control-lg);
610
676
  padding: 0;
611
677
  place-items: center;
612
678
  color: var(--color-muted);
package/src/theme.css CHANGED
@@ -2,47 +2,73 @@
2
2
 
3
3
  :root {
4
4
  color-scheme: light;
5
- --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
6
- --font-mono: 'SFMono-Regular', Consolas, monospace;
7
- --color-bg: #ffffff;
8
- --color-surface: #f7f8fa;
5
+ --font-ui: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
6
+ --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
7
+ --text-xs: 0.75rem;
8
+ --text-sm: 0.8125rem;
9
+ --text-md: 0.875rem;
10
+ --text-lg: 1rem;
11
+ --text-xl: 1.25rem;
12
+ --text-2xl: 1.5rem;
13
+ --weight-regular: 400;
14
+ --weight-medium: 500;
15
+ --weight-semibold: 600;
16
+ --leading-tight: 1.25;
17
+ --leading: 1.5;
18
+ --space-1: 0.25rem;
19
+ --space-2: 0.5rem;
20
+ --space-3: 0.75rem;
21
+ --space-4: 1rem;
22
+ --space-5: 1.25rem;
23
+ --space-6: 1.5rem;
24
+ --space-8: 2rem;
25
+ --space-12: 3rem;
26
+ --space-16: 4rem;
27
+ --control-sm: 2rem;
28
+ --control-md: 2.25rem;
29
+ --control-lg: 2.75rem;
30
+ --measure: 68ch;
31
+ --page-max: 60rem;
32
+ --sidebar: 14rem;
33
+ --color-bg: #fcfcfd;
34
+ --color-surface: #f6f6f8;
9
35
  --color-surface-raised: #fff;
10
- --color-surface-muted: #eef1f5;
11
- --color-text: #101828;
12
- --color-muted: #5d6979;
13
- --color-link: #155eef;
14
- --color-accent: #4d7c0f;
15
- --color-focus: #155eef;
36
+ --color-surface-muted: #efeff2;
37
+ --color-text: #1b1b1f;
38
+ --color-muted: #62626d;
39
+ --color-link: #3d63dd;
40
+ --color-accent: #3d63dd;
41
+ --color-focus: #3d63dd;
16
42
  --color-border: #667085;
17
- --color-border-subtle: #d8dee8;
18
- --color-button-bg: #155eef;
43
+ --color-border-subtle: #e9e9ed;
44
+ --color-button-bg: #3d63dd;
19
45
  --color-button-text: #fff;
20
- --color-button-hover: #004eeb;
46
+ --color-button-hover: #3354c4;
21
47
  --color-input-bg: #fff;
22
- --color-input-text: #101828;
48
+ --color-input-text: #1b1b1f;
23
49
  --color-input-border: #667085;
24
50
  --color-input-placeholder: #667085;
25
- --color-row-hover: #f2f4f7;
26
- --color-row-selected: #eaf1ff;
27
- --color-row-selected-text: #143d8f;
28
- --color-code: #0c1426;
29
- --color-code-text: #edf2ff;
30
- --color-syntax-comment: #a8b3c7;
31
- --color-syntax-keyword: #cba6f7;
32
- --color-syntax-string: #a6e3a1;
33
- --color-syntax-number: #fab387;
34
- --color-syntax-function: #89b4fa;
35
- --color-syntax-type: #f9e2af;
36
- --color-syntax-variable: #edf2ff;
37
- --color-syntax-operator: #89dceb;
38
- --color-syntax-punctuation: #cdd6f4;
39
- --color-syntax-tag: #89b4fa;
40
- --color-syntax-attribute: #f9e2af;
51
+ --color-row-hover: #efeff2;
52
+ --color-row-selected: #e9ebf8;
53
+ --color-row-selected-text: #3354c4;
54
+ --color-code: #f6f6f8;
55
+ --color-code-text: #1b1b1f;
56
+ --color-syntax-comment: #62626d;
57
+ --color-syntax-keyword: #3d63dd;
58
+ --color-syntax-string: #1f7a52;
59
+ --color-syntax-number: #854a0e;
60
+ --color-syntax-function: #3d63dd;
61
+ --color-syntax-type: #854a0e;
62
+ --color-syntax-variable: #1b1b1f;
63
+ --color-syntax-operator: #62626d;
64
+ --color-syntax-punctuation: #62626d;
65
+ --color-syntax-tag: #3d63dd;
66
+ --color-syntax-attribute: #854a0e;
41
67
  --color-error: #c01048;
42
68
  --color-warning: #854a0e;
43
69
  --color-success: #067647;
44
70
  --color-info: #175cd3;
45
- --color-progress: #155eef;
71
+ --color-progress: #3d63dd;
46
72
  --color-shadow: rgb(16 24 40 / 10%);
47
73
  --color-overlay: rgb(0 0 0 / 42%);
48
74
  --color-error-surface: color-mix(in srgb, var(--color-error) 12%, var(--color-surface));
@@ -52,43 +78,57 @@
52
78
  --radius-control: 0.375rem;
53
79
  --radius-panel: 0.5rem;
54
80
  --radius-pill: 999px;
55
- --duration-fast: 140ms;
56
- --shadow-control: 0 1px 2px rgb(16 24 40 / 8%);
57
- --shadow-dialog: 0 24px 80px rgb(5 12 24 / 28%);
81
+ --duration-fast: 120ms;
82
+ --duration: 180ms;
83
+ --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
84
+ --shadow-control: none;
85
+ --shadow-dialog: 0 8px 24px rgb(16 16 24 / 12%);
58
86
  }
59
87
 
60
88
  :root.dark {
61
89
  color-scheme: dark;
62
- --color-bg: #0b1020;
63
- --color-surface: #111827;
64
- --color-surface-raised: #151d2f;
65
- --color-surface-muted: #202a3d;
66
- --color-text: #f4f7ff;
67
- --color-muted: #a8b3c7;
68
- --color-link: #8fb4ff;
69
- --color-accent: #b7ef53;
70
- --color-focus: #8fb4ff;
90
+ --color-bg: #0f0f11;
91
+ --color-surface: #151518;
92
+ --color-surface-raised: #1a1a1e;
93
+ --color-surface-muted: #1f1f24;
94
+ --color-text: #ececf0;
95
+ --color-muted: #a0a0ab;
96
+ --color-link: #7d97ff;
97
+ --color-accent: #7d97ff;
98
+ --color-focus: #7d97ff;
71
99
  --color-border: #647189;
72
- --color-border-subtle: #2d384d;
73
- --color-button-bg: #6e9cff;
74
- --color-button-text: #071126;
75
- --color-button-hover: #8fb4ff;
76
- --color-input-bg: #0d1526;
77
- --color-input-text: #f4f7ff;
100
+ --color-border-subtle: #222227;
101
+ --color-button-bg: #7d97ff;
102
+ --color-button-text: #0d1020;
103
+ --color-button-hover: #97acff;
104
+ --color-input-bg: #151518;
105
+ --color-input-text: #ececf0;
78
106
  --color-input-border: #647189;
79
- --color-input-placeholder: #8995aa;
80
- --color-row-hover: #1b2538;
81
- --color-row-selected: #1b315b;
82
- --color-row-selected-text: #dbe7ff;
83
- --color-code: #070d19;
84
- --color-code-text: #edf2ff;
107
+ --color-input-placeholder: #a0a0ab;
108
+ --color-row-hover: #1f1f24;
109
+ --color-row-selected: #1f2233;
110
+ --color-row-selected-text: #ececf0;
111
+ --color-code: #151518;
112
+ --color-code-text: #ececf0;
113
+ --color-syntax-comment: #a0a0ab;
114
+ --color-syntax-keyword: #97acff;
115
+ --color-syntax-string: #6fd3a0;
116
+ --color-syntax-number: #e8b56a;
117
+ --color-syntax-function: #97acff;
118
+ --color-syntax-type: #e8b56a;
119
+ --color-syntax-variable: #ececf0;
120
+ --color-syntax-operator: #a0a0ab;
121
+ --color-syntax-punctuation: #a0a0ab;
122
+ --color-syntax-tag: #97acff;
123
+ --color-syntax-attribute: #e8b56a;
85
124
  --color-error: #ff8aad;
86
125
  --color-warning: #f8c477;
87
126
  --color-success: #75e0a7;
88
127
  --color-info: #84adff;
89
- --color-progress: #8fb4ff;
128
+ --color-progress: #7d97ff;
90
129
  --color-shadow: rgb(0 0 0 / 32%);
91
130
  --color-overlay: rgb(0 0 0 / 62%);
131
+ --shadow-dialog: 0 8px 24px rgb(0 0 0 / 45%);
92
132
  }
93
133
 
94
134
  @theme inline {