@infonomic/uikit 6.5.1 → 6.6.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 (124) hide show
  1. package/README.md +76 -4
  2. package/dist/components/accordion/accordion.module.css +1 -2
  3. package/dist/components/avatar/avatar.module.css +2 -19
  4. package/dist/components/avatar/avatar_module.css +2 -10
  5. package/dist/components/button/button-group.d.ts.map +1 -1
  6. package/dist/components/button/button-group.js +1 -1
  7. package/dist/components/button/button.module.css +56 -37
  8. package/dist/components/button/button_module.css +12 -12
  9. package/dist/components/button/combo-button.d.ts.map +1 -1
  10. package/dist/components/button/combo-button.module.css +3 -3
  11. package/dist/components/button/copy-button.d.ts.map +1 -1
  12. package/dist/components/button/copy-button.js +14 -7
  13. package/dist/components/card/card.module.css +1 -9
  14. package/dist/components/card/card_module.css +1 -5
  15. package/dist/components/chips/chip.module.css +32 -21
  16. package/dist/components/chips/chip_module.css +2 -2
  17. package/dist/components/dropdown/dropdown.d.ts.map +1 -1
  18. package/dist/components/hamburger/hamburger.module.css +6 -7
  19. package/dist/components/inputs/autocomplete.d.ts.map +1 -1
  20. package/dist/components/inputs/autocomplete.module.css +9 -10
  21. package/dist/components/inputs/autocomplete_module.css +2 -2
  22. package/dist/components/inputs/checkbox-group.module.css +6 -7
  23. package/dist/components/inputs/checkbox.module.css +16 -18
  24. package/dist/components/inputs/checkbox_module.css +2 -2
  25. package/dist/components/inputs/error-text.module.css +1 -1
  26. package/dist/components/inputs/error-text_module.css +1 -1
  27. package/dist/components/inputs/input.module.css +10 -11
  28. package/dist/components/inputs/input_module.css +2 -2
  29. package/dist/components/inputs/label.module.css +1 -1
  30. package/dist/components/inputs/label_module.css +1 -1
  31. package/dist/components/inputs/radio-group.module.css +6 -7
  32. package/dist/components/inputs/select.d.ts.map +1 -1
  33. package/dist/components/inputs/select.module.css +6 -7
  34. package/dist/components/inputs/text-area.module.css +10 -9
  35. package/dist/components/notifications/toast.module.css +9 -19
  36. package/dist/components/notifications/toast_module.css +3 -6
  37. package/dist/components/pager/first-button.d.ts.map +1 -1
  38. package/dist/components/pager/last-button.d.ts.map +1 -1
  39. package/dist/components/pager/next-button.d.ts.map +1 -1
  40. package/dist/components/pager/number-button.d.ts.map +1 -1
  41. package/dist/components/pager/pagination.module.css +1 -6
  42. package/dist/components/pager/pagination_module.css +1 -1
  43. package/dist/components/pager/previous-button.d.ts.map +1 -1
  44. package/dist/components/scroll-area/scroll-area.d.ts.map +1 -1
  45. package/dist/components/scroll-to-top/scroll-to-top.module.css +3 -3
  46. package/dist/components/scroll-to-top/scroll-to-top_module.css +6 -6
  47. package/dist/components/tabs/tabs.module.css +6 -7
  48. package/dist/components/tooltip/tooltip.d.ts.map +1 -1
  49. package/dist/components/tooltip/tooltip.module.css +10 -11
  50. package/dist/lib/ripple.js +3 -3
  51. package/dist/loaders/ellipses.d.ts.map +1 -1
  52. package/dist/loaders/ring.d.ts.map +1 -1
  53. package/dist/loaders/spinner.d.ts.map +1 -1
  54. package/dist/styles/components-vanilla.css +1 -1
  55. package/dist/styles/styles.css +1 -1
  56. package/dist/widgets/datepicker/datepicker.d.ts.map +1 -1
  57. package/dist/widgets/datepicker/datepicker.module.css +1 -2
  58. package/dist/widgets/drawer/drawer.module.css +1 -2
  59. package/dist/widgets/modal/modal.d.ts.map +1 -1
  60. package/dist/widgets/modal/modal.module.css +1 -4
  61. package/package.json +1 -1
  62. package/src/components/accordion/accordion.module.css +1 -2
  63. package/src/components/avatar/avatar.module.css +2 -19
  64. package/src/components/button/button-group.tsx +3 -9
  65. package/src/components/button/button.module.css +56 -37
  66. package/src/components/button/combo-button.module.css +3 -3
  67. package/src/components/button/combo-button.tsx +1 -7
  68. package/src/components/button/copy-button.tsx +23 -9
  69. package/src/components/card/card.module.css +1 -9
  70. package/src/components/chips/chip.module.css +32 -21
  71. package/src/components/chips/chip.stories.tsx +2 -2
  72. package/src/components/chips/chip.tsx +2 -2
  73. package/src/components/dropdown/dropdown.tsx +4 -19
  74. package/src/components/hamburger/hamburger.module.css +6 -7
  75. package/src/components/hamburger/hamburger.stories.tsx +0 -1
  76. package/src/components/inputs/autocomplete.module.css +9 -10
  77. package/src/components/inputs/autocomplete.tsx +10 -4
  78. package/src/components/inputs/calendar.stories.tsx +18 -18
  79. package/src/components/inputs/checkbox-group.module.css +6 -7
  80. package/src/components/inputs/checkbox-group.stories.tsx +4 -7
  81. package/src/components/inputs/checkbox.module.css +16 -18
  82. package/src/components/inputs/error-text.module.css +1 -1
  83. package/src/components/inputs/input.module.css +10 -11
  84. package/src/components/inputs/label.module.css +1 -1
  85. package/src/components/inputs/radio-group.module.css +6 -7
  86. package/src/components/inputs/select.module.css +6 -7
  87. package/src/components/inputs/select.stories.tsx +21 -4
  88. package/src/components/inputs/select.tsx +9 -7
  89. package/src/components/inputs/text-area.module.css +10 -9
  90. package/src/components/notifications/toast.module.css +9 -19
  91. package/src/components/notifications/toast.tsx +2 -11
  92. package/src/components/pager/first-button.tsx +5 -1
  93. package/src/components/pager/last-button.tsx +5 -1
  94. package/src/components/pager/next-button.tsx +5 -1
  95. package/src/components/pager/number-button.tsx +6 -3
  96. package/src/components/pager/pagination.module.css +1 -6
  97. package/src/components/pager/previous-button.tsx +5 -1
  98. package/src/components/scroll-area/scroll-area.tsx +1 -1
  99. package/src/components/scroll-to-top/scroll-to-top.module.css +3 -3
  100. package/src/components/tabs/tabs.module.css +6 -7
  101. package/src/components/tooltip/tooltip.module.css +10 -11
  102. package/src/components/tooltip/tooltip.tsx +12 -12
  103. package/src/lib/ripple.ts +3 -3
  104. package/src/loaders/ellipses.tsx +1 -1
  105. package/src/loaders/loaders.stories.tsx +44 -10
  106. package/src/loaders/ring.tsx +1 -1
  107. package/src/loaders/spinner.tsx +2 -2
  108. package/src/styles/components/hamburger.css +6 -6
  109. package/src/styles/components/loaders.css +1 -1
  110. package/src/styles/functional/README.md +67 -0
  111. package/src/styles/functional/borders.css +19 -0
  112. package/src/styles/functional/colors.css +237 -69
  113. package/src/styles/functional/functional.css +1 -0
  114. package/src/styles/functional/shadcn-compat.css +120 -0
  115. package/src/styles/functional/surfaces.css +17 -0
  116. package/src/styles/functional/typography.css +14 -6
  117. package/src/styles/local-fonts.css +1 -1
  118. package/src/styles/theme/theme.css +1 -1
  119. package/src/styles/utils/utility-classes.css +12 -22
  120. package/src/widgets/datepicker/datepicker.module.css +1 -2
  121. package/src/widgets/datepicker/datepicker.tsx +10 -8
  122. package/src/widgets/drawer/drawer.module.css +1 -2
  123. package/src/widgets/modal/modal.module.css +1 -4
  124. package/src/widgets/modal/modal.tsx +2 -6
