sh-ui-cli 0.49.0 → 0.50.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 (85) hide show
  1. package/data/changelog/versions.json +14 -0
  2. package/data/registry/react/components/accordion/index.vanilla-extract.tsx +97 -0
  3. package/data/registry/react/components/accordion/styles.css.ts +131 -0
  4. package/data/registry/react/components/avatar/index.vanilla-extract.tsx +73 -0
  5. package/data/registry/react/components/avatar/styles.css.ts +68 -0
  6. package/data/registry/react/components/badge/index.vanilla-extract.tsx +40 -0
  7. package/data/registry/react/components/badge/styles.css.ts +71 -0
  8. package/data/registry/react/components/breadcrumb/index.vanilla-extract.tsx +152 -0
  9. package/data/registry/react/components/breadcrumb/styles.css.ts +95 -0
  10. package/data/registry/react/components/calendar/index.vanilla-extract.tsx +806 -0
  11. package/data/registry/react/components/calendar/styles.css.ts +250 -0
  12. package/data/registry/react/components/carousel/index.vanilla-extract.tsx +430 -0
  13. package/data/registry/react/components/carousel/styles.css.ts +169 -0
  14. package/data/registry/react/components/checkbox/index.vanilla-extract.tsx +96 -0
  15. package/data/registry/react/components/checkbox/styles.css.ts +74 -0
  16. package/data/registry/react/components/code-editor/index.vanilla-extract.tsx +230 -0
  17. package/data/registry/react/components/code-editor/styles.css.ts +97 -0
  18. package/data/registry/react/components/code-panel/index.vanilla-extract.tsx +191 -0
  19. package/data/registry/react/components/code-panel/styles.css.ts +151 -0
  20. package/data/registry/react/components/color-picker/index.vanilla-extract.tsx +467 -0
  21. package/data/registry/react/components/color-picker/styles.css.ts +169 -0
  22. package/data/registry/react/components/combobox/index.vanilla-extract.tsx +165 -0
  23. package/data/registry/react/components/combobox/styles.css.ts +174 -0
  24. package/data/registry/react/components/context-menu/index.vanilla-extract.tsx +251 -0
  25. package/data/registry/react/components/context-menu/styles.css.ts +167 -0
  26. package/data/registry/react/components/date-picker/index.vanilla-extract.tsx +520 -0
  27. package/data/registry/react/components/date-picker/styles.css.ts +111 -0
  28. package/data/registry/react/components/dialog/index.vanilla-extract.tsx +95 -0
  29. package/data/registry/react/components/dialog/styles.css.ts +140 -0
  30. package/data/registry/react/components/dropdown-menu/index.vanilla-extract.tsx +255 -0
  31. package/data/registry/react/components/dropdown-menu/styles.css.ts +175 -0
  32. package/data/registry/react/components/file-upload/index.vanilla-extract.tsx +487 -0
  33. package/data/registry/react/components/file-upload/styles.css.ts +193 -0
  34. package/data/registry/react/components/form/index.vanilla-extract.tsx +61 -0
  35. package/data/registry/react/components/form/styles.css.ts +56 -0
  36. package/data/registry/react/components/header/index.vanilla-extract.tsx +805 -0
  37. package/data/registry/react/components/header/styles.css.ts +413 -0
  38. package/data/registry/react/components/label/index.vanilla-extract.tsx +52 -0
  39. package/data/registry/react/components/label/styles.css.ts +141 -0
  40. package/data/registry/react/components/markdown-editor/index.vanilla-extract.tsx +119 -0
  41. package/data/registry/react/components/markdown-editor/styles.css.ts +231 -0
  42. package/data/registry/react/components/menubar/index.vanilla-extract.tsx +32 -0
  43. package/data/registry/react/components/menubar/styles.css.ts +53 -0
  44. package/data/registry/react/components/numeric-input/index.vanilla-extract.tsx +148 -0
  45. package/data/registry/react/components/numeric-input/styles.css.ts +65 -0
  46. package/data/registry/react/components/page-toc/index.vanilla-extract.tsx +174 -0
  47. package/data/registry/react/components/page-toc/styles.css.ts +97 -0
  48. package/data/registry/react/components/pagination/index.vanilla-extract.tsx +269 -0
  49. package/data/registry/react/components/pagination/styles.css.ts +113 -0
  50. package/data/registry/react/components/popover/index.vanilla-extract.tsx +113 -0
  51. package/data/registry/react/components/popover/styles.css.ts +78 -0
  52. package/data/registry/react/components/progress/index.vanilla-extract.tsx +54 -0
  53. package/data/registry/react/components/progress/styles.css.ts +53 -0
  54. package/data/registry/react/components/radio/index.vanilla-extract.tsx +65 -0
  55. package/data/registry/react/components/radio/styles.css.ts +79 -0
  56. package/data/registry/react/components/rich-text-editor/index.vanilla-extract.tsx +348 -0
  57. package/data/registry/react/components/rich-text-editor/styles.css.ts +243 -0
  58. package/data/registry/react/components/select/index.vanilla-extract.tsx +234 -0
  59. package/data/registry/react/components/select/styles.css.ts +225 -0
  60. package/data/registry/react/components/separator/index.vanilla-extract.tsx +46 -0
  61. package/data/registry/react/components/separator/styles.css.ts +24 -0
  62. package/data/registry/react/components/sidebar/index.vanilla-extract.tsx +1067 -0
  63. package/data/registry/react/components/sidebar/styles.css.ts +578 -0
  64. package/data/registry/react/components/skeleton/index.vanilla-extract.tsx +22 -0
  65. package/data/registry/react/components/skeleton/styles.css.ts +30 -0
  66. package/data/registry/react/components/slider/index.vanilla-extract.tsx +298 -0
  67. package/data/registry/react/components/slider/styles.css.ts +75 -0
  68. package/data/registry/react/components/spinner/index.vanilla-extract.tsx +38 -0
  69. package/data/registry/react/components/spinner/styles.css.ts +60 -0
  70. package/data/registry/react/components/switch/index.vanilla-extract.tsx +39 -0
  71. package/data/registry/react/components/switch/styles.css.ts +87 -0
  72. package/data/registry/react/components/tabs/index.vanilla-extract.tsx +91 -0
  73. package/data/registry/react/components/tabs/styles.css.ts +145 -0
  74. package/data/registry/react/components/textarea/index.vanilla-extract.tsx +23 -0
  75. package/data/registry/react/components/textarea/styles.css.ts +55 -0
  76. package/data/registry/react/components/toast/index.vanilla-extract.tsx +258 -0
  77. package/data/registry/react/components/toast/styles.css.ts +307 -0
  78. package/data/registry/react/components/toggle/index.vanilla-extract.tsx +131 -0
  79. package/data/registry/react/components/toggle/styles.css.ts +109 -0
  80. package/data/registry/react/components/tooltip/index.vanilla-extract.tsx +83 -0
  81. package/data/registry/react/components/tooltip/styles.css.ts +59 -0
  82. package/data/registry/react/registry.json +853 -36
  83. package/package.json +1 -1
  84. package/src/api.d.ts +4 -3
  85. package/src/constants.js +4 -3
