@stisla/style 3.0.0-beta.8

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 (63) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +16 -0
  3. package/dist/accordion/accordion.css +194 -0
  4. package/dist/alert/alert.css +138 -0
  5. package/dist/autocomplete/autocomplete.css +193 -0
  6. package/dist/avatar/avatar.css +142 -0
  7. package/dist/avatar-group/avatar-group.css +42 -0
  8. package/dist/badge/badge.css +74 -0
  9. package/dist/breadcrumb/breadcrumb.css +71 -0
  10. package/dist/button/button.css +318 -0
  11. package/dist/button/index.d.ts +1 -0
  12. package/dist/button/index.js +6 -0
  13. package/dist/button-group/button-group.css +108 -0
  14. package/dist/card/card.css +219 -0
  15. package/dist/carousel/carousel.css +170 -0
  16. package/dist/checkbox/checkbox.css +98 -0
  17. package/dist/chunk-K45KLI3Y.js +74 -0
  18. package/dist/collapsible/collapsible.css +36 -0
  19. package/dist/combobox/combobox.css +106 -0
  20. package/dist/combobox/combobox.tomselect.css +251 -0
  21. package/dist/config-CARtrJ7I.d.ts +61 -0
  22. package/dist/dialog/dialog.css +258 -0
  23. package/dist/drawer/drawer.css +318 -0
  24. package/dist/empty-state/empty-state.css +138 -0
  25. package/dist/field/field.css +70 -0
  26. package/dist/icon-box/icon-box.css +64 -0
  27. package/dist/illustration/illustration.css +103 -0
  28. package/dist/index.d.ts +14 -0
  29. package/dist/index.js +60 -0
  30. package/dist/indicator/indicator.css +84 -0
  31. package/dist/input/input.css +220 -0
  32. package/dist/input-group/input-group.css +141 -0
  33. package/dist/kbd/kbd.css +55 -0
  34. package/dist/link/link.css +28 -0
  35. package/dist/list-group/list-group.css +261 -0
  36. package/dist/media/media.css +115 -0
  37. package/dist/menu/menu.css +237 -0
  38. package/dist/meter/meter.css +124 -0
  39. package/dist/navbar/navbar.css +170 -0
  40. package/dist/page/page.css +95 -0
  41. package/dist/pagination/pagination.css +125 -0
  42. package/dist/placeholders/placeholders.css +58 -0
  43. package/dist/popover/popover.css +251 -0
  44. package/dist/progress/progress.css +139 -0
  45. package/dist/radio/radio.css +81 -0
  46. package/dist/scroll-area/scroll-area.css +25 -0
  47. package/dist/scroll-area/scroll-area.overlayscrollbars.css +42 -0
  48. package/dist/select/select.css +282 -0
  49. package/dist/separator/separator.css +26 -0
  50. package/dist/sidebar/sidebar.css +493 -0
  51. package/dist/slider/slider.css +159 -0
  52. package/dist/spinner/spinner.css +65 -0
  53. package/dist/switch/switch.css +91 -0
  54. package/dist/table/table.css +284 -0
  55. package/dist/tabs/tabs.css +137 -0
  56. package/dist/textarea/textarea.css +99 -0
  57. package/dist/timeline/timeline.css +271 -0
  58. package/dist/toast/toast.css +267 -0
  59. package/dist/toggle/toggle.css +125 -0
  60. package/dist/toggle-group/toggle-group.css +87 -0
  61. package/dist/tooltip/tooltip.css +95 -0
  62. package/package.json +46 -0
  63. package/src/theme.css +151 -0
