@ropav/styles 0.4.0 → 0.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 (181) hide show
  1. package/README.md +89 -5
  2. package/dist/components/accordion.css +6 -14
  3. package/dist/components/alert-dialog.css +1 -13
  4. package/dist/components/alert.css +1 -1
  5. package/dist/components/autocomplete/autocomplete.styles.d.ts +33 -0
  6. package/dist/components/autocomplete/autocomplete.styles.d.ts.map +1 -1
  7. package/dist/components/autocomplete/autocomplete.styles.js +12 -0
  8. package/dist/components/autocomplete.css +54 -36
  9. package/dist/components/breadcrumbs.css +9 -2
  10. package/dist/components/button-group.css +6 -10
  11. package/dist/components/button.css +10 -18
  12. package/dist/components/calendar-year-picker.css +20 -8
  13. package/dist/components/calendar.css +46 -21
  14. package/dist/components/card.css +1 -1
  15. package/dist/components/checkbox.css +54 -56
  16. package/dist/components/chip.css +3 -1
  17. package/dist/components/close-button.css +7 -6
  18. package/dist/components/color-area.css +6 -6
  19. package/dist/components/color-input-group/color-input-group.styles.d.ts +27 -0
  20. package/dist/components/color-input-group/color-input-group.styles.d.ts.map +1 -1
  21. package/dist/components/color-input-group/color-input-group.styles.js +6 -0
  22. package/dist/components/color-input-group.css +31 -28
  23. package/dist/components/color-picker.css +1 -5
  24. package/dist/components/color-slider.css +14 -12
  25. package/dist/components/color-swatch-picker.css +2 -85
  26. package/dist/components/color-swatch.css +1 -1
  27. package/dist/components/combo-box/combo-box.styles.d.ts +27 -0
  28. package/dist/components/combo-box/combo-box.styles.d.ts.map +1 -1
  29. package/dist/components/combo-box/combo-box.styles.js +17 -7
  30. package/dist/components/combo-box.css +34 -4
  31. package/dist/components/date-input-group/date-input-group.styles.d.ts +27 -0
  32. package/dist/components/date-input-group/date-input-group.styles.d.ts.map +1 -1
  33. package/dist/components/date-input-group/date-input-group.styles.js +6 -0
  34. package/dist/components/date-input-group.css +55 -33
  35. package/dist/components/date-picker.css +1 -5
  36. package/dist/components/date-range-picker.css +1 -5
  37. package/dist/components/disclosure.css +0 -4
  38. package/dist/components/drawer.css +4 -8
  39. package/dist/components/drop-zone/drop-zone.styles.d.ts +34 -0
  40. package/dist/components/drop-zone/drop-zone.styles.d.ts.map +1 -0
  41. package/dist/components/drop-zone/drop-zone.styles.js +8 -0
  42. package/dist/components/drop-zone/index.d.ts +2 -0
  43. package/dist/components/drop-zone/index.d.ts.map +1 -0
  44. package/dist/components/drop-zone/index.js +2 -0
  45. package/dist/components/drop-zone.css +78 -0
  46. package/dist/components/dropdown.css +1 -5
  47. package/dist/components/error-message.css +0 -4
  48. package/dist/components/field-error.css +0 -4
  49. package/dist/components/index.css +5 -0
  50. package/dist/components/index.d.ts +5 -0
  51. package/dist/components/index.d.ts.map +1 -1
  52. package/dist/components/input/input.styles.d.ts +15 -0
  53. package/dist/components/input/input.styles.d.ts.map +1 -1
  54. package/dist/components/input/input.styles.js +6 -0
  55. package/dist/components/input-group/input-group.styles.d.ts +27 -0
  56. package/dist/components/input-group/input-group.styles.d.ts.map +1 -1
  57. package/dist/components/input-group/input-group.styles.js +6 -0
  58. package/dist/components/input-group.css +35 -38
  59. package/dist/components/input-otp.css +14 -26
  60. package/dist/components/input.css +23 -32
  61. package/dist/components/kbd.css +3 -1
  62. package/dist/components/label.css +7 -2
  63. package/dist/components/link.css +13 -11
  64. package/dist/components/list-box/list-box.styles.d.ts +15 -0
  65. package/dist/components/list-box/list-box.styles.d.ts.map +1 -1
  66. package/dist/components/list-box/list-box.styles.js +15 -5
  67. package/dist/components/list-box-item.css +8 -12
  68. package/dist/components/list-box.css +19 -0
  69. package/dist/components/menu/menu.styles.d.ts +19 -1
  70. package/dist/components/menu/menu.styles.d.ts.map +1 -1
  71. package/dist/components/menu/menu.styles.js +9 -1
  72. package/dist/components/menu-item.css +4 -10
  73. package/dist/components/menu.css +19 -0
  74. package/dist/components/meter.css +8 -16
  75. package/dist/components/modal.css +1 -13
  76. package/dist/components/number-field/number-field.styles.d.ts +27 -0
  77. package/dist/components/number-field/number-field.styles.d.ts.map +1 -1
  78. package/dist/components/number-field/number-field.styles.js +6 -0
  79. package/dist/components/number-field.css +83 -36
  80. package/dist/components/pagination.css +6 -10
  81. package/dist/components/popover.css +15 -5
  82. package/dist/components/progress-bar/progress-bar.styles.d.ts +36 -0
  83. package/dist/components/progress-bar/progress-bar.styles.d.ts.map +1 -1
  84. package/dist/components/progress-bar/progress-bar.styles.js +10 -0
  85. package/dist/components/progress-bar.css +82 -16
  86. package/dist/components/progress-circle.css +0 -4
  87. package/dist/components/radio.css +7 -9
  88. package/dist/components/range-calendar.css +73 -31
  89. package/dist/components/search-field/search-field.styles.d.ts +27 -0
  90. package/dist/components/search-field/search-field.styles.d.ts.map +1 -1
  91. package/dist/components/search-field/search-field.styles.js +6 -0
  92. package/dist/components/search-field.css +36 -29
  93. package/dist/components/segmented-control/index.d.ts +2 -0
  94. package/dist/components/segmented-control/index.d.ts.map +1 -0
  95. package/dist/components/segmented-control/index.js +2 -0
  96. package/dist/components/segmented-control/segmented-control.styles.d.ts +73 -0
  97. package/dist/components/segmented-control/segmented-control.styles.d.ts.map +1 -0
  98. package/dist/components/segmented-control/segmented-control.styles.js +27 -0
  99. package/dist/components/segmented-control.css +188 -0
  100. package/dist/components/select/select.styles.d.ts +33 -0
  101. package/dist/components/select/select.styles.d.ts.map +1 -1
  102. package/dist/components/select/select.styles.js +12 -0
  103. package/dist/components/select.css +47 -33
  104. package/dist/components/sidebar/index.d.ts +2 -0
  105. package/dist/components/sidebar/index.d.ts.map +1 -0
  106. package/dist/components/sidebar/index.js +2 -0
  107. package/dist/components/sidebar/sidebar.styles.d.ts +226 -0
  108. package/dist/components/sidebar/sidebar.styles.d.ts.map +1 -0
  109. package/dist/components/sidebar/sidebar.styles.js +65 -0
  110. package/dist/components/sidebar.css +604 -0
  111. package/dist/components/slider.css +10 -11
  112. package/dist/components/splitter/index.d.ts +2 -0
  113. package/dist/components/splitter/index.d.ts.map +1 -0
  114. package/dist/components/splitter/index.js +2 -0
  115. package/dist/components/splitter/splitter.styles.d.ts +61 -0
  116. package/dist/components/splitter/splitter.styles.d.ts.map +1 -0
  117. package/dist/components/splitter/splitter.styles.js +26 -0
  118. package/dist/components/splitter.css +249 -0
  119. package/dist/components/switch.css +16 -15
  120. package/dist/components/table.css +72 -30
  121. package/dist/components/tabs.css +9 -20
  122. package/dist/components/tag.css +32 -24
  123. package/dist/components/textarea/textarea.styles.d.ts +15 -0
  124. package/dist/components/textarea/textarea.styles.d.ts.map +1 -1
  125. package/dist/components/textarea/textarea.styles.js +6 -0
  126. package/dist/components/textarea.css +23 -32
  127. package/dist/components/toast.css +4 -2
  128. package/dist/components/toggle-button-group.css +7 -11
  129. package/dist/components/toggle-button.css +9 -17
  130. package/dist/components/toolbar.css +1 -1
  131. package/dist/components/tooltip.css +15 -6
  132. package/dist/components/typography.css +12 -4
  133. package/dist/components/virtualizer/index.d.ts +2 -0
  134. package/dist/components/virtualizer/index.d.ts.map +1 -0
  135. package/dist/components/virtualizer/index.js +2 -0
  136. package/dist/components/virtualizer/virtualizer.styles.d.ts +44 -0
  137. package/dist/components/virtualizer/virtualizer.styles.d.ts.map +1 -0
  138. package/dist/components/virtualizer/virtualizer.styles.js +15 -0
  139. package/dist/components/virtualizer.css +72 -0
  140. package/dist/index.js +6 -1
  141. package/dist/ropav.min.css +2 -2
  142. package/dist/themes/airbnb.css +11 -4
  143. package/dist/themes/all.css +1 -0
  144. package/dist/themes/coinbase.css +11 -4
  145. package/dist/themes/default.css +40 -8
  146. package/dist/themes/discord.css +11 -4
  147. package/dist/themes/hero.css +282 -0
  148. package/dist/themes/lavender.css +11 -4
  149. package/dist/themes/mint.css +11 -4
  150. package/dist/themes/netflix.css +11 -4
  151. package/dist/themes/rabbit.css +11 -4
  152. package/dist/themes/shared/theme.css +20 -2
  153. package/dist/themes/sky.css +11 -4
  154. package/dist/themes/spotify.css +11 -4
  155. package/dist/themes/uber.css +11 -4
  156. package/dist/utilities/index.css +27 -0
  157. package/package.json +1 -1
  158. package/src/components/autocomplete/autocomplete.styles.ts +12 -0
  159. package/src/components/color-input-group/color-input-group.styles.ts +10 -0
  160. package/src/components/combo-box/combo-box.styles.ts +12 -0
  161. package/src/components/date-input-group/date-input-group.styles.ts +10 -0
  162. package/src/components/drop-zone/drop-zone.styles.ts +12 -0
  163. package/src/components/drop-zone/index.ts +1 -0
  164. package/src/components/index.ts +5 -0
  165. package/src/components/input/input.styles.ts +6 -0
  166. package/src/components/input-group/input-group.styles.ts +10 -0
  167. package/src/components/list-box/list-box.styles.ts +6 -0
  168. package/src/components/menu/menu.styles.ts +10 -0
  169. package/src/components/number-field/number-field.styles.ts +10 -0
  170. package/src/components/progress-bar/progress-bar.styles.ts +14 -0
  171. package/src/components/search-field/search-field.styles.ts +10 -0
  172. package/src/components/segmented-control/index.ts +1 -0
  173. package/src/components/segmented-control/segmented-control.styles.ts +37 -0
  174. package/src/components/select/select.styles.ts +12 -0
  175. package/src/components/sidebar/index.ts +1 -0
  176. package/src/components/sidebar/sidebar.styles.ts +117 -0
  177. package/src/components/splitter/index.ts +1 -0
  178. package/src/components/splitter/splitter.styles.ts +44 -0
  179. package/src/components/textarea/textarea.styles.ts +6 -0
  180. package/src/components/virtualizer/index.ts +1 -0
  181. package/src/components/virtualizer/virtualizer.styles.ts +15 -0