@@ -21,7 +21,15 @@ export interface TooltipProps {
21
21
 
22
22
  function ArrowSvg(props: React.ComponentProps<'svg'>) {
23
23
  return (
24
- <svg width="15" height="8" viewBox="0 0 20 10" fill="none" aria-hidden role="presentation" {...props}>
24
+ <svg
25
+ width="15"
26
+ height="8"
27
+ viewBox="0 0 20 10"
28
+ fill="none"
29
+ aria-hidden
30
+ role="presentation"
31
+ {...props}
32
+ >
25
33
  <path
26
34
  d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
27
35
  className={styles['arrow-fill']}
@@ -56,18 +64,10 @@ export const Tooltip = function Tooltip({
56
64
  onOpenChange={onOpenChange}
57
65
  disableHoverablePopup={disableHoverablePopup}
58
66
  >
59
- <TooltipPrimitive.Trigger
60
- render={children}
61
- />
67
+ <TooltipPrimitive.Trigger render={children} />
62
68
  <TooltipPrimitive.Portal>
63
- <TooltipPrimitive.Positioner
64
- ref={ref}
65
- side={side}
66
- sideOffset={sideOffset}
67
- >
68
- <TooltipPrimitive.Popup
69
- className={cx(styles.tooltip, 'infonomic-tooltip')}
70
- >
69
+ <TooltipPrimitive.Positioner ref={ref} side={side} sideOffset={sideOffset}>
70
+ <TooltipPrimitive.Popup className={cx(styles.tooltip, 'infonomic-tooltip')}>
71
71
  <TooltipPrimitive.Arrow
72
72
  className={cx(styles['tooltip-arrow'], 'infonomic-tooltip-arrow')}
73
73
  >
package/src/lib/ripple.ts CHANGED
@@ -43,9 +43,9 @@ export class Ripple {
43
43
  element.style.borderRadius = '50%'
44
44
  element.style.pointerEvents = 'none'
45
45
  element.style.position = 'absolute'
46
- element.style.left = clientX - rect.left - radius + 'px'
47
- element.style.top = clientY - rect.top - radius + 'px'
48
- element.style.width = element.style.height = radius * 2 + 'px'
46
+ element.style.left = `${clientX - rect.left - radius}px`
47
+ element.style.top = `${clientY - rect.top - radius}px`
48
+ element.style.width = element.style.height = `${radius * 2}px`
49
49
  }
50
50
 
51
51
  private applyAnimation(element: HTMLSpanElement): void {
@@ -3,8 +3,8 @@ import type React from 'react'
3
3
 
4
4
  import cx from 'classnames'
5
5
 
6
- import type { LoaderProps } from './@types/index.js'
7
6
  import styles from './ellipses.module.css'
7
+ import type { LoaderProps } from './@types/index.js'
8
8
 
9
9
  export function LoaderEllipsis({
10
10
  color,
@@ -53,7 +53,11 @@ export const Sizes = (): React.JSX.Element => {
53
53
  <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Ring</h3>
54
54
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
55
55
  {sizes.map((size) => (
56
- <Loader key={String(size)} loader={<LoaderRing size={size} />} label={`${size}${typeof size === 'number' ? 'px' : ''}`} />
56
+ <Loader
57
+ key={String(size)}
58
+ loader={<LoaderRing size={size} />}
59
+ label={`${size}${typeof size === 'number' ? 'px' : ''}`}
60
+ />
57
61
  ))}
58
62
  </div>
59
63
  </div>
@@ -61,7 +65,11 @@ export const Sizes = (): React.JSX.Element => {
61
65
  <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Ellipsis</h3>
62
66
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
63
67
  {sizes.map((size) => (
64
- <Loader key={String(size)} loader={<LoaderEllipsis size={size} />} label={`${size}${typeof size === 'number' ? 'px' : ''}`} />
68
+ <Loader
69
+ key={String(size)}
70
+ loader={<LoaderEllipsis size={size} />}
71
+ label={`${size}${typeof size === 'number' ? 'px' : ''}`}
72
+ />
65
73
  ))}
66
74
  </div>
67
75
  </div>
@@ -69,7 +77,11 @@ export const Sizes = (): React.JSX.Element => {
69
77
  <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Spinner</h3>
70
78
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
71
79
  {sizes.map((size) => (
72
- <Loader key={String(size)} loader={<LoaderSpinner size={size} />} label={`${size}${typeof size === 'number' ? 'px' : ''}`} />
80
+ <Loader
81
+ key={String(size)}
82
+ loader={<LoaderSpinner size={size} />}
83
+ label={`${size}${typeof size === 'number' ? 'px' : ''}`}
84
+ />
73
85
  ))}
74
86
  </div>
75
87
  </div>
@@ -102,7 +114,11 @@ export const Colors = (): React.JSX.Element => {
102
114
  <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Ellipsis</h3>
103
115
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
104
116
  {colors.map(({ value, label }) => (
105
- <Loader key={label} loader={<LoaderEllipsis size={48} color={value} />} label={label} />
117
+ <Loader
118
+ key={label}
119
+ loader={<LoaderEllipsis size={48} color={value} />}
120
+ label={label}
121
+ />
106
122
  ))}
107
123
  </div>
108
124
  </div>
@@ -110,7 +126,11 @@ export const Colors = (): React.JSX.Element => {
110
126
  <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Spinner</h3>
111
127
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
112
128
  {colors.map(({ value, label }) => (
113
- <Loader key={label} loader={<LoaderSpinner size={48} color={value} />} label={label} />
129
+ <Loader
130
+ key={label}
131
+ loader={<LoaderSpinner size={48} color={value} />}
132
+ label={label}
133
+ />
114
134
  ))}
115
135
  </div>
116
136
  </div>
@@ -126,7 +146,9 @@ export const StringSizes = (): React.JSX.Element => {
126
146
  <div style={{ maxWidth: '800px', margin: '1.5rem auto' }}>
127
147
  <div style={{ maxWidth: '800px', display: 'flex', flexDirection: 'column', gap: '2.5rem' }}>
128
148
  <div>
129
- <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Ring (rem units)</h3>
149
+ <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>
150
+ Ring (rem units)
151
+ </h3>
130
152
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
131
153
  {stringSizes.map((size) => (
132
154
  <Loader key={String(size)} loader={<LoaderRing size={size} />} label={String(size)} />
@@ -134,18 +156,30 @@ export const StringSizes = (): React.JSX.Element => {
134
156
  </div>
135
157
  </div>
136
158
  <div>
137
- <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Ellipsis (rem units)</h3>
159
+ <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>
160
+ Ellipsis (rem units)
161
+ </h3>
138
162
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
139
163
  {stringSizes.map((size) => (
140
- <Loader key={String(size)} loader={<LoaderEllipsis size={size} />} label={String(size)} />
164
+ <Loader
165
+ key={String(size)}
166
+ loader={<LoaderEllipsis size={size} />}
167
+ label={String(size)}
168
+ />
141
169
  ))}
142
170
  </div>
143
171
  </div>
144
172
  <div>
145
- <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>Spinner (rem units)</h3>
173
+ <h3 style={{ marginBottom: '1rem', fontSize: '1.125rem', fontWeight: 600 }}>
174
+ Spinner (rem units)
175
+ </h3>
146
176
  <div style={{ display: 'flex', alignItems: 'flex-end', gap: '2.5rem' }}>
147
177
  {stringSizes.map((size) => (
148
- <Loader key={String(size)} loader={<LoaderSpinner size={size} />} label={String(size)} />
178
+ <Loader
179
+ key={String(size)}
180
+ loader={<LoaderSpinner size={size} />}
181
+ label={String(size)}
182
+ />
149
183
  ))}
150
184
  </div>
151
185
  </div>
@@ -3,8 +3,8 @@ import type React from 'react'
3
3
 
4
4
  import cx from 'classnames'
5
5
 
6
- import type { LoaderProps } from './@types/index.js'
7
6
  import styles from './ring.module.css'
7
+ import type { LoaderProps } from './@types/index.js'
8
8
 
9
9
  export function LoaderRing({
10
10
  color,
@@ -3,8 +3,8 @@ import type React from 'react'
3
3
 
4
4
  import cx from 'classnames'
5
5
 
6
- import type { LoaderProps } from './@types/index.js'
7
6
  import styles from './spinner.module.css'
7
+ import type { LoaderProps } from './@types/index.js'
8
8
 
9
9
  export function LoaderSpinner({
10
10
  color,
@@ -23,7 +23,7 @@ export function LoaderSpinner({
23
23
  <div
24
24
  className={cx(
25
25
  'infonomic-loader-spinner-blade-inner',
26
- styles['loader-spinner-blade-inner'],
26
+ styles['loader-spinner-blade-inner']
27
27
  )}
28
28
  />
29
29
  </div>
@@ -1,11 +1,11 @@
1
1
  /* No longer used in our actual hamburger React and Astro components
2
2
  but left here as a reference. */
3
3
  @layer infonomic-base,
4
- infonomic-functional,
5
- infonomic-utilities,
6
- infonomic-theme,
7
- infonomic-typography,
8
- infonomic-components;
4
+ infonomic-functional,
5
+ infonomic-utilities,
6
+ infonomic-theme,
7
+ infonomic-typography,
8
+ infonomic-components;
9
9
 
10
10
  @layer infonomic-components {
11
11
  .component--hamburger {
@@ -119,4 +119,4 @@ infonomic-components;
119
119
  bottom 0.075s ease,
120
120
  transform 0.075s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
121
121
  }
122
- }
122
+ }
@@ -195,4 +195,4 @@ but left here as a reference. */
195
195
  100% {
196
196
  opacity: 0;
197
197
  }
198
- }
198
+ }
@@ -0,0 +1,67 @@
1
+ # Functional Token Layer
2
+
3
+ This directory holds the **semantic source of truth** for the uikit. Every token here is defined in three scopes: `:root` (light), `.dark` / `[data-theme="dark"]` (dark), and `.not-dark` (a local override that forces light-mode tokens regardless of an ancestor `.dark` class).
4
+
5
+ Components must read from these tokens. They must not read base palette primitives directly unless there is no semantic equivalent.
6
+
7
+ ## Files
8
+
9
+ - `colors.css` — intent token families (fill, text-on, text, stroke, ring, gradient × primary, secondary, noeffect, success, info, warning, danger), plus the generic `--focus-ring` role token.
10
+ - `surfaces.css` — `--background`, `--foreground`, `--surface-panel*`, `--surface-item*`, `--surface-subtle*`, scrollbar tokens.
11
+ - `typography.css` — `--text`, `--headings`, `--muted`, `--text-subtle`, `--text-placeholder`.
12
+ - `borders.css` — `--border-color`, field-state tokens (`--field-border`, `--field-border-hover`, `--field-border-invalid`, `--field-ring`, `--field-ring-invalid`).
13
+ - `grid-flex.css` — layout tokens.
14
+ - `shadcn-compat.css` — optional `--shadcn-*` alias namespace. Strictly for ShadCN-style Tailwind utilities in consumer apps; **do not use inside uikit components**.
15
+
16
+ ## Intent Token Taxonomy
17
+
18
+ `--{element}-{intent}[-{emphasis}][-{state}]`
19
+
20
+ | Part | Values |
21
+ | --- | --- |
22
+ | element | `fill`, `text-on`, `text`, `stroke`, `ring`, `gradient` |
23
+ | intent | `primary`, `secondary`, `noeffect`, `success`, `info`, `warning`, `danger` |
24
+ | emphasis | `strong`, `weak`, `outlined`, `text` (present on `fill` and `text-on` tokens) |
25
+ | state | `hover`, `disabled` (present where a state-specific value is needed) |
26
+
27
+ There is **no `accent` intent family**. `--accent` is a raw brand palette token; prefer `--fill-primary-*` for emphasis surfaces or `--surface-subtle-*` for interactive neutral surfaces.
28
+
29
+ ### Standard variants per intent
30
+
31
+ Every intent family provides these:
32
+
33
+ - `--fill-{intent}-strong`, `-strong-hover`, `-strong-disabled`
34
+ - `--fill-{intent}-weak`, `-weak-hover`, `-weak-disabled`
35
+ - `--fill-{intent}-outlined`, `-outlined-hover`, `-outlined-disabled`
36
+ - `--fill-{intent}-text`, `-text-hover`, `-text-disabled`
37
+ - `--text-on-{intent}-strong`, `-strong-hover`, `-strong-disabled`
38
+ - `--text-on-{intent}-weak`, `-weak-hover`, `-weak-disabled`
39
+ - `--text-on-{intent}-outlined`, `-outlined-hover`, `-outlined-disabled`
40
+ - `--text-{intent}`, `-weak`, `-hover`, `-disabled`
41
+ - `--stroke-{intent}`, `-hover`, `-disabled`
42
+ - `--ring-{intent}`
43
+ - `--gradient-{intent}-start`, `-end`, `-foreground`, `-disabled`
44
+
45
+ Noeffect additionally provides `--text-on-noeffect-text*` and `--gradient-noeffect-hover`.
46
+
47
+ ## Generic Role Tokens
48
+
49
+ Use these when a component needs a role without adopting an intent:
50
+
51
+ | Token | Purpose |
52
+ | --- | --- |
53
+ | `--focus-ring` | Neutral focus ring when the component is not tied to an intent |
54
+ | `--field-border` | Default border on form fields |
55
+ | `--field-border-hover` | Hover border on form fields |
56
+ | `--field-border-invalid` | Invalid-state border on form fields |
57
+ | `--field-ring` | Default focus ring on form fields |
58
+ | `--field-ring-invalid` | Invalid-state focus ring on form fields |
59
+ | `--surface-subtle` | Subdued neutral surface |
60
+ | `--surface-subtle-hover` | Subdued neutral surface on hover / for interactive neutral highlight |
61
+ | `--surface-subtle-active` | Subdued neutral surface when pressed / active |
62
+ | `--text-subtle` | Subdued foreground text |
63
+ | `--text-placeholder` | Placeholder-style foreground text |
64
+
65
+ ## Parity Contract
66
+
67
+ Every token defined in `:root` must also be defined in `.dark` and `.not-dark`, or it will silently fall back to the property's initial value in one of the modes. A Python parity check is in the repo history at `packages/uikit/src/styles/functional/colors.css` — if you add a new token, audit all three scopes before merging.
@@ -8,16 +8,35 @@
8
8
  @layer infonomic-functional {
9
9
  :root {
10
10
  --border-color: var(--gray-100);
11
+
12
+ /* Generic field-state tokens (used by Input, Autocomplete, Select, etc.) */
13
+ --field-border: var(--border-color);
14
+ --field-border-hover: var(--stroke-noeffect-hover);
15
+ --field-border-invalid: var(--stroke-danger);
16
+ --field-ring: var(--ring-primary);
17
+ --field-ring-invalid: var(--ring-danger);
11
18
  }
12
19
 
13
20
  /* Dark mode */
14
21
  .dark,
15
22
  [data-theme="dark"] {
16
23
  --border-color: var(--canvas-600);
24
+
25
+ --field-border: var(--border-color);
26
+ --field-border-hover: var(--stroke-noeffect-hover);
27
+ --field-border-invalid: var(--stroke-danger);
28
+ --field-ring: var(--ring-primary);
29
+ --field-ring-invalid: var(--ring-danger);
17
30
  }
18
31
 
19
32
  /* Force light mode (local override) */
20
33
  .not-dark {
21
34
  --border-color: var(--gray-100);
35
+
36
+ --field-border: var(--border-color);
37
+ --field-border-hover: var(--stroke-noeffect-hover);
38
+ --field-border-invalid: var(--stroke-danger);
39
+ --field-ring: var(--ring-primary);
40
+ --field-ring-invalid: var(--ring-danger);
22
41
  }
23
42
  }