@@ -0,0 +1,578 @@
1
+ import { style, keyframes } from "@vanilla-extract/css";
2
+
3
+ export const shUiSidebarPanelIn = keyframes({
4
+ "from": {
5
+ transform: "translateX(-8px)",
6
+ opacity: 0,
7
+ },
8
+ "to": {
9
+ transform: "translateX(0)",
10
+ opacity: 1,
11
+ },
12
+ });
13
+
14
+ export const sidebarWrapper = style({
15
+ "--sidebar-width": "16rem",
16
+ "--sidebar-width-icon": "3rem",
17
+ "--sidebar-width-mobile": "18rem",
18
+ "--sidebar-bg": "var(--background-subtle)",
19
+ "--sidebar-fg": "var(--foreground)",
20
+ "--sidebar-border": "var(--border)",
21
+ "--sidebar-accent": "var(--background-muted)",
22
+ "--sidebar-accent-fg": "var(--foreground)",
23
+ display: "flex",
24
+ minHeight: "100svh",
25
+ width: "100%",
26
+ selectors: {
27
+ "&[data-embedded]": {
28
+ minHeight: 0,
29
+ height: "100%",
30
+ },
31
+ [`&[data-embedded] ${sidebar__inner}`]: {
32
+ height: "100%",
33
+ position: "relative",
34
+ top: 0,
35
+ },
36
+ [`&[data-embedded] ${sidebarStatic}`]: {
37
+ height: "100%",
38
+ position: "relative",
39
+ top: 0,
40
+ },
41
+ [`&[data-embedded] ${sidebarMobile}`]: {
42
+ position: "absolute",
43
+ },
44
+ [`&[data-embedded] ${sidebar__backdrop}`]: {
45
+ position: "absolute",
46
+ },
47
+ [`&[data-embedded] ${sidebar__panel}`]: {
48
+ position: "relative",
49
+ },
50
+ },
51
+ });
52
+
53
+ export const sidebar = style({
54
+ display: "flex",
55
+ flexDirection: "column",
56
+ width: "var(--sidebar-width)",
57
+ flexShrink: 0,
58
+ background: "var(--sidebar-bg)",
59
+ color: "var(--sidebar-fg)",
60
+ borderRight: "1px solid var(--sidebar-border)",
61
+ transition: "width var(--duration-slow) ease",
62
+ position: "relative",
63
+ zIndex: 5,
64
+ selectors: {
65
+ "&[data-side="right"]": {
66
+ borderRight: "none",
67
+ borderLeft: "1px solid var(--sidebar-border)",
68
+ order: 1,
69
+ },
70
+ "&[data-state="collapsed"][data-collapsible="offcanvas"]": {
71
+ width: 0,
72
+ borderRightWidth: 0,
73
+ borderLeftWidth: 0,
74
+ overflow: "hidden",
75
+ },
76
+ "&[data-state="collapsed"][data-collapsible="icon"]": {
77
+ width: "var(--sidebar-width-icon)",
78
+ },
79
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebarGroupLabel}`]: {
80
+ display: "none",
81
+ },
82
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebarMenuButton} > span`]: {
83
+ display: "none",
84
+ },
85
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebarMenuSub}`]: {
86
+ display: "none",
87
+ },
88
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebarMenuButton}`]: {
89
+ justifyContent: "center",
90
+ padding: "var(--space-2)",
91
+ },
92
+ "&[data-variant="floating"]": {
93
+ border: "none",
94
+ padding: "var(--space-2)",
95
+ background: "transparent",
96
+ },
97
+ [`&[data-variant="floating"] ${sidebar__inner}`]: {
98
+ border: "1px solid var(--sidebar-border)",
99
+ borderRadius: "var(--radius)",
100
+ background: "var(--sidebar-bg)",
101
+ height: "calc(100svh - 1rem)",
102
+ top: "var(--space-2)",
103
+ },
104
+ "&[data-variant="inset"]": {
105
+ background: "transparent",
106
+ border: "none",
107
+ },
108
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebar__chevron}`]: {
109
+ display: "none",
110
+ },
111
+ [`&[data-state="collapsed"][data-collapsible="icon"] ${sidebarCollapsibleContent}`]: {
112
+ display: "none",
113
+ },
114
+ },
115
+ "@media": {
116
+ "(prefers-reduced-motion: reduce)": {
117
+ transition: "none",
118
+ },
119
+ },
120
+ });
121
+
122
+ export const sidebar__inner = style({
123
+ display: "flex",
124
+ flexDirection: "column",
125
+ height: "100svh",
126
+ position: "sticky",
127
+ top: 0,
128
+ overflow: "hidden",
129
+ });
130
+
131
+ export const sidebarStatic = style({
132
+ height: "100svh",
133
+ position: "sticky",
134
+ top: 0,
135
+ });
136
+
137
+ export const sidebarMobile = style({
138
+ position: "fixed",
139
+ top: 0,
140
+ bottom: 0,
141
+ width: "var(--sidebar-width-mobile)",
142
+ zIndex: "var(--z-overlay)",
143
+ transition: "transform var(--duration-slow) ease",
144
+ borderRight: "1px solid var(--sidebar-border)",
145
+ selectors: {
146
+ "&[data-side="left"]": {
147
+ left: 0,
148
+ transform: "translateX(-100%)",
149
+ },
150
+ "&[data-side="right"]": {
151
+ right: 0,
152
+ transform: "translateX(100%)",
153
+ borderRight: "none",
154
+ borderLeft: "1px solid var(--sidebar-border)",
155
+ },
156
+ "&[data-state="open"]": {
157
+ transform: "translateX(0)",
158
+ },
159
+ },
160
+ "@media": {
161
+ "(prefers-reduced-motion: reduce)": {
162
+ transition: "none",
163
+ },
164
+ },
165
+ });
166
+
167
+ export const sidebar__backdrop = style({
168
+ position: "fixed",
169
+ inset: 0,
170
+ background: "rgba(0, 0, 0, 0.25)",
171
+ backdropFilter: "blur(8px)",
172
+ zIndex: 40,
173
+ });
174
+
175
+ export const sidebar__trigger = style({
176
+ display: "inline-flex",
177
+ alignItems: "center",
178
+ justifyContent: "center",
179
+ width: "2rem",
180
+ height: "2rem",
181
+ border: "1px solid transparent",
182
+ background: "transparent",
183
+ color: "var(--foreground-muted)",
184
+ borderRadius: "calc(var(--radius) - 2px)",
185
+ cursor: "pointer",
186
+ transition: "background-color var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast)",
187
+ selectors: {
188
+ "&:hover": {
189
+ background: "var(--sidebar-accent)",
190
+ color: "var(--foreground)",
191
+ },
192
+ "&:focus-visible": {
193
+ outline: "var(--border-width-strong) solid var(--foreground)",
194
+ outlineOffset: "2px",
195
+ },
196
+ },
197
+ "@media": {
198
+ "(prefers-reduced-motion: reduce)": {
199
+ transition: "none",
200
+ },
201
+ },
202
+ });
203
+
204
+ export const sidebar__panel = style({
205
+ "--sidebar-panel-width": "20rem",
206
+ display: "flex",
207
+ flexDirection: "column",
208
+ width: "var(--sidebar-panel-width)",
209
+ flexShrink: 0,
210
+ background: "var(--background)",
211
+ borderRight: "1px solid var(--sidebar-border)",
212
+ position: "relative",
213
+ zIndex: 4,
214
+ overflow: "hidden",
215
+ animation: "sh-ui-sidebar-panel-in 180ms ease",
216
+ selectors: {
217
+ "&[data-state="closed"]": {
218
+ display: "none",
219
+ },
220
+ },
221
+ "@media": {
222
+ "(max-width: 47.9375rem)": {
223
+ position: "fixed",
224
+ top: 0,
225
+ bottom: 0,
226
+ left: 0,
227
+ width: "min(var(--sidebar-panel-width), 90vw)",
228
+ zIndex: "var(--z-modal)",
229
+ borderRight: "1px solid var(--sidebar-border)",
230
+ boxShadow: "0 10px 30px rgba(0, 0, 0, 0.15)",
231
+ },
232
+ "(prefers-reduced-motion: reduce)": {
233
+ animation: "none",
234
+ },
235
+ },
236
+ });
237
+
238
+ export const sidebarPanelHeader = style({
239
+ display: "flex",
240
+ alignItems: "center",
241
+ gap: "var(--space-2)",
242
+ padding: "0.875rem var(--space-4)",
243
+ borderBottom: "1px solid var(--sidebar-border)",
244
+ fontWeight: "var(--weight-semibold)",
245
+ fontSize: "0.9375rem",
246
+ });
247
+
248
+ export const sidebarPanelContent = style({
249
+ flex: "1 1 auto",
250
+ minHeight: 0,
251
+ overflowY: "auto",
252
+ padding: "var(--space-3) var(--space-4) var(--space-4)",
253
+ });
254
+
255
+ export const sidebarPanelClose = style({
256
+ position: "absolute",
257
+ top: "var(--space-2)",
258
+ right: "var(--space-2)",
259
+ display: "inline-flex",
260
+ alignItems: "center",
261
+ justifyContent: "center",
262
+ width: "2rem",
263
+ height: "2rem",
264
+ border: 0,
265
+ borderRadius: "calc(var(--radius) - 2px)",
266
+ background: "transparent",
267
+ color: "var(--foreground-muted)",
268
+ fontSize: "var(--text-lg)",
269
+ lineHeight: 1,
270
+ cursor: "pointer",
271
+ transition: "background-color var(--duration-fast), color var(--duration-fast)",
272
+ selectors: {
273
+ "&:hover": {
274
+ background: "var(--sidebar-accent)",
275
+ color: "var(--foreground)",
276
+ },
277
+ },
278
+ "@media": {
279
+ "(prefers-reduced-motion: reduce)": {
280
+ transition: "none",
281
+ },
282
+ },
283
+ });
284
+
285
+ export const sidebarInset = style({
286
+ flex: "1 1 0%",
287
+ minWidth: 0,
288
+ background: "var(--background)",
289
+ display: "flex",
290
+ flexDirection: "column",
291
+ });
292
+
293
+ export const sidebar__header = style({
294
+ display: "flex",
295
+ flexDirection: "column",
296
+ gap: "var(--space-2)",
297
+ padding: "var(--space-2)",
298
+ overflow: "hidden",
299
+ });
300
+
301
+ export const sidebar__footer = style({
302
+ display: "flex",
303
+ flexDirection: "column",
304
+ gap: "var(--space-2)",
305
+ padding: "var(--space-2)",
306
+ overflow: "hidden",
307
+ });
308
+
309
+ export const sidebar__content = style({
310
+ display: "flex",
311
+ flexDirection: "column",
312
+ flex: "1 1 0%",
313
+ minHeight: 0,
314
+ overflowY: "auto",
315
+ gap: 0,
316
+ });
317
+
318
+ export const sidebar__separator = style({
319
+ margin: "var(--space-1) var(--space-2)",
320
+ border: "none",
321
+ borderTop: "1px solid var(--sidebar-border)",
322
+ width: "auto",
323
+ });
324
+
325
+ export const sidebar__group = style({
326
+ display: "flex",
327
+ flexDirection: "column",
328
+ padding: "var(--space-2)",
329
+ minWidth: 0,
330
+ });
331
+
332
+ export const sidebarGroupLabel = style({
333
+ display: "flex",
334
+ alignItems: "center",
335
+ height: "2rem",
336
+ padding: "0 var(--space-2)",
337
+ fontSize: "var(--text-xs)",
338
+ fontWeight: "var(--weight-medium)",
339
+ color: "var(--foreground-muted)",
340
+ borderRadius: "calc(var(--radius) - 2px)",
341
+ });
342
+
343
+ export const sidebarGroupContent = style({
344
+ width: "100%",
345
+ fontSize: "var(--text-sm)",
346
+ });
347
+
348
+ export const sidebar__menu = style({
349
+ listStyle: "none",
350
+ margin: 0,
351
+ padding: 0,
352
+ display: "flex",
353
+ flexDirection: "column",
354
+ minWidth: 0,
355
+ gap: 0,
356
+ });
357
+
358
+ export const sidebarMenuItem = style({
359
+ position: "relative",
360
+ margin: 0,
361
+ });
362
+
363
+ export const sidebarMenuButton = style({
364
+ display: "flex",
365
+ width: "100%",
366
+ alignItems: "center",
367
+ gap: "var(--space-2)",
368
+ padding: "var(--space-2)",
369
+ textAlign: "left",
370
+ fontSize: "var(--text-sm)",
371
+ color: "var(--sidebar-fg)",
372
+ background: "transparent",
373
+ border: "none",
374
+ borderRadius: "calc(var(--radius) - 2px)",
375
+ cursor: "pointer",
376
+ transition: "background-color var(--duration-fast), color var(--duration-fast)",
377
+ textDecoration: "none",
378
+ fontFamily: "inherit",
379
+ lineHeight: 1.4,
380
+ selectors: {
381
+ "& > svg": {
382
+ width: "1rem",
383
+ height: "1rem",
384
+ flexShrink: 0,
385
+ },
386
+ "& > span": {
387
+ flex: "1 1 0%",
388
+ minWidth: 0,
389
+ overflow: "hidden",
390
+ textOverflow: "ellipsis",
391
+ whiteSpace: "nowrap",
392
+ },
393
+ "&:hover": {
394
+ background: "var(--sidebar-accent)",
395
+ color: "var(--sidebar-accent-fg)",
396
+ },
397
+ "&:focus-visible": {
398
+ outline: "var(--border-width-strong) solid var(--foreground)",
399
+ outlineOffset: "-2px",
400
+ },
401
+ "&[data-active]": {
402
+ background: "var(--primary)",
403
+ color: "var(--primary-foreground)",
404
+ fontWeight: "var(--weight-semibold)",
405
+ },
406
+ "&[data-active]:hover": {
407
+ background: "var(--primary-hover)",
408
+ color: "var(--primary-foreground)",
409
+ },
410
+ "&:disabled": {
411
+ opacity: "var(--opacity-disabled)",
412
+ pointerEvents: "none",
413
+ },
414
+ "&[aria-disabled="true"]": {
415
+ opacity: "var(--opacity-disabled)",
416
+ pointerEvents: "none",
417
+ },
418
+ },
419
+ "@media": {
420
+ "(prefers-reduced-motion: reduce)": {
421
+ transition: "none",
422
+ },
423
+ },
424
+ });
425
+
426
+ export const sidebarMenuButtonSm = style({
427
+ height: "1.75rem",
428
+ padding: "var(--space-1) var(--space-2)",
429
+ fontSize: "0.8125rem",
430
+ });
431
+
432
+ export const sidebarMenuButtonLg = style({
433
+ padding: "var(--space-3)",
434
+ fontSize: "0.9375rem",
435
+ });
436
+
437
+ export const sidebarMenuSub = style({
438
+ listStyle: "none",
439
+ margin: "0.125rem 0 0",
440
+ padding: "0.125rem 0 0.125rem 0.625rem",
441
+ marginLeft: "0.875rem",
442
+ borderLeft: "1px solid var(--sidebar-border)",
443
+ display: "flex",
444
+ flexDirection: "column",
445
+ gap: "0.125rem",
446
+ minWidth: 0,
447
+ });
448
+
449
+ export const sidebarMenuSubItem = style({
450
+ position: "relative",
451
+ });
452
+
453
+ export const sidebarMenuSubButton = style({
454
+ display: "flex",
455
+ alignItems: "center",
456
+ gap: "var(--space-2)",
457
+ height: "1.75rem",
458
+ padding: "0 var(--space-2)",
459
+ borderRadius: "calc(var(--radius) - 2px)",
460
+ fontSize: "0.8125rem",
461
+ color: "var(--sidebar-fg)",
462
+ textDecoration: "none",
463
+ transition: "background-color var(--duration-fast), color var(--duration-fast)",
464
+ minWidth: 0,
465
+ selectors: {
466
+ "& > span": {
467
+ flex: "1 1 0%",
468
+ minWidth: 0,
469
+ overflow: "hidden",
470
+ textOverflow: "ellipsis",
471
+ whiteSpace: "nowrap",
472
+ },
473
+ "&:hover": {
474
+ background: "var(--sidebar-accent)",
475
+ color: "var(--sidebar-accent-fg)",
476
+ },
477
+ "&[data-active]": {
478
+ background: "var(--primary)",
479
+ color: "var(--primary-foreground)",
480
+ fontWeight: "var(--weight-semibold)",
481
+ },
482
+ "&[data-active]:hover": {
483
+ background: "var(--primary-hover)",
484
+ color: "var(--primary-foreground)",
485
+ },
486
+ },
487
+ "@media": {
488
+ "(prefers-reduced-motion: reduce)": {
489
+ transition: "none",
490
+ },
491
+ },
492
+ });
493
+
494
+ export const sidebarMenuSubButtonSm = style({
495
+ fontSize: "var(--text-xs)",
496
+ });
497
+
498
+ export const sidebar__chevron = style({
499
+ width: "0.875rem !important",
500
+ height: "0.875rem !important",
501
+ marginLeft: "auto",
502
+ flexShrink: 0,
503
+ transition: "transform 150ms ease",
504
+ color: "var(--foreground-muted)",
505
+ "@media": {
506
+ "(prefers-reduced-motion: reduce)": {
507
+ transition: "none",
508
+ },
509
+ },
510
+ });
511
+
512
+ export const sidebarCollapsibleTrigger = style({
513
+ selectors: {
514
+ [`&[data-state="open"] ${sidebar__chevron}`]: {
515
+ transform: "rotate(90deg)",
516
+ },
517
+ },
518
+ });
519
+
520
+ export const sidebarCollapsibleContent = style({
521
+ selectors: {
522
+ "&[data-state="closed"]": {
523
+ display: "none",
524
+ },
525
+ },
526
+ });
527
+
528
+ export const sidebarCollapsibleFlyout = style({
529
+ selectors: {
530
+ [`& ${sidebarMenuSub}`]: {
531
+ display: "flex !important",
532
+ flexDirection: "column",
533
+ gap: "0.125rem",
534
+ margin: 0,
535
+ padding: 0,
536
+ borderLeft: 0,
537
+ },
538
+ [`& ${sidebarMenuSubButton}`]: {
539
+ paddingLeft: "0.625rem",
540
+ },
541
+ },
542
+ });
543
+
544
+ /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
545
+ export const byKey: Record<string, string> = {
546
+ "sidebar-wrapper": sidebarWrapper,
547
+ "sidebar": sidebar,
548
+ "sidebar__inner": sidebar__inner,
549
+ "sidebar--static": sidebarStatic,
550
+ "sidebar--mobile": sidebarMobile,
551
+ "sidebar__backdrop": sidebar__backdrop,
552
+ "sidebar__trigger": sidebar__trigger,
553
+ "sidebar__panel": sidebar__panel,
554
+ "sidebar__panel-header": sidebarPanelHeader,
555
+ "sidebar__panel-content": sidebarPanelContent,
556
+ "sidebar__panel-close": sidebarPanelClose,
557
+ "sidebar-inset": sidebarInset,
558
+ "sidebar__header": sidebar__header,
559
+ "sidebar__footer": sidebar__footer,
560
+ "sidebar__content": sidebar__content,
561
+ "sidebar__separator": sidebar__separator,
562
+ "sidebar__group": sidebar__group,
563
+ "sidebar__group-label": sidebarGroupLabel,
564
+ "sidebar__group-content": sidebarGroupContent,
565
+ "sidebar__menu": sidebar__menu,
566
+ "sidebar__menu-item": sidebarMenuItem,
567
+ "sidebar__menu-button": sidebarMenuButton,
568
+ "sidebar__menu-button--sm": sidebarMenuButtonSm,
569
+ "sidebar__menu-button--lg": sidebarMenuButtonLg,
570
+ "sidebar__menu-sub": sidebarMenuSub,
571
+ "sidebar__menu-sub-item": sidebarMenuSubItem,
572
+ "sidebar__menu-sub-button": sidebarMenuSubButton,
573
+ "sidebar__menu-sub-button--sm": sidebarMenuSubButtonSm,
574
+ "sidebar__chevron": sidebar__chevron,
575
+ "sidebar__collapsible-trigger": sidebarCollapsibleTrigger,
576
+ "sidebar__collapsible-content": sidebarCollapsibleContent,
577
+ "sidebar__collapsible-flyout": sidebarCollapsibleFlyout,
578
+ };
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ import { byKey, skeleton } from "./styles.css";
3
+
4
+
5
+ import { cn } from "@SH_UI_UTILS@";
6
+ /**
7
+ * 로딩 중 콘텐츠 자리를 채우는 placeholder 박스. 폭/높이는 인라인 스타일이나
8
+ * 클래스로 직접 지정한다. `aria-hidden`이 기본 적용되므로 스크린리더에 노출되지
9
+ * 않는다 — 로딩 상태 안내가 필요하면 부모에 `aria-busy`를 함께 둘 것.
10
+ */
11
+ export const Skeleton = React.forwardRef<
12
+ HTMLDivElement,
13
+ React.HTMLAttributes<HTMLDivElement>
14
+ >(({ className, ...props }, ref) => (
15
+ <div
16
+ ref={ref}
17
+ aria-hidden="true"
18
+ className={cn(skeleton, className)}
19
+ {...props}
20
+ />
21
+ ));
22
+ Skeleton.displayName = "Skeleton";
@@ -0,0 +1,30 @@
1
+ import { style, keyframes } from "@vanilla-extract/css";
2
+
3
+ export const shUiSkeletonPulse = keyframes({
4
+ "0%,
5
+ 100%": {
6
+ opacity: 1,
7
+ },
8
+ "50%": {
9
+ opacity: 0.55,
10
+ },
11
+ });
12
+
13
+ export const skeleton = style({
14
+ display: "block",
15
+ width: "100%",
16
+ height: "1rem",
17
+ background: "var(--background-muted)",
18
+ borderRadius: "calc(var(--radius) - 2px)",
19
+ animation: "sh-ui-skeleton-pulse 1.6s ease-in-out infinite",
20
+ "@media": {
21
+ "(prefers-reduced-motion: reduce)": {
22
+ animation: "none",
23
+ },
24
+ },
25
+ });
26
+
27
+ /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
28
+ export const byKey: Record<string, string> = {
29
+ "skeleton": skeleton,
30
+ };