package/README.md CHANGED
@@ -112,6 +112,11 @@ component that publishes it as an attribute.
112
112
 
113
113
  `components/button.css` is the densest example of both — read it before writing a new component file.
114
114
 
115
+ **Every `ropav` component takes a `class` prop**, merged through its `tv()` recipe rather than
116
+ concatenated, so a utility that conflicts with one the recipe already carries replaces it. That is
117
+ the first thing to reach for. It cannot reach a part drawn in `::before`/`::after`, and it flattens
118
+ every state of whatever property it sets — see [State colors](#state-colors) for the way round both.
119
+
115
120
  ## Theming
116
121
 
117
122
  Two independent axes. `data-theme` picks the palette, a `light`/`dark` class picks the appearance:
@@ -126,8 +131,9 @@ did before the other themes existed.
126
131
 
127
132
  ### Bundled themes
128
133
 
129
- Eleven, ported from HeroUI's theme gallery. The default one is already in `@ropav/styles`; the rest are
130
- opt-in, one file each:
134
+ The default one, plus a theme per brand ported from HeroUI's gallery `hero` among them, being
135
+ HeroUI's own palette. The default is already in `@ropav/styles`; the others are opt-in, one file
136
+ each:
131
137
 
132
138
  ```css
133
139
  @import "@ropav/styles";
@@ -136,10 +142,10 @@ opt-in, one file each:
136
142
 
137
143
  | `data-theme` | | `data-theme` | | `data-theme` |
138
144
  | --- | --- | --- | --- | --- |
139
- | `default` | | `netflix` | | `airbnb` |
145
+ | `default` | | `mint` | | `coinbase` |
146
+ | `hero` | | `netflix` | | `airbnb` |
140
147
  | `sky` | | `uber` | | `discord` |
141
148
  | `lavender` | | `spotify` | | `rabbit` |
142
- | `mint` | | `coinbase` | | |
143
149
 
144
150
  Each carries both a light and a dark palette, so a theme is a brand rather than an appearance. There is
145
151
  no `netflix-dark` — it is `data-theme="netflix"` plus `class="dark"`.
@@ -147,11 +153,15 @@ no `netflix-dark` — it is `data-theme="netflix"` plus `class="dark"`.
147
153
  `themes/all.css` pulls in all of them at once. That is for docs and playgrounds; an app should import
148
154
  only the themes it actually offers, since each is around 10 kB before compression.
149
155
 
150
- The ten non-default themes are **generated** — edit `scripts/themes/presets.ts` and run
156
+ Every theme but `default` and `hero` is **generated** — edit `scripts/themes/presets.ts` and run
151
157
  `pnpm generate:themes`, never the CSS. A preset is four numbers (accent lightness, chroma and hue, plus
152
158
  the chroma of the neutral ramp), a radius pair, and any exact brand colours that should beat the
153
159
  calculated ones.
154
160
 
161
+ Those two stay hand-written, each file's header saying what the generator cannot reproduce about it.
162
+ Their presets carry the label and the presentation order; the CSS is the source of truth for their
163
+ tokens.
164
+
155
165
  ### Retheming
156
166
 
157
167
  Every token is a CSS custom property, so overriding them in your own stylesheet is enough — no rebuild
@@ -198,6 +208,80 @@ scrollbar set, and shadows.
198
208
  stale the moment a token moves. `themes/shared/theme.css` holds what is derived from those tokens: the
199
209
  `--radius-xs` … `--radius-4xl` scale and the easing curves.
200
210
 
211
+ ### State colors
212
+
213
+ A component's own properties are the third tier, declared on its block and private to its file —
214
+ `--button-bg`, `--switch-control-bg-checked-hover`, `--sidebar-rail-line`. The convention:
215
+
216
+ > **A color a state rule paints goes through a custom property — where more than one state paints
217
+ > that property.**
218
+
219
+ That is what makes one state retunable on its own. A color written straight into the rule is not:
220
+ the resting and the lit value are the same property on the same element, so the one declaration a
221
+ caller writes to change either beats every state rule at once — and a utility beats them all
222
+ whatever their specificity, `utilities` being a later layer than `components`. The only way left is
223
+ to restate the whole state set behind `:not()`, which drifts silently the day a state is added.
224
+
225
+ So a caller sets the property instead, and the states that read the others are left standing:
226
+
227
+ ```html
228
+ <!-- No line at rest; it still flares on hover and while dragging. -->
229
+ <SidebarRoot class="[--sidebar-rail-line:transparent]">
230
+ ```
231
+
232
+ The qualifier is what keeps this from becoming surface for its own sake. Where exactly one state
233
+ paints a property, a caller can name that state from the call site — `hover:bg-*`, `focus-visible:outline-*` —
234
+ and there is no other state for it to flatten, so no property is minted. It is the second state
235
+ painting the same thing that makes the call site unable to tell them apart.
236
+
237
+ Defaults chain, so retuning one carries the states below it unless they are set too —
238
+ `--sidebar-rail-line-dragging` follows `--sidebar-rail-line-hover`, the way `--button-bg-pressed`
239
+ follows `--button-bg-hover`. Read `components/button.css` for the shape and
240
+ `components/sidebar.css` for a part painted on a pseudo-element, which a class cannot reach at all.
241
+
242
+ Two limits. The properties are per component and resolve to the tokens above, so a palette change
243
+ belongs in a theme rather than here. And Forced Colors Mode is not covered: those blocks paint the
244
+ system keywords, which are the only colors exempt from the override and not a component's to
245
+ retune — `[--sidebar-rail-line:transparent]` leaves the line drawn under High Contrast, on purpose.
246
+
247
+ `state-colors.test.ts` in the `ropav` package reads every component file and fails on a state color
248
+ that does not go through a property. Its ledger of exceptions is currently empty, so an entry
249
+ appearing there is debt to pay down rather than a licence to add more.
250
+
251
+ ### Translucent surfaces
252
+
253
+ A `surface--transparent` paints nothing of its own, and so does a surface a caller has thinned to
254
+ let something through — a blurred header, a panel over an image, a window whose material the OS
255
+ draws. What sits on one of those has no way to know what is behind it, and that splits the palette
256
+ in two.
257
+
258
+ **Safe on anything: the tokens that are an alpha.** `--state-layer` is what a state paints, and
259
+ `--separator` and `--border` are the lines — each an alpha of `--surface-foreground` rather than a
260
+ neutral of its own. An alpha darkens or lightens whatever it lands on, so it holds its contrast
261
+ against a fill it was never tuned for: another surface, the far half of the theme, or a photograph.
262
+ The `-soft` family and `--scrollbar-thumb` are alphas too, which is why a selection is
263
+ `--accent-soft` wherever the library marks one.
264
+
265
+ **Not safe: the fills.** `--default`, `--accent`, the status colors, `--surface` and its secondary
266
+ and tertiary steps are opaque, and they are meant to be — a badge you can read the page through is a
267
+ broken badge. They assume a background because they *are* one. Use them to fill a box, never to mark
268
+ a state on a box that is already transparent.
269
+
270
+ `--surface-hover` sits on the fill side of that line despite the name: it is a surface that has been
271
+ tinted and stays opaque, for a component opaque at rest whose hover must stay that way.
272
+ `--state-layer` is the one for a component transparent at rest. Reaching for the wrong one fails
273
+ quietly — a translucent hover on an opaque tag shows the page through it, and a flat neutral on a
274
+ transparent row vanishes the moment the fill behind it matches.
275
+
276
+ The line between the two is what a color is for, not what it looks like. `--default` is a fine grey
277
+ until it is asked to be a state layer: then it is a fixed lightness laid on an unknown one, and the
278
+ day those two match it is gone with nothing to fail but the eye.
279
+
280
+ **Contrast on a translucent surface is the app's to guarantee.** `contrast.browser.test.ts` holds
281
+ the floor for text on the fills, where both sides are known. Once the background is whatever happens
282
+ to be behind the window, ropav cannot see it and does not claim to — an app that thins a surface
283
+ owns the legibility of what it puts there.
284
+
201
285
  ### Reduced motion
202
286
 
203
287
  `data-reduce-motion="true"` on any ancestor forces animations off, `"false"` forces them on regardless
@@ -59,10 +59,6 @@
59
59
  /* Base Styles */
60
60
  @apply flex flex-1 items-center justify-between px-4 py-4 text-start text-sm font-medium no-highlight;
61
61
 
62
- /**
63
- * Transitions
64
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
65
- */
66
62
  transition:
67
63
  opacity 150ms var(--ease-out),
68
64
  box-shadow 150ms var(--ease-out);
@@ -98,10 +94,6 @@
98
94
  height: var(--disclosure-panel-height);
99
95
  overflow: clip;
100
96
 
101
- /**
102
- * Transitions
103
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
104
- */
105
97
  transition:
106
98
  height 200ms var(--ease-out-quad),
107
99
  opacity 200ms var(--ease-out);
@@ -116,7 +108,7 @@
116
108
  /* Surface variant */
117
109
  .accordion--surface {
118
110
  @apply bg-surface;
119
- border-radius: min(32px, var(--radius-3xl));
111
+ border-radius: min(32px, var(--component-radius));
120
112
 
121
113
  /* Forced Colors Mode flattens the fill onto the page and strips the shadow, so the container
122
114
  * stops having any shape and its contents sit loose on the page. */
@@ -129,7 +121,7 @@
129
121
  @media (hover: hover) {
130
122
  &:hover:not([aria-expanded="true"]),
131
123
  &[data-hovered="true"]:not([aria-expanded="true"]) {
132
- @apply bg-default;
124
+ @apply bg-state-layer;
133
125
  }
134
126
  }
135
127
  }
@@ -147,13 +139,13 @@
147
139
 
148
140
  /* Special rounding for first and last items in surface variant */
149
141
  &:first-child [data-slot="accordion-trigger"] {
150
- border-start-start-radius: min(32px, var(--radius-3xl));
151
- border-start-end-radius: min(32px, var(--radius-3xl));
142
+ border-start-start-radius: min(32px, var(--component-radius));
143
+ border-start-end-radius: min(32px, var(--component-radius));
152
144
  }
153
145
 
154
146
  &:last-child:not(:has([data-slot="accordion-trigger"][aria-expanded="true"]))
155
147
  [data-slot="accordion-trigger"] {
156
- border-end-start-radius: min(32px, var(--radius-3xl));
157
- border-end-end-radius: min(32px, var(--radius-3xl));
148
+ border-end-start-radius: min(32px, var(--component-radius));
149
+ border-end-end-radius: min(32px, var(--component-radius));
158
150
  }
159
151
  }
@@ -10,10 +10,6 @@
10
10
  @apply inline-block;
11
11
  @apply cursor-(--cursor-interactive);
12
12
 
13
- /**
14
- * Transitions
15
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
16
- */
17
13
  transition:
18
14
  transform 250ms var(--ease-out-quart),
19
15
  background-color 150ms var(--ease-smooth),
@@ -57,10 +53,6 @@
57
53
  @apply animate-out duration-100 ease-out fade-out-0;
58
54
  }
59
55
 
60
- /**
61
- * Reduce Animation
62
- * CRITICAL: motion-reduce must be AFTER animate for correct override specificity
63
- */
64
56
  &[data-exiting="true"],
65
57
  &[data-entering="true"] {
66
58
  @apply will-change-[opacity];
@@ -126,10 +118,6 @@
126
118
  @apply animate-out duration-100 ease-out-quad fade-out-0 zoom-out-95;
127
119
  }
128
120
 
129
- /**
130
- * Reduce Animation
131
- * CRITICAL: motion-reduce must be AFTER animate for correct override specificity
132
- */
133
121
  &[data-exiting="true"],
134
122
  &[data-entering="true"] {
135
123
  @apply will-change-[opacity,transform];
@@ -145,7 +133,7 @@
145
133
  @apply flex min-h-0 w-full flex-col;
146
134
  @apply max-h-full;
147
135
  @apply bg-overlay shadow-overlay outline-none;
148
- border-radius: min(32px, var(--radius-3xl));
136
+ border-radius: min(32px, var(--component-radius));
149
137
  @apply p-6;
150
138
  @apply overflow-clip;
151
139
  @apply pointer-events-auto;
@@ -11,7 +11,7 @@
11
11
  outline: 1px solid CanvasText;
12
12
  outline-offset: -1px;
13
13
  }
14
- border-radius: min(32px, var(--radius-3xl));
14
+ border-radius: min(32px, var(--component-radius));
15
15
  }
16
16
 
17
17
  /* Alert elements */
@@ -7,6 +7,17 @@ export declare const autocompleteVariants: import("tailwind-variants").TVReturnT
7
7
  trigger: string;
8
8
  };
9
9
  };
10
+ size: {
11
+ lg: {
12
+ base: string;
13
+ popover: string;
14
+ };
15
+ md: {};
16
+ sm: {
17
+ base: string;
18
+ popover: string;
19
+ };
20
+ };
10
21
  variant: {
11
22
  primary: {
12
23
  base: string;
@@ -31,6 +42,17 @@ export declare const autocompleteVariants: import("tailwind-variants").TVReturnT
31
42
  trigger: string;
32
43
  };
33
44
  };
45
+ size: {
46
+ lg: {
47
+ base: string;
48
+ popover: string;
49
+ };
50
+ md: {};
51
+ sm: {
52
+ base: string;
53
+ popover: string;
54
+ };
55
+ };
34
56
  variant: {
35
57
  primary: {
36
58
  base: string;
@@ -55,6 +77,17 @@ export declare const autocompleteVariants: import("tailwind-variants").TVReturnT
55
77
  trigger: string;
56
78
  };
57
79
  };
80
+ size: {
81
+ lg: {
82
+ base: string;
83
+ popover: string;
84
+ };
85
+ md: {};
86
+ sm: {
87
+ base: string;
88
+ popover: string;
89
+ };
90
+ };
58
91
  variant: {
59
92
  primary: {
60
93
  base: string;
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.styles.d.ts","sourceRoot":"","sources":["../../../src/components/autocomplete/autocomplete.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,eAAO,MAAM,oBAAoB;;QAgB3B,KAAK;QACL,IAAI;YACF,IAAI;YACJ,OAAO;;;;QAIT,OAAO;YACL,IAAI;;QAEN,SAAS;YACP,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAIV,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"autocomplete.styles.d.ts","sourceRoot":"","sources":["../../../src/components/autocomplete/autocomplete.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,eAAO,MAAM,oBAAoB;;QAiB3B,KAAK;QACL,IAAI;YACF,IAAI;YACJ,OAAO;;;;QAIT,EAAE;YACA,IAAI;YACJ,OAAO;;QAET,EAAE;QACF,EAAE;YACA,IAAI;YACJ,OAAO;;;;QAIT,OAAO;YACL,IAAI;;QAEN,SAAS;YACP,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAIV,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -3,6 +3,7 @@ import { tv } from "tailwind-variants";
3
3
  const autocompleteVariants = tv({
4
4
  defaultVariants: {
5
5
  fullWidth: false,
6
+ size: "md",
6
7
  variant: "primary"
7
8
  },
8
9
  slots: {
@@ -22,6 +23,17 @@ const autocompleteVariants = tv({
22
23
  trigger: "autocomplete__trigger--full-width"
23
24
  }
24
25
  },
26
+ size: {
27
+ lg: {
28
+ base: "autocomplete--lg",
29
+ popover: "autocomplete__popover--lg"
30
+ },
31
+ md: {},
32
+ sm: {
33
+ base: "autocomplete--sm",
34
+ popover: "autocomplete__popover--sm"
35
+ }
36
+ },
25
37
  variant: {
26
38
  primary: { base: "autocomplete--primary" },
27
39
  secondary: { base: "autocomplete--secondary" }
@@ -4,7 +4,14 @@
4
4
  }
5
5
 
6
6
  .autocomplete__trigger {
7
- @apply relative isolate inline-flex min-h-9 rounded-field border bg-field px-3 py-2 text-sm text-field-foreground shadow-field outline-none select-none no-highlight;
7
+ @apply relative isolate inline-flex min-h-9 rounded-field border px-3 field-line-md text-field-foreground shadow-field outline-none select-none no-highlight;
8
+
9
+ /* The fill, per state. The `--secondary` variant re-points these and declares nothing else. */
10
+ --autocomplete-trigger-bg: var(--field-background, var(--default));
11
+ --autocomplete-trigger-bg-hover: var(--field-hover);
12
+ --autocomplete-trigger-bg-focus: var(--field-focus);
13
+
14
+ background-color: var(--autocomplete-trigger-bg);
8
15
 
9
16
  /* Forced Colors Mode flattens the fill onto the page and strips the shadow, leaving a control
10
17
  * with nothing to say it is one. `ButtonBorder` is the keyword the platform uses for a
@@ -14,10 +21,6 @@
14
21
  outline-offset: -1px;
15
22
  }
16
23
 
17
- /**
18
- * Transitions
19
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
20
- */
21
24
  transition:
22
25
  background-color 150ms var(--ease-smooth),
23
26
  border-color 150ms var(--ease-smooth),
@@ -39,7 +42,7 @@
39
42
  @media (hover: hover) {
40
43
  &:hover:not(:has(.autocomplete__clear-button:hover)),
41
44
  &[data-hovered="true"]:not(:has(.autocomplete__clear-button:hover)) {
42
- @apply bg-field-hover;
45
+ background-color: var(--autocomplete-trigger-bg-hover);
43
46
  border-color: var(--field-border-hover);
44
47
  }
45
48
  }
@@ -49,7 +52,7 @@
49
52
  &[data-focus-visible="true"] {
50
53
  @apply status-focused;
51
54
  border-color: var(--field-border-focus);
52
- background-color: var(--field-focus);
55
+ background-color: var(--autocomplete-trigger-bg-focus);
53
56
  }
54
57
 
55
58
  /* Focus state */
@@ -61,7 +64,7 @@
61
64
  .autocomplete[data-invalid="true"] &,
62
65
  .autocomplete[aria-invalid="true"] & {
63
66
  @apply status-invalid-field;
64
- background-color: var(--field-focus);
67
+ background-color: var(--autocomplete-trigger-bg-focus);
65
68
  }
66
69
 
67
70
  /* Disabled state */
@@ -79,40 +82,22 @@
79
82
 
80
83
  .autocomplete--secondary .autocomplete__trigger {
81
84
  @apply shadow-none;
82
- background-color: var(--autocomplete-trigger-bg);
83
85
 
84
86
  --autocomplete-trigger-bg: var(--default);
85
87
  --autocomplete-trigger-bg-hover: var(--default-hover);
86
88
  --autocomplete-trigger-bg-focus: var(--default);
87
-
88
- /* Exclude when clear button is hovered to prevent double hover effect */
89
- @media (hover: hover) {
90
- &:hover:not(:has(.autocomplete__clear-button:hover)),
91
- &[data-hovered="true"]:not(:has(.autocomplete__clear-button:hover)) {
92
- background-color: var(--autocomplete-trigger-bg-hover);
93
- }
94
- }
95
-
96
- &:focus-visible:not(:focus),
97
- &[data-focus-visible="true"] {
98
- background-color: var(--autocomplete-trigger-bg-focus);
99
- }
100
-
101
- &:focus,
102
- &[data-focus="true"] {
103
- }
104
-
105
- .autocomplete[data-invalid="true"] &,
106
- .autocomplete[aria-invalid="true"] & {
107
- background-color: var(--autocomplete-trigger-bg-focus);
108
- }
109
89
  }
110
90
 
111
91
  .autocomplete__value {
112
- @apply flex-1 text-start text-base wrap-break-word text-current sm:text-sm;
92
+ @apply flex-1 text-start wrap-break-word;
93
+
94
+ --autocomplete-value-fg: currentcolor;
95
+ --autocomplete-value-fg-placeholder: var(--field-placeholder, var(--muted));
96
+
97
+ color: var(--autocomplete-value-fg);
113
98
 
114
99
  &[data-placeholder="true"] {
115
- @apply text-field-placeholder;
100
+ color: var(--autocomplete-value-fg-placeholder);
116
101
  }
117
102
 
118
103
  /* Removes the list-box-item indicator element from the autocomplete value*/
@@ -139,7 +124,7 @@
139
124
  /* Similar to popover content styles */
140
125
  .autocomplete__popover {
141
126
  @apply flex w-(--trigger-width) max-w-(--trigger-width) origin-(--trigger-anchor-point) scroll-py-1 flex-col overflow-hidden overscroll-contain bg-overlay p-0 pt-2 text-sm outline-none;
142
- border-radius: min(32px, var(--radius-3xl));
127
+ border-radius: min(32px, var(--component-radius));
143
128
  box-shadow: var(--shadow-overlay);
144
129
 
145
130
  &:focus,
@@ -252,7 +237,12 @@
252
237
  /* Clear Button styles */
253
238
  .autocomplete__clear-button {
254
239
  @apply relative isolate inline-flex h-6 w-6 shrink-0 origin-center items-center justify-center rounded-xl p-1 text-muted select-none no-highlight;
255
- @apply me-0 size-5 shrink-0 self-center bg-transparent;
240
+ @apply me-0 size-5 shrink-0 self-center;
241
+
242
+ --autocomplete-clear-button-bg: transparent;
243
+ --autocomplete-clear-button-bg-hover: var(--default-hover);
244
+
245
+ background-color: var(--autocomplete-clear-button-bg);
256
246
 
257
247
  /* Cursor */
258
248
  cursor: var(--cursor-interactive);
@@ -280,7 +270,7 @@
280
270
  @media (hover: hover) {
281
271
  &:hover,
282
272
  &[data-hovered="true"] {
283
- @apply bg-default-hover;
273
+ background-color: var(--autocomplete-clear-button-bg-hover);
284
274
  }
285
275
  }
286
276
 
@@ -289,3 +279,31 @@
289
279
  transform: scale(0.93);
290
280
  }
291
281
  }
282
+
283
+ /* ==========================================================================
284
+ Size variants
285
+ ========================================================================== */
286
+
287
+ /* The trigger's own metrics, and the option rows in a popover that is portalled out of this tree -
288
+ * which is why the popover carries its own size class rather than being reached from the base. */
289
+ .autocomplete--sm .autocomplete__trigger {
290
+ @apply min-h-8 field-line-sm;
291
+ }
292
+
293
+ .autocomplete--lg .autocomplete__trigger {
294
+ @apply min-h-10 field-line-lg;
295
+ }
296
+
297
+ .autocomplete__popover--sm {
298
+ [data-slot="list-box-item"] {
299
+ @apply min-h-8 py-1;
300
+ }
301
+ }
302
+
303
+ .autocomplete__popover--lg {
304
+ @apply text-base;
305
+
306
+ [data-slot="list-box-item"] {
307
+ @apply min-h-10 py-2;
308
+ }
309
+ }
@@ -4,7 +4,12 @@
4
4
 
5
5
  /* Breadcrumb link */
6
6
  .breadcrumbs__link {
7
- @apply relative px-0.5 text-sm leading-5 font-medium text-muted no-underline opacity-100;
7
+ @apply relative px-0.5 text-sm leading-5 font-medium no-underline opacity-100;
8
+
9
+ --breadcrumbs-link-fg: var(--muted);
10
+ --breadcrumbs-link-fg-current: var(--link);
11
+
12
+ color: var(--breadcrumbs-link-fg);
8
13
 
9
14
  &:hover,
10
15
  &[data-hovered="true"] {
@@ -12,7 +17,9 @@
12
17
  }
13
18
 
14
19
  &[data-current="true"] {
15
- @apply text-link opacity-100;
20
+ @apply opacity-100;
21
+
22
+ color: var(--breadcrumbs-link-fg-current);
16
23
  }
17
24
  }
18
25
 
@@ -26,32 +26,32 @@
26
26
 
27
27
  /* Apply border radius to first button (start edge) */
28
28
  .button-group--horizontal .button:first-child {
29
- @apply rounded-s-3xl;
29
+ @apply rounded-s-component;
30
30
  }
31
31
 
32
32
  /* Apply border radius to last button (end edge) */
33
33
  .button-group--horizontal .button:last-child {
34
- @apply rounded-e-3xl;
34
+ @apply rounded-e-component;
35
35
  }
36
36
 
37
37
  /* If only one button, apply both rounded edges */
38
38
  .button-group--horizontal .button:first-child:last-child {
39
- @apply rounded-3xl;
39
+ @apply rounded-component;
40
40
  }
41
41
 
42
42
  /* Apply border radius to first button (top edge) in vertical */
43
43
  .button-group--vertical .button:first-child {
44
- @apply rounded-t-3xl;
44
+ @apply rounded-t-component;
45
45
  }
46
46
 
47
47
  /* Apply border radius to last button (bottom edge) in vertical */
48
48
  .button-group--vertical .button:last-child {
49
- @apply rounded-b-3xl;
49
+ @apply rounded-b-component;
50
50
  }
51
51
 
52
52
  /* If only one button in vertical, apply all rounded edges */
53
53
  .button-group--vertical .button:first-child:last-child {
54
- @apply rounded-3xl;
54
+ @apply rounded-component;
55
55
  }
56
56
 
57
57
  /* Remove scale transform on active/pressed state for buttons in group */
@@ -75,10 +75,6 @@
75
75
  position: absolute;
76
76
  pointer-events: none;
77
77
 
78
- /**
79
- * Transitions
80
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
81
- */
82
78
  transition: opacity 150ms var(--ease-smooth);
83
79
  @apply motion-reduce:transition-none;
84
80
 
@@ -2,12 +2,8 @@
2
2
 
3
3
  /* Base button styles */
4
4
  .button {
5
- @apply relative isolate inline-flex h-10 w-fit origin-center items-center justify-center gap-2 rounded-3xl px-4 text-sm font-medium whitespace-nowrap outline-none select-none no-highlight md:h-9;
5
+ @apply relative isolate inline-flex h-9 w-fit origin-center items-center justify-center gap-2 rounded-component px-4 text-sm font-medium whitespace-nowrap outline-none select-none no-highlight;
6
6
 
7
- /**
8
- * Transitions
9
- * CRITICAL: motion-reduce must be AFTER transition for correct override specificity
10
- */
11
7
  transition:
12
8
  transform 250ms var(--ease-smooth),
13
9
  background-color 100ms var(--ease-out),
@@ -69,17 +65,13 @@
69
65
 
70
66
  /* SVG icon styling - exclude spinner and link-icon svgs */
71
67
  & svg:not([data-slot="spinner"] svg, [data-slot="link-icon"] svg) {
72
- @apply pointer-events-none -mx-0.5 my-0.5 size-5 shrink-0 self-center sm:my-1 sm:size-4;
68
+ @apply pointer-events-none -mx-0.5 my-1 size-4 shrink-0 self-center;
73
69
  }
74
70
  }
75
71
 
76
72
  /* Size variants */
77
73
  .button--sm {
78
- @apply h-9 px-3 md:h-8;
79
-
80
- & svg:not([data-slot="spinner"] svg, [data-slot="link-icon"] svg) {
81
- @apply size-4;
82
- }
74
+ @apply h-8 px-3;
83
75
 
84
76
  &:active,
85
77
  &[data-pressed="true"] {
@@ -92,7 +84,7 @@
92
84
  }
93
85
 
94
86
  .button--lg {
95
- @apply h-11 text-base md:h-10;
87
+ @apply h-10 text-base;
96
88
 
97
89
  &:active,
98
90
  &[data-pressed="true"] {
@@ -134,14 +126,14 @@
134
126
  .button--ghost,
135
127
  .button--outline {
136
128
  --button-bg: transparent;
137
- --button-bg-hover: var(--default);
138
- --button-bg-pressed: var(--default);
129
+ --button-bg-hover: var(--state-layer);
130
+ --button-bg-pressed: var(--state-layer);
139
131
  --button-fg: var(--default-foreground);
140
132
  }
141
133
 
142
134
  .button--outline {
143
135
  @apply border border-border;
144
- --button-bg-hover: color-mix(in srgb, var(--default) 60%, transparent);
136
+ --button-bg-hover: color-mix(in oklab, var(--state-layer) 60%, transparent);
145
137
  }
146
138
 
147
139
  .button--danger {
@@ -168,15 +160,15 @@
168
160
 
169
161
  /* Icon-only modifier */
170
162
  .button--icon-only {
171
- @apply w-10 p-0 md:w-9;
163
+ @apply w-9 p-0;
172
164
  }
173
165
 
174
166
  .button--icon-only.button--sm {
175
- @apply w-9 md:w-8;
167
+ @apply w-8;
176
168
  }
177
169
 
178
170
  .button--icon-only.button--lg {
179
- @apply w-11 md:w-10;
171
+ @apply w-10;
180
172
  }
181
173
 
182
174
  /* Full width modifier */