@@ -0,0 +1,282 @@
1
+ /* @stisla/style — Select. Ported from src/scss/components/_select.scss + the form-field-base mixin.
2
+ * THIS PORT COVERS THE NATIVE <select class="select"> (the no-JS baseline): the field shape + the
3
+ * chevron in the inline-end padding well, plus the [multiple]/[size] multi-line opt-out. References
4
+ * the @theme tokens (colors var(--color-*), spacing --spacing(n), type var(--text-*), radius
5
+ * var(--radius-*)); only no-namespace customs use --st-* (border-width, duration). Knobs --select-*.
6
+ *
7
+ * DEFERRED: the JS-hydrated custom trigger + popup (.select__trigger / __value / __popup / __item /
8
+ * __indicator / __group-label) builds on the shared menu-surface recipe and Stisla.Select behavior —
9
+ * both land in a later pass (menu + @stisla/vanilla). Native select needs none of it.
10
+ *
11
+ * The field base is DUPLICATED here with --select-* (plain CSS has no parameterized mixin); keep in
12
+ * sync with input.css + textarea.css. Uses background-color (not the `background` shorthand) so the
13
+ * chevron background-image survives. State is native, no is-*. @layer components.
14
+ * Authoring rules: ../../../../PORTING.md */
15
+
16
+ @layer components {
17
+ .select {
18
+ display: block;
19
+ width: 100%;
20
+ height: var(--select-height, --spacing(9));
21
+ padding-block: var(--select-padding-block, 0);
22
+ padding-inline: var(--select-padding-inline, --spacing(2.5));
23
+ /* Chevron well on the inline-end edge. */
24
+ padding-inline-end: --spacing(9);
25
+ font-family: inherit;
26
+ font-size: var(--select-font-size, var(--text-sm));
27
+ font-weight: var(--font-weight-normal);
28
+ line-height: var(--leading-tight);
29
+ color: var(--select-color, var(--color-foreground));
30
+ background-color: var(--select-bg, var(--color-surface));
31
+ /* Chevron — fallback-default custom prop so a scope can swap the SVG. The stroke must be a literal
32
+ (CSS vars don't resolve in url()); the dark scope below swaps to a lighter chevron. */
33
+ background-image: var(
34
+ --select-indicator,
35
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 6 8 10 12 6'/%3E%3C/svg%3E")
36
+ );
37
+ background-position: right --spacing(3) center;
38
+ background-repeat: no-repeat;
39
+ background-size: --spacing(3) --spacing(3);
40
+ border: var(--select-border-width, var(--st-border-width)) solid
41
+ var(--select-border-color, var(--color-border-strong));
42
+ border-radius: var(--select-radius, var(--radius-md));
43
+ appearance: none;
44
+ cursor: pointer;
45
+ transition:
46
+ border-color var(--transition-duration-fast) ease,
47
+ box-shadow var(--transition-duration-fast) ease,
48
+ background-color var(--transition-duration-fast) ease;
49
+
50
+ /* iOS Safari zooms when a focused field's font-size < 16px and never zooms back. */
51
+ @media (pointer: coarse) {
52
+ font-size: var(--select-font-size, var(--text-base));
53
+ }
54
+
55
+ &:hover:not(:disabled, :focus-visible, [aria-invalid="true"], :user-invalid) {
56
+ border-color: color-mix(in oklch, var(--color-border-strong) 80%, var(--color-foreground));
57
+ }
58
+
59
+ &:focus-visible {
60
+ outline: none;
61
+ border-color: var(--color-primary);
62
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-ring) 25%, transparent);
63
+ }
64
+
65
+ &[aria-invalid="true"],
66
+ &:user-invalid {
67
+ border-color: var(--color-danger);
68
+ }
69
+ &[aria-invalid="true"]:focus-visible,
70
+ &:user-invalid:focus-visible {
71
+ border-color: var(--color-danger);
72
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-danger) 25%, transparent);
73
+ }
74
+
75
+ &:disabled {
76
+ opacity: 0.55;
77
+ cursor: not-allowed;
78
+ }
79
+
80
+ &[readonly]:not(:disabled) {
81
+ background-color: var(--color-surface-2);
82
+ }
83
+
84
+ @media (prefers-reduced-motion: reduce) {
85
+ transition: none;
86
+ }
87
+
88
+ /* Dark — every token-driven property flips via theme.css; only the chevron can't (data: URLs are
89
+ static), so swap to the same geometry with a lighter stroke. @variant dark uses the registered
90
+ custom-variant ([data-theme="dark"] / .dark). */
91
+ @variant dark {
92
+ --select-indicator: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 6 8 10 12 6'/%3E%3C/svg%3E");
93
+ }
94
+ }
95
+
96
+ /* Multi-line native selects (<select multiple> or <select size> > 1) render as inline lists: drop
97
+ the chevron, restore native rendering, opt out of the hard-height contract (same shape as
98
+ textarea). Scoped to <select> so it never hits a future JS trigger button. */
99
+ select.select[multiple],
100
+ select.select[size]:not([size="1"]) {
101
+ height: auto;
102
+ min-height: var(--select-height, --spacing(9));
103
+ padding-block: --spacing(1.5);
104
+ padding-inline: var(--select-padding-inline, --spacing(2.5));
105
+ appearance: auto;
106
+ background-image: none;
107
+ }
108
+
109
+ /* === Sizes (base = md) === */
110
+ .select--sm {
111
+ --select-radius: var(--radius-sm);
112
+ --select-height: --spacing(7);
113
+ --select-padding-inline: --spacing(2);
114
+ --select-font-size: var(--text-xs);
115
+ @media (pointer: coarse) {
116
+ --select-font-size: var(--text-base);
117
+ }
118
+ }
119
+
120
+ .select--lg {
121
+ --select-radius: var(--radius-lg);
122
+ --select-height: --spacing(11);
123
+ --select-padding-inline: --spacing(3.5);
124
+ --select-font-size: var(--text-base);
125
+ }
126
+ }
127
+
128
+ /* === Custom select (JS-hydrated) === Stisla.Select hides the native <select class="select"
129
+ * data-stisla-select> and inserts a sibling <button class="select select__trigger"> + <ul
130
+ * class="select__popup" role="listbox">. The button reuses the .select field shape, so it inherits the
131
+ * shape/border/chevron/sizes/validation; the popup expands the shared menu-surface recipe inline with
132
+ * --select-* knobs so it matches .menu / combobox / autocomplete. Highlight is [data-highlighted]
133
+ * (keyboard cursor) and selected is [aria-selected="true"] — both recast from the legacy is-* classes
134
+ * per the no-is-* convention. Positioning (Floating UI) ships with the JS layer. @layer components. */
135
+ @layer components {
136
+ /* Hide the hydrated source <select> as belt-and-braces (JS also sets the [hidden] attribute). */
137
+ select.select[data-stisla-select][hidden] {
138
+ display: none !important;
139
+ }
140
+
141
+ /* === Trigger === same .select shell + internal flex for the value text + optional "+N more" chip. */
142
+ .select__trigger {
143
+ display: inline-flex;
144
+ align-items: center;
145
+ gap: --spacing(2);
146
+ text-align: start;
147
+ }
148
+
149
+ .select__value {
150
+ flex: 1 1 auto;
151
+ min-width: 0;
152
+ overflow: hidden;
153
+ text-overflow: ellipsis;
154
+ white-space: nowrap;
155
+ }
156
+ /* Empty value → placeholder via attr() (declarative; the JS never writes the placeholder string). */
157
+ .select__value:empty::before {
158
+ content: attr(data-placeholder);
159
+ color: var(--select-placeholder, var(--color-muted-foreground));
160
+ }
161
+
162
+ .select__more {
163
+ flex-shrink: 0;
164
+ font-size: var(--select-more-font-size, var(--text-xs));
165
+ color: var(--select-placeholder, var(--color-muted-foreground));
166
+ }
167
+
168
+ /* === Popup === the menu-surface recipe; the JS (Floating UI) sets position/left/top inline. */
169
+ .select__popup {
170
+ padding: var(--select-popup-padding-block, --spacing(1))
171
+ var(--select-popup-padding-inline, --spacing(1));
172
+ font-size: var(--select-font-size, var(--text-sm));
173
+ line-height: var(--leading-normal);
174
+ color: var(--select-color, var(--color-foreground));
175
+ background-color: var(--select-bg, var(--color-surface));
176
+ border: var(--select-border-width, var(--st-border-width)) solid
177
+ var(--select-popup-border-color, var(--color-border));
178
+ border-radius: var(--select-radius, var(--radius-md));
179
+ box-shadow: var(--select-shadow, var(--shadow-md));
180
+ position: absolute;
181
+ top: 0;
182
+ left: 0;
183
+ z-index: var(--select-z-index, var(--z-index-dropdown));
184
+ display: flex;
185
+ flex-direction: column;
186
+ gap: var(--select-item-gap, --spacing(0.5));
187
+ margin: 0;
188
+ list-style: none;
189
+ overflow-y: auto;
190
+ }
191
+ .select__popup[hidden] {
192
+ display: none;
193
+ }
194
+
195
+ /* === Item === the menu-item recipe. Concentric inner radius = popup radius − inline gutter. */
196
+ .select__item {
197
+ display: flex;
198
+ align-items: center;
199
+ gap: var(--select-item-gap-inner, --spacing(2));
200
+ width: 100%;
201
+ min-height: var(--select-item-min-height, --spacing(8));
202
+ padding: var(--select-item-padding-block, --spacing(0.5))
203
+ var(--select-item-padding-inline, --spacing(3));
204
+ font: inherit;
205
+ color: var(--select-color, var(--color-foreground));
206
+ text-align: start;
207
+ background-color: transparent;
208
+ border: 0;
209
+ border-radius: var(
210
+ --select-item-radius,
211
+ calc(var(--select-radius, var(--radius-md)) - var(--select-popup-padding-inline, --spacing(1)))
212
+ );
213
+ cursor: pointer;
214
+ user-select: none;
215
+ transition:
216
+ background-color var(--transition-duration-fast) ease,
217
+ color var(--transition-duration-fast) ease;
218
+ }
219
+
220
+ /* Hover (mouse) + [data-highlighted] (keyboard nav) paint the same accent chip. */
221
+ .select__item:hover,
222
+ .select__item[data-highlighted] {
223
+ color: var(--select-item-color-hover, var(--color-accent-foreground));
224
+ background-color: var(--select-item-bg-hover, var(--color-accent));
225
+ }
226
+
227
+ /* Selected — persists past hover/highlight so the chosen value stays visible. */
228
+ .select__item[aria-selected="true"],
229
+ .select__item[aria-selected="true"]:hover,
230
+ .select__item[aria-selected="true"][data-highlighted] {
231
+ color: var(--select-item-color-active, var(--color-highlight-foreground));
232
+ background-color: var(--select-item-bg-active, var(--color-highlight));
233
+ }
234
+
235
+ .select__item[aria-disabled="true"] {
236
+ color: var(--select-item-color-disabled, var(--color-muted-foreground));
237
+ background-color: transparent;
238
+ pointer-events: none;
239
+ }
240
+
241
+ /* Selected-option check — the slot footprint is always reserved (visibility, not display) so rows stay
242
+ column-aligned; order:1 + auto margin push it to the trailing edge. The JS renders the slot + glyph
243
+ in every row; it shows only on the selected row. */
244
+ .select__indicator {
245
+ display: inline-flex;
246
+ align-items: center;
247
+ justify-content: center;
248
+ width: var(--select-item-icon-size, --spacing(4));
249
+ height: var(--select-item-icon-size, --spacing(4));
250
+ flex-shrink: 0;
251
+ order: 1;
252
+ margin-inline-start: auto;
253
+ color: inherit;
254
+ visibility: hidden;
255
+ }
256
+ .select__item[aria-selected="true"] .select__indicator {
257
+ visibility: visible;
258
+ }
259
+
260
+ /* === Group label === */
261
+ .select__group-label {
262
+ display: flex;
263
+ align-items: center;
264
+ padding: var(--select-group-label-padding-block, --spacing(1))
265
+ var(--select-group-label-padding-inline, --spacing(3));
266
+ margin: 0;
267
+ font-size: var(--select-group-label-font-size, var(--text-xs));
268
+ font-weight: var(--select-group-label-font-weight, var(--font-weight-semibold));
269
+ color: var(--select-group-label-color, var(--color-muted-foreground));
270
+ white-space: nowrap;
271
+ }
272
+ /* Subsequent group headers get top space so the section break reads as a divider. */
273
+ .select__item + .select__group-label {
274
+ margin-block-start: --spacing(2);
275
+ }
276
+
277
+ @media (prefers-reduced-motion: reduce) {
278
+ .select__item {
279
+ transition: none;
280
+ }
281
+ }
282
+ }
@@ -0,0 +1,26 @@
1
+ /* @stisla/style — Separator. Ported from src/scss/components/_separator.scss. Hairline divider:
2
+ * horizontal sits in flow as a full-width rule (<hr class="separator">); vertical works inside a flex
3
+ * row, where align-self: stretch sizes it to the cross axis. References the @theme tokens (colors
4
+ * var(--color-*), spacing --spacing(n)); the hairline thickness defaults to the --st-border-width
5
+ * custom. Knobs are --separator-*. @layer components. Authoring rules: ../../../../PORTING.md */
6
+
7
+ @layer components {
8
+ .separator {
9
+ display: block;
10
+ flex-shrink: 0;
11
+ width: 100%;
12
+ height: var(--separator-thickness, var(--st-border-width));
13
+ margin: 0;
14
+ background: var(--separator-color, var(--color-border));
15
+ border: 0;
16
+ }
17
+
18
+ /* Vertical — inside a flex row align-self: stretch fills the cross axis; the min-height floor keeps
19
+ the rule visible when the parent is not a flex container. */
20
+ .separator--vertical {
21
+ width: var(--separator-thickness, var(--st-border-width));
22
+ height: auto;
23
+ min-height: var(--separator-min-height, --spacing(5));
24
+ align-self: stretch;
25
+ }
26
+ }