@acrylblends/ui 0.0.0-stage → 0.3.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.
@@ -0,0 +1,1789 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "library": "@acryl/ui",
4
+ "surfaces": [
5
+ "web",
6
+ "desktop",
7
+ "tui"
8
+ ],
9
+ "components": {
10
+ "Stack": {
11
+ "summary": "Lays children out in a row or a column with a theme-consistent gap.",
12
+ "props": {
13
+ "direction": {
14
+ "type": "'column' | 'row'",
15
+ "default": "'column'"
16
+ },
17
+ "gap": {
18
+ "type": "'xs' | 'sm' | 'md' | 'lg'",
19
+ "default": "'md'"
20
+ },
21
+ "align": {
22
+ "type": "'start' | 'center' | 'end' | 'stretch'",
23
+ "default": "'stretch'"
24
+ }
25
+ },
26
+ "children": true,
27
+ "a11y": [
28
+ "no role: it is layout only"
29
+ ],
30
+ "surfaces": [
31
+ "web",
32
+ "tui"
33
+ ]
34
+ },
35
+ "Card": {
36
+ "summary": "A bordered surface with an optional title, body and footer actions.",
37
+ "props": {
38
+ "title": {
39
+ "type": "string"
40
+ },
41
+ "footer": {
42
+ "type": "ReactNode",
43
+ "description": "actions, right-aligned"
44
+ }
45
+ },
46
+ "children": true,
47
+ "a11y": [
48
+ "role=group, labelled by the title when there is one"
49
+ ],
50
+ "surfaces": [
51
+ "web",
52
+ "tui"
53
+ ]
54
+ },
55
+ "Field": {
56
+ "summary": "A labelled text input with hint and error text.",
57
+ "props": {
58
+ "label": {
59
+ "type": "string",
60
+ "required": true
61
+ },
62
+ "value": {
63
+ "type": "string",
64
+ "required": true
65
+ },
66
+ "onChange": {
67
+ "type": "(value: string) => void",
68
+ "required": true,
69
+ "description": "receives the string, not the event"
70
+ },
71
+ "hint": {
72
+ "type": "string"
73
+ },
74
+ "error": {
75
+ "type": "string",
76
+ "description": "shown in place of the hint and announced"
77
+ },
78
+ "placeholder": {
79
+ "type": "string"
80
+ }
81
+ },
82
+ "a11y": [
83
+ "the label is associated with the input",
84
+ "the error is announced (role=alert) and referenced by aria-describedby"
85
+ ],
86
+ "surfaces": [
87
+ "web",
88
+ "tui"
89
+ ]
90
+ },
91
+ "SwitchField": {
92
+ "summary": "A switch with a label and optional hint.",
93
+ "props": {
94
+ "label": {
95
+ "type": "string",
96
+ "required": true
97
+ },
98
+ "checked": {
99
+ "type": "boolean",
100
+ "required": true
101
+ },
102
+ "onChange": {
103
+ "type": "(checked: boolean) => void",
104
+ "required": true
105
+ },
106
+ "hint": {
107
+ "type": "string"
108
+ }
109
+ },
110
+ "a11y": [
111
+ "the label is the accessible name"
112
+ ],
113
+ "surfaces": [
114
+ "web",
115
+ "tui"
116
+ ]
117
+ },
118
+ "EmptyState": {
119
+ "summary": "Centered message for a list or view with nothing in it yet.",
120
+ "props": {
121
+ "title": {
122
+ "type": "string",
123
+ "required": true
124
+ },
125
+ "description": {
126
+ "type": "string"
127
+ },
128
+ "action": {
129
+ "type": "ReactNode"
130
+ }
131
+ },
132
+ "a11y": [
133
+ "the title is a heading"
134
+ ],
135
+ "surfaces": [
136
+ "web",
137
+ "tui"
138
+ ]
139
+ },
140
+ "SettingsRow": {
141
+ "summary": "A settings-style row: label and description on the left, one control on the right (the layout of the app's own Settings screens).",
142
+ "props": {
143
+ "label": {
144
+ "type": "string",
145
+ "required": true
146
+ },
147
+ "description": {
148
+ "type": "string"
149
+ },
150
+ "focused": {
151
+ "type": "boolean",
152
+ "description": "terminal only: marks the row that has the keyboard focus"
153
+ }
154
+ },
155
+ "children": true,
156
+ "a11y": [
157
+ "the control passed as children keeps its own accessible name"
158
+ ],
159
+ "surfaces": [
160
+ "web",
161
+ "tui"
162
+ ]
163
+ },
164
+ "SelectField": {
165
+ "summary": "A dropdown built on the app's own Menu: shows the selected option and opens the option list.",
166
+ "props": {
167
+ "options": {
168
+ "type": "Array<{ id: string, label: string, disabled?: boolean }>",
169
+ "required": true
170
+ },
171
+ "value": {
172
+ "type": "string",
173
+ "required": true
174
+ },
175
+ "onChange": {
176
+ "type": "(id: string) => void",
177
+ "required": true
178
+ },
179
+ "placeholder": {
180
+ "type": "string",
181
+ "default": "'Select'"
182
+ },
183
+ "label": {
184
+ "type": "string",
185
+ "description": "accessible name of the trigger"
186
+ }
187
+ },
188
+ "a11y": [
189
+ "trigger has aria-haspopup and aria-expanded",
190
+ "Escape and outside click close it (Menu)"
191
+ ],
192
+ "surfaces": [
193
+ "web",
194
+ "tui"
195
+ ]
196
+ },
197
+ "Segmented": {
198
+ "summary": "Tile group for a small set of exclusive choices: DSH's Appearance picker (Light, Dark, System), a full-width row.",
199
+ "props": {
200
+ "options": {
201
+ "type": "Array<{ id: string, label: string, icon?: ReactNode }>",
202
+ "required": true
203
+ },
204
+ "value": {
205
+ "type": "string",
206
+ "required": true
207
+ },
208
+ "onChange": {
209
+ "type": "(id: string) => void",
210
+ "required": true
211
+ },
212
+ "label": {
213
+ "type": "string",
214
+ "description": "accessible name of the group"
215
+ },
216
+ "title": {
217
+ "type": "string",
218
+ "description": "visible title above the tiles (DSH shows one). The row is full width: do not put it inside a SettingsRow's right-hand control."
219
+ }
220
+ },
221
+ "a11y": [
222
+ "role=radiogroup with role=radio tiles and aria-checked",
223
+ "roving tabindex; arrow keys move the choice"
224
+ ],
225
+ "surfaces": [
226
+ "web",
227
+ "tui"
228
+ ]
229
+ },
230
+ "Tabs": {
231
+ "summary": "Tab strip with the active panel as children.",
232
+ "props": {
233
+ "tabs": {
234
+ "type": "Array<{ id: string, label: string }>",
235
+ "required": true
236
+ },
237
+ "value": {
238
+ "type": "string",
239
+ "required": true
240
+ },
241
+ "onChange": {
242
+ "type": "(id: string) => void",
243
+ "required": true
244
+ },
245
+ "label": {
246
+ "type": "string"
247
+ }
248
+ },
249
+ "children": true,
250
+ "a11y": [
251
+ "role=tablist, tab and tabpanel wired with aria-controls and aria-labelledby",
252
+ "roving tabindex; left and right arrows move the tab"
253
+ ],
254
+ "surfaces": [
255
+ "web",
256
+ "tui"
257
+ ]
258
+ },
259
+ "Dialog": {
260
+ "summary": "A confirm dialog over the app's Modal, with cancel and confirm actions.",
261
+ "props": {
262
+ "open": {
263
+ "type": "boolean",
264
+ "required": true
265
+ },
266
+ "title": {
267
+ "type": "string",
268
+ "required": true
269
+ },
270
+ "onClose": {
271
+ "type": "() => void",
272
+ "required": true
273
+ },
274
+ "onConfirm": {
275
+ "type": "() => void",
276
+ "required": true
277
+ },
278
+ "confirmLabel": {
279
+ "type": "string",
280
+ "default": "'OK'"
281
+ },
282
+ "cancelLabel": {
283
+ "type": "string",
284
+ "default": "'Cancel'"
285
+ },
286
+ "danger": {
287
+ "type": "boolean",
288
+ "default": "false",
289
+ "description": "terminal only (paints the confirm action with the error role). On the web use the app's RiskConfirmation primitive for destructive confirmations: its Button has no danger variant."
290
+ }
291
+ },
292
+ "children": true,
293
+ "a11y": [
294
+ "focus handling and Escape come from the app's Modal"
295
+ ],
296
+ "surfaces": [
297
+ "web",
298
+ "tui"
299
+ ]
300
+ },
301
+ "SidebarRow": {
302
+ "summary": "The sidebar's New Session bar: icon and label when the sidebar is wide, a plain icon control with a tooltip on the rail (extracted from DSH's sidebar).",
303
+ "props": {
304
+ "icon": {
305
+ "type": "ReactNode",
306
+ "required": true
307
+ },
308
+ "label": {
309
+ "type": "string",
310
+ "required": true,
311
+ "description": "visible text when wide, tooltip and accessible name on the rail"
312
+ },
313
+ "wide": {
314
+ "type": "boolean",
315
+ "required": true
316
+ },
317
+ "onClick": {
318
+ "type": "() => void",
319
+ "required": true
320
+ }
321
+ },
322
+ "surfaces": [
323
+ "web"
324
+ ],
325
+ "a11y": [
326
+ "aria-label carries the label in both forms"
327
+ ]
328
+ },
329
+ "ToolCallCard": {
330
+ "summary": "A collapsible tool-call row as in the conversation: leading icon or state dot, title, summary, expandable IN/OUT card (extracted from DSH's ToolRow).",
331
+ "props": {
332
+ "icon": {
333
+ "type": "ReactNode",
334
+ "required": true
335
+ },
336
+ "title": {
337
+ "type": "string",
338
+ "required": true
339
+ },
340
+ "summary": {
341
+ "type": "string",
342
+ "required": true
343
+ },
344
+ "state": {
345
+ "type": "'running' | 'ok' | 'error' | 'stopped'",
346
+ "required": true
347
+ },
348
+ "errorSummary": {
349
+ "type": "string",
350
+ "description": "replaces the summary on an error row"
351
+ },
352
+ "input": {
353
+ "type": "string"
354
+ },
355
+ "output": {
356
+ "type": "string"
357
+ },
358
+ "labels": {
359
+ "type": "{ input, output, running, failed, stopped }",
360
+ "required": true,
361
+ "description": "copy; the run-state labels are visually hidden text"
362
+ }
363
+ },
364
+ "children": true,
365
+ "surfaces": [
366
+ "web"
367
+ ],
368
+ "a11y": [
369
+ "expandable rows are disclosure controls (Enter and Space toggle)",
370
+ "the run state is exposed as visually hidden text, not colour only"
371
+ ]
372
+ },
373
+ "StateDot": {
374
+ "summary": "A small coloured status dot (done, warning, ongoing, error, idle).",
375
+ "props": {
376
+ "state": {
377
+ "type": "'done' | 'warning' | 'ongoing' | 'error' | 'idle'",
378
+ "required": true
379
+ },
380
+ "size": {
381
+ "type": "number"
382
+ }
383
+ },
384
+ "surfaces": [
385
+ "web"
386
+ ],
387
+ "reexport": true
388
+ },
389
+ "DisclosureRow": {
390
+ "summary": "A collapsible row: leading icon, title, optional collapsed summary, expand on click or chevron.",
391
+ "props": {
392
+ "icon": {
393
+ "type": "ReactNode"
394
+ },
395
+ "title": {
396
+ "type": "string",
397
+ "required": true
398
+ },
399
+ "open": {
400
+ "type": "boolean",
401
+ "required": true
402
+ },
403
+ "expandable": {
404
+ "type": "boolean",
405
+ "required": true
406
+ },
407
+ "onToggle": {
408
+ "type": "() => void",
409
+ "required": true
410
+ }
411
+ },
412
+ "surfaces": [
413
+ "web"
414
+ ],
415
+ "reexport": true
416
+ },
417
+ "Menu": {
418
+ "summary": "A positioned menu of items, separators and labels (built by SelectField).",
419
+ "props": {
420
+ "entries": {
421
+ "type": "MenuEntry[]",
422
+ "required": true
423
+ }
424
+ },
425
+ "surfaces": [
426
+ "web"
427
+ ],
428
+ "reexport": true
429
+ },
430
+ "Switch": {
431
+ "summary": "A toggle switch with an accessible name only; pair it with a visible label (see SwitchField).",
432
+ "props": {
433
+ "checked": {
434
+ "type": "boolean",
435
+ "required": true
436
+ },
437
+ "onChange": {
438
+ "type": "(checked: boolean) => void",
439
+ "required": true
440
+ },
441
+ "label": {
442
+ "type": "string",
443
+ "required": true
444
+ }
445
+ },
446
+ "surfaces": [
447
+ "web"
448
+ ],
449
+ "reexport": true
450
+ },
451
+ "Input": {
452
+ "summary": "A plain text input (used by Field for its label, hint and error wiring).",
453
+ "props": {
454
+ "value": {
455
+ "type": "string",
456
+ "required": true
457
+ },
458
+ "onChange": {
459
+ "type": "(value: string) => void",
460
+ "required": true
461
+ }
462
+ },
463
+ "surfaces": [
464
+ "web"
465
+ ],
466
+ "reexport": true
467
+ },
468
+ "HoverCard": {
469
+ "summary": "Content shown on hover/focus near a trigger.",
470
+ "props": {
471
+ "trigger": {
472
+ "type": "ReactNode",
473
+ "required": true
474
+ }
475
+ },
476
+ "surfaces": [
477
+ "web"
478
+ ],
479
+ "reexport": true
480
+ },
481
+ "RiskConfirmation": {
482
+ "summary": "The app's own destructive-confirmation control (has a danger state Dialog does not; terminal parity note in Dialog).",
483
+ "props": {
484
+ "title": {
485
+ "type": "string",
486
+ "required": true
487
+ },
488
+ "onConfirm": {
489
+ "type": "() => void",
490
+ "required": true
491
+ }
492
+ },
493
+ "surfaces": [
494
+ "web"
495
+ ],
496
+ "reexport": true
497
+ },
498
+ "ConnectionIndicator": {
499
+ "summary": "A connection-state dot (connecting, connected, error, and so on).",
500
+ "props": {
501
+ "state": {
502
+ "type": "ConnectionIndicatorState",
503
+ "required": true
504
+ }
505
+ },
506
+ "surfaces": [
507
+ "web"
508
+ ],
509
+ "reexport": true
510
+ },
511
+ "JsonTree": {
512
+ "summary": "A collapsible tree view of a JSON value.",
513
+ "props": {
514
+ "value": {
515
+ "type": "unknown",
516
+ "required": true
517
+ },
518
+ "labels": {
519
+ "type": "JsonTreeLabels"
520
+ }
521
+ },
522
+ "surfaces": [
523
+ "web"
524
+ ],
525
+ "reexport": true
526
+ },
527
+ "TerminalBlock": {
528
+ "summary": "A scrollback view for terminal tool output, capped and expandable.",
529
+ "props": {
530
+ "lines": {
531
+ "type": "string[]",
532
+ "required": true
533
+ },
534
+ "labels": {
535
+ "type": "TerminalBlockLabels"
536
+ }
537
+ },
538
+ "surfaces": [
539
+ "web"
540
+ ],
541
+ "reexport": true
542
+ },
543
+ "ReadBlock": {
544
+ "summary": "A file-read tool card body: numbered lines with a max before truncation.",
545
+ "props": {
546
+ "lines": {
547
+ "type": "ReadBlockLine[]",
548
+ "required": true
549
+ },
550
+ "labels": {
551
+ "type": "ReadBlockLabels"
552
+ }
553
+ },
554
+ "surfaces": [
555
+ "web"
556
+ ],
557
+ "reexport": true
558
+ },
559
+ "DiffBlock": {
560
+ "summary": "A unified diff view, capped and expandable, with add/remove totals.",
561
+ "props": {
562
+ "hunks": {
563
+ "type": "DiffHunk[]",
564
+ "required": true
565
+ },
566
+ "labels": {
567
+ "type": "DiffBlockLabels"
568
+ }
569
+ },
570
+ "surfaces": [
571
+ "web"
572
+ ],
573
+ "reexport": true
574
+ },
575
+ "SearchBlock": {
576
+ "summary": "A search-tool result list, capped and expandable.",
577
+ "props": {
578
+ "labels": {
579
+ "type": "object"
580
+ }
581
+ },
582
+ "surfaces": [
583
+ "web"
584
+ ],
585
+ "reexport": true
586
+ },
587
+ "WebBlock": {
588
+ "summary": "A web-fetch tool result card.",
589
+ "props": {},
590
+ "surfaces": [
591
+ "web"
592
+ ],
593
+ "reexport": true
594
+ },
595
+ "CodeBlock": {
596
+ "summary": "A syntax-highlighted code block used inside markdown.",
597
+ "props": {},
598
+ "surfaces": [
599
+ "web"
600
+ ],
601
+ "reexport": true
602
+ },
603
+ "JsonBlock": {
604
+ "summary": "A formatted JSON block used inside markdown.",
605
+ "props": {},
606
+ "surfaces": [
607
+ "web"
608
+ ],
609
+ "reexport": true
610
+ },
611
+ "MarkdownText": {
612
+ "summary": "Renders assistant/user markdown with the app's own extensions (file mentions, path images, code).",
613
+ "props": {
614
+ "labels": {
615
+ "type": "MarkdownLabels"
616
+ }
617
+ },
618
+ "surfaces": [
619
+ "web"
620
+ ],
621
+ "reexport": true
622
+ },
623
+ "Kbd": {
624
+ "summary": "One keyboard key or shortcut segment (ported from shadcn/ui's Kbd). Group several with this library's Stack.",
625
+ "props": {
626
+ "children": {
627
+ "type": "ReactNode"
628
+ },
629
+ "className": {
630
+ "type": "string"
631
+ }
632
+ },
633
+ "surfaces": [
634
+ "web"
635
+ ]
636
+ },
637
+ "ReferenceIconMedium": {
638
+ "summary": "The glyph for one inline reference domain (file, web, terminal, and so on), medium weight.",
639
+ "props": {
640
+ "kind": {
641
+ "type": "ReferenceIconKind",
642
+ "required": true
643
+ },
644
+ "size": {
645
+ "type": "number"
646
+ }
647
+ },
648
+ "surfaces": [
649
+ "web"
650
+ ],
651
+ "reexport": true
652
+ },
653
+ "ReferenceIconRegular": {
654
+ "summary": "The glyph for one inline reference domain (file, web, terminal, and so on), regular weight.",
655
+ "props": {
656
+ "kind": {
657
+ "type": "ReferenceIconKind",
658
+ "required": true
659
+ },
660
+ "size": {
661
+ "type": "number"
662
+ }
663
+ },
664
+ "surfaces": [
665
+ "web"
666
+ ],
667
+ "reexport": true
668
+ },
669
+ "LinkIconMedium": {
670
+ "summary": "The glyph for a file-type or web link, chosen from a path extension, medium weight.",
671
+ "props": {
672
+ "kind": {
673
+ "type": "LinkIconKind",
674
+ "required": true
675
+ }
676
+ },
677
+ "surfaces": [
678
+ "web"
679
+ ],
680
+ "reexport": true
681
+ },
682
+ "LinkIconRegular": {
683
+ "summary": "The glyph for a file-type or web link, chosen from a path extension, regular weight.",
684
+ "props": {
685
+ "kind": {
686
+ "type": "LinkIconKind",
687
+ "required": true
688
+ }
689
+ },
690
+ "surfaces": [
691
+ "web"
692
+ ],
693
+ "reexport": true
694
+ },
695
+ "FileTypeIcon": {
696
+ "summary": "The glyph for a file, chosen from its classified file type.",
697
+ "props": {
698
+ "kind": {
699
+ "type": "FileTypeKind",
700
+ "required": true
701
+ },
702
+ "className": {
703
+ "type": "string"
704
+ }
705
+ },
706
+ "surfaces": [
707
+ "web"
708
+ ],
709
+ "reexport": true
710
+ },
711
+ "Badge": {
712
+ "summary": "A small status/count pill (ported from shadcn/ui's Badge).",
713
+ "props": {
714
+ "children": {
715
+ "type": "ReactNode"
716
+ },
717
+ "variant": {
718
+ "type": "'default' | 'primary' | 'success' | 'warning' | 'error'"
719
+ },
720
+ "className": {
721
+ "type": "string"
722
+ }
723
+ },
724
+ "surfaces": [
725
+ "web"
726
+ ]
727
+ },
728
+ "Skeleton": {
729
+ "summary": "A pulsing placeholder shape for loading content (ported from shadcn/ui's Skeleton).",
730
+ "props": {
731
+ "className": {
732
+ "type": "string"
733
+ },
734
+ "style": {
735
+ "type": "{ width?, height? }"
736
+ }
737
+ },
738
+ "surfaces": [
739
+ "web"
740
+ ]
741
+ },
742
+ "Spinner": {
743
+ "summary": "A rotating loading indicator (ported from shadcn/ui's Spinner; no lucide-react dependency).",
744
+ "props": {
745
+ "className": {
746
+ "type": "string"
747
+ }
748
+ },
749
+ "surfaces": [
750
+ "web"
751
+ ]
752
+ },
753
+ "Alert": {
754
+ "summary": "A titled message box with an optional icon (ported from shadcn/ui's Alert).",
755
+ "props": {
756
+ "icon": {
757
+ "type": "ReactNode"
758
+ },
759
+ "title": {
760
+ "type": "ReactNode"
761
+ },
762
+ "children": {
763
+ "type": "ReactNode"
764
+ },
765
+ "variant": {
766
+ "type": "'default' | 'error'"
767
+ },
768
+ "className": {
769
+ "type": "string"
770
+ }
771
+ },
772
+ "surfaces": [
773
+ "web"
774
+ ],
775
+ "a11y": [
776
+ "role=alert"
777
+ ]
778
+ },
779
+ "Separator": {
780
+ "summary": "A thin dividing line, horizontal or vertical (ported from shadcn/ui's Separator; no Radix dependency).",
781
+ "props": {
782
+ "orientation": {
783
+ "type": "'horizontal' | 'vertical'"
784
+ },
785
+ "decorative": {
786
+ "type": "boolean"
787
+ },
788
+ "className": {
789
+ "type": "string"
790
+ }
791
+ },
792
+ "surfaces": [
793
+ "web"
794
+ ]
795
+ },
796
+ "Progress": {
797
+ "summary": "A determinate progress bar, 0 to 100 (ported from shadcn/ui's Progress; no Radix dependency).",
798
+ "props": {
799
+ "value": {
800
+ "type": "number",
801
+ "required": true
802
+ },
803
+ "className": {
804
+ "type": "string"
805
+ }
806
+ },
807
+ "surfaces": [
808
+ "web"
809
+ ],
810
+ "a11y": [
811
+ "role=progressbar with aria-valuenow/min/max"
812
+ ]
813
+ },
814
+ "Avatar": {
815
+ "summary": "An image avatar with a fallback shown when there is no image or it fails to load (ported from shadcn/ui's Avatar; no Radix dependency).",
816
+ "props": {
817
+ "src": {
818
+ "type": "string"
819
+ },
820
+ "alt": {
821
+ "type": "string"
822
+ },
823
+ "fallback": {
824
+ "type": "ReactNode",
825
+ "required": true
826
+ },
827
+ "size": {
828
+ "type": "'sm' | 'default' | 'lg'"
829
+ },
830
+ "className": {
831
+ "type": "string"
832
+ }
833
+ },
834
+ "surfaces": [
835
+ "web"
836
+ ]
837
+ },
838
+ "ValueField": {
839
+ "summary": "A settings-style field bound to a text value, with an override badge and reset action.",
840
+ "props": {
841
+ "id": {
842
+ "type": "string",
843
+ "required": true
844
+ },
845
+ "label": {
846
+ "type": "string",
847
+ "required": true
848
+ },
849
+ "hint": {
850
+ "type": "string",
851
+ "required": true
852
+ },
853
+ "numeric": {
854
+ "type": "boolean"
855
+ },
856
+ "placeholder": {
857
+ "type": "string"
858
+ }
859
+ },
860
+ "surfaces": [
861
+ "web"
862
+ ]
863
+ },
864
+ "SecretField": {
865
+ "summary": "A settings-style field for a credential reference: shows whether it is configured, edits without ever displaying the secret.",
866
+ "props": {
867
+ "id": {
868
+ "type": "string",
869
+ "required": true
870
+ },
871
+ "label": {
872
+ "type": "string",
873
+ "required": true
874
+ },
875
+ "hint": {
876
+ "type": "string",
877
+ "required": true
878
+ },
879
+ "configured": {
880
+ "type": "boolean",
881
+ "required": true
882
+ },
883
+ "stateLabel": {
884
+ "type": "string",
885
+ "required": true
886
+ }
887
+ },
888
+ "surfaces": [
889
+ "web"
890
+ ]
891
+ },
892
+ "SelectPill": {
893
+ "summary": "A pill-shaped dropdown selector built on the app's own Menu.",
894
+ "props": {
895
+ "options": {
896
+ "type": "SelectOption[]",
897
+ "required": true
898
+ },
899
+ "value": {
900
+ "type": "string",
901
+ "required": true
902
+ },
903
+ "onChange": {
904
+ "type": "(value: string) => void",
905
+ "required": true
906
+ },
907
+ "label": {
908
+ "type": "string"
909
+ },
910
+ "placeholder": {
911
+ "type": "string"
912
+ },
913
+ "disabled": {
914
+ "type": "boolean"
915
+ }
916
+ },
917
+ "surfaces": [
918
+ "web"
919
+ ]
920
+ },
921
+ "AppearanceCubes": {
922
+ "summary": "A row of icon-and-label tiles for a small exclusive choice (Light/Dark/System), pressed state on the selected one.",
923
+ "props": {
924
+ "title": {
925
+ "type": "string"
926
+ },
927
+ "options": {
928
+ "type": "CubeOption[]",
929
+ "required": true
930
+ },
931
+ "value": {
932
+ "type": "string",
933
+ "required": true
934
+ },
935
+ "onChange": {
936
+ "type": "(value: string) => void",
937
+ "required": true
938
+ }
939
+ },
940
+ "surfaces": [
941
+ "web"
942
+ ]
943
+ },
944
+ "Label": {
945
+ "summary": "A form label (ported from shadcn/ui's Label; no Radix dependency).",
946
+ "props": {
947
+ "htmlFor": {
948
+ "type": "string"
949
+ },
950
+ "children": {
951
+ "type": "ReactNode"
952
+ },
953
+ "className": {
954
+ "type": "string"
955
+ }
956
+ },
957
+ "surfaces": [
958
+ "web"
959
+ ]
960
+ },
961
+ "Textarea": {
962
+ "summary": "A multi-line text input (ported from shadcn/ui's Textarea).",
963
+ "props": {
964
+ "value": {
965
+ "type": "string",
966
+ "required": true
967
+ },
968
+ "onChange": {
969
+ "type": "(value: string) => void",
970
+ "required": true
971
+ },
972
+ "placeholder": {
973
+ "type": "string"
974
+ },
975
+ "disabled": {
976
+ "type": "boolean"
977
+ },
978
+ "rows": {
979
+ "type": "number"
980
+ }
981
+ },
982
+ "surfaces": [
983
+ "web"
984
+ ]
985
+ },
986
+ "Checkbox": {
987
+ "summary": "A checkbox with its accessible label (ported from shadcn/ui's Checkbox; a native input, no Radix dependency).",
988
+ "props": {
989
+ "checked": {
990
+ "type": "boolean",
991
+ "required": true
992
+ },
993
+ "onChange": {
994
+ "type": "(checked: boolean) => void",
995
+ "required": true
996
+ },
997
+ "label": {
998
+ "type": "string",
999
+ "required": true
1000
+ },
1001
+ "disabled": {
1002
+ "type": "boolean"
1003
+ }
1004
+ },
1005
+ "surfaces": [
1006
+ "web"
1007
+ ]
1008
+ },
1009
+ "AspectRatio": {
1010
+ "summary": "A box held to a fixed width:height ratio (ported from shadcn/ui's AspectRatio; pure CSS, no Radix dependency).",
1011
+ "props": {
1012
+ "ratio": {
1013
+ "type": "number",
1014
+ "required": true
1015
+ },
1016
+ "children": {
1017
+ "type": "ReactNode"
1018
+ }
1019
+ },
1020
+ "surfaces": [
1021
+ "web"
1022
+ ]
1023
+ },
1024
+ "Breadcrumb": {
1025
+ "summary": "A breadcrumb trail: list, item, link, current page, separator and an ellipsis for a collapsed middle (ported from shadcn/ui's Breadcrumb).",
1026
+ "props": {
1027
+ "children": {
1028
+ "type": "ReactNode"
1029
+ }
1030
+ },
1031
+ "surfaces": [
1032
+ "web"
1033
+ ],
1034
+ "a11y": [
1035
+ "nav aria-label=breadcrumb; the current page is aria-current=page"
1036
+ ]
1037
+ },
1038
+ "Toggle": {
1039
+ "summary": "A two-state pressed button (ported from shadcn/ui's Toggle; a native aria-pressed button, no Radix dependency).",
1040
+ "props": {
1041
+ "pressed": {
1042
+ "type": "boolean",
1043
+ "required": true
1044
+ },
1045
+ "onPressedChange": {
1046
+ "type": "(pressed: boolean) => void",
1047
+ "required": true
1048
+ },
1049
+ "children": {
1050
+ "type": "ReactNode"
1051
+ },
1052
+ "variant": {
1053
+ "type": "'default' | 'outline'"
1054
+ },
1055
+ "size": {
1056
+ "type": "'sm' | 'default' | 'lg'"
1057
+ }
1058
+ },
1059
+ "surfaces": [
1060
+ "web"
1061
+ ]
1062
+ },
1063
+ "ButtonGroup": {
1064
+ "summary": "A row (or column) of controls with merged corners (ported from shadcn/ui's ButtonGroup).",
1065
+ "props": {
1066
+ "children": {
1067
+ "type": "ReactNode"
1068
+ },
1069
+ "orientation": {
1070
+ "type": "'horizontal' | 'vertical'"
1071
+ }
1072
+ },
1073
+ "surfaces": [
1074
+ "web"
1075
+ ]
1076
+ },
1077
+ "Accordion": {
1078
+ "summary": "One or more collapsible items sharing an open/close model, single or multiple open (ported from shadcn/ui's Accordion; plain state, no Radix dependency).",
1079
+ "props": {
1080
+ "type": {
1081
+ "type": "'single' | 'multiple'",
1082
+ "required": true
1083
+ },
1084
+ "children": {
1085
+ "type": "ReactNode"
1086
+ }
1087
+ },
1088
+ "surfaces": [
1089
+ "web"
1090
+ ]
1091
+ },
1092
+ "RadioGroup": {
1093
+ "summary": "A classic radio-dot list for a set of mutually exclusive plain-text options (ported from shadcn/ui's RadioGroup; a native input[type=radio] group, no Radix dependency). Distinct from AppearanceCubes/Segmented (icon-and-label tiles).",
1094
+ "props": {
1095
+ "name": {
1096
+ "type": "string",
1097
+ "required": true
1098
+ },
1099
+ "options": {
1100
+ "type": "RadioOption[]",
1101
+ "required": true
1102
+ },
1103
+ "value": {
1104
+ "type": "string",
1105
+ "required": true
1106
+ },
1107
+ "onChange": {
1108
+ "type": "(value: string) => void",
1109
+ "required": true
1110
+ }
1111
+ },
1112
+ "surfaces": [
1113
+ "web"
1114
+ ]
1115
+ },
1116
+ "Collapsible": {
1117
+ "summary": "The bare collapsible primitive (trigger + content, no chrome) - ported from shadcn/ui's Collapsible. Distinct from DisclosureRow, which is a fully-chromed row (icon, title, chevron).",
1118
+ "props": {
1119
+ "defaultOpen": {
1120
+ "type": "boolean"
1121
+ },
1122
+ "children": {
1123
+ "type": "ReactNode"
1124
+ }
1125
+ },
1126
+ "surfaces": [
1127
+ "web"
1128
+ ]
1129
+ },
1130
+ "ToggleGroup": {
1131
+ "summary": "A row of toggle buttons sharing one single- or multiple-selection model (ported from shadcn/ui's ToggleGroup; plain state, no Radix dependency).",
1132
+ "props": {
1133
+ "type": {
1134
+ "type": "'single' | 'multiple'",
1135
+ "required": true
1136
+ },
1137
+ "value": {
1138
+ "type": "string | string[]",
1139
+ "required": true
1140
+ },
1141
+ "onChange": {
1142
+ "type": "(value: string | string[]) => void",
1143
+ "required": true
1144
+ },
1145
+ "children": {
1146
+ "type": "ReactNode"
1147
+ }
1148
+ },
1149
+ "surfaces": [
1150
+ "web"
1151
+ ]
1152
+ },
1153
+ "Table": {
1154
+ "summary": "A data table: header, body, footer, row, head, cell and caption, each in its own horizontal scroll container (ported from shadcn/ui's Table; no Radix primitive involved).",
1155
+ "props": {
1156
+ "children": {
1157
+ "type": "ReactNode"
1158
+ },
1159
+ "className": {
1160
+ "type": "string"
1161
+ }
1162
+ },
1163
+ "surfaces": [
1164
+ "web"
1165
+ ],
1166
+ "a11y": [
1167
+ "native table semantics; the scroll container keeps a wide table from widening the page instead of clipping it"
1168
+ ]
1169
+ },
1170
+ "DirectionProvider": {
1171
+ "summary": "A text-direction provider for descendants, with the source's dir prop and direction alias, and a useDirection hook (ported from shadcn/ui's Direction; a plain context instead of Radix).",
1172
+ "props": {
1173
+ "dir": {
1174
+ "type": "'ltr' | 'rtl'"
1175
+ },
1176
+ "direction": {
1177
+ "type": "'ltr' | 'rtl'"
1178
+ },
1179
+ "children": {
1180
+ "type": "ReactNode"
1181
+ }
1182
+ },
1183
+ "surfaces": [
1184
+ "web"
1185
+ ],
1186
+ "a11y": [
1187
+ "consumers set dir on the subtree, which is what decides the browser's own bidi behavior"
1188
+ ]
1189
+ },
1190
+ "Marker": {
1191
+ "summary": "A muted label line between message groups: plain, ruled on both sides, or underlined at the bottom (ported from shadcn/ui's Marker).",
1192
+ "props": {
1193
+ "variant": {
1194
+ "type": "'default' | 'separator' | 'border'"
1195
+ },
1196
+ "children": {
1197
+ "type": "ReactNode"
1198
+ }
1199
+ },
1200
+ "surfaces": [
1201
+ "web"
1202
+ ],
1203
+ "a11y": [
1204
+ "the icon part is aria-hidden, so a decorative glyph is never announced"
1205
+ ]
1206
+ },
1207
+ "Message": {
1208
+ "summary": "A message row around a Bubble: group, avatar, content, header and footer, with an end alignment for the reader's own turns (ported from shadcn/ui's Message).",
1209
+ "props": {
1210
+ "align": {
1211
+ "type": "'start' | 'end'"
1212
+ },
1213
+ "children": {
1214
+ "type": "ReactNode"
1215
+ }
1216
+ },
1217
+ "surfaces": [
1218
+ "web"
1219
+ ],
1220
+ "a11y": []
1221
+ },
1222
+ "Bubble": {
1223
+ "summary": "A chat bubble with seven variants and a reaction pill, meant to sit inside this library's Message (ported from shadcn/ui's Bubble; no Radix, no cva).",
1224
+ "props": {
1225
+ "variant": {
1226
+ "type": "'default' | 'secondary' | 'muted' | 'tinted' | 'outline' | 'ghost' | 'destructive'"
1227
+ },
1228
+ "align": {
1229
+ "type": "'start' | 'end'"
1230
+ },
1231
+ "children": {
1232
+ "type": "ReactNode"
1233
+ }
1234
+ },
1235
+ "surfaces": [
1236
+ "web"
1237
+ ],
1238
+ "a11y": [
1239
+ "interactive content inside a bubble keeps its own focus ring (border plus a 3px shadow) rather than having its outline removed"
1240
+ ]
1241
+ },
1242
+ "Pagination": {
1243
+ "summary": "A pagination landmark: content, item, link, previous, next and an ellipsis, with the current page marked for assistive tech (ported from shadcn/ui's Pagination; the Button item's look is restated locally to stay self-contained).",
1244
+ "props": {
1245
+ "children": {
1246
+ "type": "ReactNode"
1247
+ }
1248
+ },
1249
+ "surfaces": [
1250
+ "web"
1251
+ ],
1252
+ "a11y": [
1253
+ "nav aria-label=pagination; the current page is aria-current=page; the ellipsis has a screen-reader-only label"
1254
+ ]
1255
+ },
1256
+ "NativeSelect": {
1257
+ "summary": "The platform's own <select>, styled to match the library's inputs, for a short static option list (ported from shadcn/ui's Native Select; not the same control as this library's SelectField, which opens a menu).",
1258
+ "props": {
1259
+ "size": {
1260
+ "type": "'sm' | 'default'"
1261
+ },
1262
+ "children": {
1263
+ "type": "ReactNode"
1264
+ }
1265
+ },
1266
+ "surfaces": [
1267
+ "web"
1268
+ ],
1269
+ "a11y": [
1270
+ "native select semantics, keyboard behavior and typeahead are kept; an invalid control is styleable through aria-invalid"
1271
+ ]
1272
+ },
1273
+ "ScrollArea": {
1274
+ "summary": "A scroll container that stays in its own box: the platform's styled scrollbars, and reaching an end does not scroll the page behind it (ported from shadcn/ui's Scroll Area; Radix's JavaScript scroller is dropped for the platform's own).",
1275
+ "props": {
1276
+ "children": {
1277
+ "type": "ReactNode"
1278
+ },
1279
+ "className": {
1280
+ "type": "string"
1281
+ },
1282
+ "style": {
1283
+ "type": "CSSProperties"
1284
+ }
1285
+ },
1286
+ "surfaces": [
1287
+ "web"
1288
+ ],
1289
+ "a11y": [
1290
+ "the viewport is focusable, so a keyboard user can scroll it without a pointer, and its focus ring is visible"
1291
+ ]
1292
+ },
1293
+ "InputOTP": {
1294
+ "summary": "A one-time-code input: one real input over a row of slots, so typing, paste and arrow keys are the platform's behaviour (ported from shadcn/ui's Input OTP; the input-otp package is dropped for it).",
1295
+ "props": {
1296
+ "value": {
1297
+ "type": "string"
1298
+ },
1299
+ "onChange": {
1300
+ "type": "(value: string) => void"
1301
+ },
1302
+ "maxLength": {
1303
+ "type": "number"
1304
+ },
1305
+ "disabled": {
1306
+ "type": "boolean"
1307
+ },
1308
+ "label": {
1309
+ "type": "string"
1310
+ },
1311
+ "containerClassName": {
1312
+ "type": "string"
1313
+ }
1314
+ },
1315
+ "surfaces": [
1316
+ "web"
1317
+ ],
1318
+ "a11y": [
1319
+ "the real input carries inputMode=numeric, autoComplete=one-time-code and the caller's label; the active slot shows a blinking caret in place of the one the platform would draw on an invisible field"
1320
+ ]
1321
+ },
1322
+ "Item": {
1323
+ "summary": "One row of a list: group, media, content, title, description, actions, header and footer (ported from shadcn/ui's Item; no Radix, no cva, and no cross-item Separator import).",
1324
+ "props": {
1325
+ "variant": {
1326
+ "type": "'default' | 'outline' | 'muted'"
1327
+ },
1328
+ "size": {
1329
+ "type": "'default' | 'sm'"
1330
+ },
1331
+ "children": {
1332
+ "type": "ReactNode"
1333
+ }
1334
+ },
1335
+ "surfaces": [
1336
+ "web"
1337
+ ],
1338
+ "a11y": [
1339
+ "the group is a list (role=list); the separator is decorative (role=none)"
1340
+ ]
1341
+ },
1342
+ "Attachment": {
1343
+ "summary": "A file chip for a composer: media, title, description, actions and a whole-chip trigger, with idle, uploading, processing, error and done states (ported from shadcn/ui's Attachment).",
1344
+ "props": {
1345
+ "state": {
1346
+ "type": "'idle' | 'uploading' | 'processing' | 'error' | 'done'"
1347
+ },
1348
+ "size": {
1349
+ "type": "'default' | 'sm' | 'xs'"
1350
+ },
1351
+ "orientation": {
1352
+ "type": "'horizontal' | 'vertical'"
1353
+ },
1354
+ "children": {
1355
+ "type": "ReactNode"
1356
+ }
1357
+ },
1358
+ "surfaces": [
1359
+ "web"
1360
+ ],
1361
+ "a11y": [
1362
+ "the trigger and each action are real buttons with accessible names, the trigger covering the whole chip; the uploading and processing states are conveyed by the title shimmer and the state attribute, not by colour alone"
1363
+ ]
1364
+ },
1365
+ "InputGroup": {
1366
+ "summary": "One bordered field grouping an input or textarea with addons before, after, above or below it; the wrapper carries the focus ring and the error tint (ported from shadcn/ui's Input Group).",
1367
+ "props": {
1368
+ "disabled": {
1369
+ "type": "boolean"
1370
+ },
1371
+ "children": {
1372
+ "type": "ReactNode"
1373
+ }
1374
+ },
1375
+ "surfaces": [
1376
+ "web"
1377
+ ],
1378
+ "a11y": [
1379
+ "role=group, with each addon its own group; clicking an addon focuses the control, so a prefix behaves like part of the field; an aria-invalid control tints the whole group rather than only itself"
1380
+ ]
1381
+ },
1382
+ "FormField": {
1383
+ "summary": "The layout around one field's parts - set, group, legend, label, title, content, description, separator and error - in vertical, horizontal or container-responsive orientation (ported from shadcn/ui's Field, renamed so it cannot collide with this library's own Field).",
1384
+ "props": {
1385
+ "orientation": {
1386
+ "type": "'vertical' | 'horizontal' | 'responsive'"
1387
+ },
1388
+ "invalid": {
1389
+ "type": "boolean"
1390
+ },
1391
+ "disabled": {
1392
+ "type": "boolean"
1393
+ },
1394
+ "children": {
1395
+ "type": "ReactNode"
1396
+ }
1397
+ },
1398
+ "surfaces": [
1399
+ "web"
1400
+ ],
1401
+ "a11y": [
1402
+ "role=group on the field and role=alert on its error; FieldLabel is a real label element; a multi-message error renders as a list rather than one run-on line"
1403
+ ]
1404
+ },
1405
+ "Popover": {
1406
+ "summary": "A floating panel anchored to a trigger: the root owns open state, the trigger toggles it, and the content is positioned in viewport coordinates with Escape and outside-click closing (ported from shadcn/ui's Popover; Radix's primitive is replaced by hand, and the panel renders in place rather than through a portal).",
1407
+ "props": {
1408
+ "open": {
1409
+ "type": "boolean"
1410
+ },
1411
+ "defaultOpen": {
1412
+ "type": "boolean"
1413
+ },
1414
+ "onOpenChange": {
1415
+ "type": "(open: boolean) => void"
1416
+ },
1417
+ "children": {
1418
+ "type": "ReactNode"
1419
+ }
1420
+ },
1421
+ "surfaces": [
1422
+ "web"
1423
+ ],
1424
+ "a11y": [
1425
+ "the trigger carries aria-haspopup=dialog and aria-expanded; the panel is role=dialog with the caller's label and takes focus once it is positioned; Escape closes it and returns focus to the trigger; a press outside closes it and leaves focus where the user pressed"
1426
+ ]
1427
+ },
1428
+ "Slider": {
1429
+ "summary": "A slider with one thumb per value, draggable and keyboard-operable, with a range fill spanning the lowest to the highest value (ported from shadcn/ui's Slider; Radix's primitive is replaced by hand).",
1430
+ "props": {
1431
+ "value": {
1432
+ "type": "number | number[]"
1433
+ },
1434
+ "defaultValue": {
1435
+ "type": "number | number[]"
1436
+ },
1437
+ "min": {
1438
+ "type": "number"
1439
+ },
1440
+ "max": {
1441
+ "type": "number"
1442
+ },
1443
+ "step": {
1444
+ "type": "number"
1445
+ },
1446
+ "orientation": {
1447
+ "type": "'horizontal' | 'vertical'"
1448
+ },
1449
+ "onValueChange": {
1450
+ "type": "(value: number[]) => void"
1451
+ }
1452
+ },
1453
+ "surfaces": [
1454
+ "web"
1455
+ ],
1456
+ "a11y": [
1457
+ "each thumb is role=slider with aria-valuemin, aria-valuemax, aria-valuenow and aria-orientation; arrows move by one step, PageUp/PageDown by ten, Home/End jump to the ends; a disabled slider takes its thumbs out of the tab order and reports aria-disabled"
1458
+ ]
1459
+ },
1460
+ "Sheet": {
1461
+ "summary": "A panel that slides in from an edge - top, right, bottom or left - over an overlay, dismissed by Escape, an overlay press or the close button (ported from shadcn/ui's Sheet; Radix's Dialog is replaced by hand).",
1462
+ "props": {
1463
+ "open": {
1464
+ "type": "boolean"
1465
+ },
1466
+ "defaultOpen": {
1467
+ "type": "boolean"
1468
+ },
1469
+ "onOpenChange": {
1470
+ "type": "(open: boolean) => void"
1471
+ },
1472
+ "children": {
1473
+ "type": "ReactNode"
1474
+ }
1475
+ },
1476
+ "surfaces": [
1477
+ "web"
1478
+ ],
1479
+ "a11y": [
1480
+ "role=dialog with aria-modal=true and the caller's label; focus moves onto the panel as it opens and back to the trigger on close; Tab wraps inside the panel. The page behind is NOT made inert, so assistive tech can still reach it - recorded in the manifest rather than claimed as done"
1481
+ ]
1482
+ },
1483
+ "Drawer": {
1484
+ "summary": "A sheet you can flick away: a panel from any edge, with a drag handle on the horizontal edges and dismissal by dragging past a quarter of its extent (ported from shadcn/ui's Drawer; vaul is replaced by hand).",
1485
+ "props": {
1486
+ "open": {
1487
+ "type": "boolean"
1488
+ },
1489
+ "defaultOpen": {
1490
+ "type": "boolean"
1491
+ },
1492
+ "direction": {
1493
+ "type": "'top' | 'right' | 'bottom' | 'left'"
1494
+ },
1495
+ "onOpenChange": {
1496
+ "type": "(open: boolean) => void"
1497
+ },
1498
+ "children": {
1499
+ "type": "ReactNode"
1500
+ }
1501
+ },
1502
+ "surfaces": [
1503
+ "web"
1504
+ ],
1505
+ "a11y": [
1506
+ "role=dialog with aria-modal=true and the caller's label; focus moves onto the panel as it opens and back to the trigger on close; Tab wraps inside the panel; a press that starts on a control inside the panel belongs to that control rather than to the drag. The page behind is NOT inert, as recorded for Sheet. Dismissal is by distance only - vaul's velocity flick is not implemented"
1507
+ ]
1508
+ },
1509
+ "Command": {
1510
+ "summary": "A searchable command menu: an input, a filtered list with groups and headings, an empty state, and keyboard selection (ported from shadcn/ui's Command; cmdk is replaced by hand).",
1511
+ "props": {
1512
+ "label": {
1513
+ "type": "string"
1514
+ },
1515
+ "query": {
1516
+ "type": "string"
1517
+ },
1518
+ "onQueryChange": {
1519
+ "type": "(query: string) => void"
1520
+ },
1521
+ "children": {
1522
+ "type": "ReactNode"
1523
+ }
1524
+ },
1525
+ "surfaces": [
1526
+ "web"
1527
+ ],
1528
+ "a11y": [
1529
+ "the root is role=combobox with aria-controls pointing at the listbox and the caller's label; the input carries aria-activedescendant pointing at the active option and aria-autocomplete=list; each row is role=option with aria-selected; a filtered-out row is display-none, so it leaves the accessibility tree as well as the layout. CommandDialog is not ported (it composes the Dialog item), so a consumer places this Command inside this library's Dialog"
1530
+ ]
1531
+ },
1532
+ "Combobox": {
1533
+ "summary": "A searchable single-select combobox: a field that filters a list, an anchored panel, groups with labels, an empty state and keyboard selection (ported from shadcn/ui's Combobox; Base UI's primitive is replaced by hand).",
1534
+ "props": {
1535
+ "open": {
1536
+ "type": "boolean"
1537
+ },
1538
+ "defaultOpen": {
1539
+ "type": "boolean"
1540
+ },
1541
+ "value": {
1542
+ "type": "string | null"
1543
+ },
1544
+ "defaultValue": {
1545
+ "type": "string | null"
1546
+ },
1547
+ "onValueChange": {
1548
+ "type": "(value: string | null) => void"
1549
+ },
1550
+ "onOpenChange": {
1551
+ "type": "(open: boolean) => void"
1552
+ }
1553
+ },
1554
+ "surfaces": [
1555
+ "web"
1556
+ ],
1557
+ "a11y": [
1558
+ "the field is role=combobox with aria-expanded and aria-controls naming the listbox, and aria-activedescendant pointing at the active row while open; rows are role=option with aria-selected and the source's data-highlighted hook for the active one; a filtered-out row is display-none, leaving the accessibility tree with the layout; the panel is not portalled, so an ancestor with overflow hidden or a transform can clip it. Single-select only in this pass - the multi-select chips family is a recorded follow-up"
1559
+ ]
1560
+ },
1561
+ "ContextMenu": {
1562
+ "summary": "A menu opened by a right-click, anchored at the pointer rather than at a field, with checkbox and radio rows (ported from shadcn/ui's Context Menu; Radix's primitive is replaced by hand).",
1563
+ "props": {
1564
+ "open": {
1565
+ "type": "boolean"
1566
+ },
1567
+ "defaultOpen": {
1568
+ "type": "boolean"
1569
+ },
1570
+ "onOpenChange": {
1571
+ "type": "(open: boolean) => void"
1572
+ },
1573
+ "children": {
1574
+ "type": "ReactNode"
1575
+ }
1576
+ },
1577
+ "surfaces": [
1578
+ "web"
1579
+ ],
1580
+ "a11y": [
1581
+ "the trigger is a focusable region that opens the menu on a right-click and is where focus returns on close; the panel is role=menu with arrow keys, Home/End and Enter/Space walking and activating its rows; rows are menuitem, menuitemcheckbox or menuitemradio with aria-checked where it applies, and a disabled row reports aria-disabled. The submenu family is not ported in this pass, and the panel is not portalled"
1582
+ ]
1583
+ },
1584
+ "Carousel": {
1585
+ "summary": "A sliding track of full-viewport items with previous/next controls: the platform's own scroller with snap points, and an api a caller can drive (ported from shadcn/ui's Carousel; embla is dropped for CSS scroll snap).",
1586
+ "props": {
1587
+ "orientation": {
1588
+ "type": "'horizontal' | 'vertical'"
1589
+ },
1590
+ "setApi": {
1591
+ "type": "(api: CarouselApi) => void"
1592
+ },
1593
+ "children": {
1594
+ "type": "ReactNode"
1595
+ },
1596
+ "className": {
1597
+ "type": "string"
1598
+ }
1599
+ },
1600
+ "surfaces": [
1601
+ "web"
1602
+ ],
1603
+ "a11y": [
1604
+ "the root is a role=region named by aria-roledescription=carousel, each slide is a role=group with aria-roledescription=slide, and each arrow carries screen-reader-only text; ArrowLeft and ArrowRight are handled on the root in the capture phase, so a focused arrow still moves the track, and an arrow is disabled when the track cannot move that way. A vertical carousel needs a definite height on CarouselContent. embla's wider api (its events, scroll options, drag physics and plugins) is not ported"
1605
+ ]
1606
+ },
1607
+ "ResizablePanelGroup": {
1608
+ "summary": "A group of panels with draggable dividers between them: drag a divider or resize it from the keyboard, and each panel keeps its own limits (ported from shadcn/ui's Resizable; react-resizable-panels is replaced by hand).",
1609
+ "props": {
1610
+ "orientation": {
1611
+ "type": "'horizontal' | 'vertical'"
1612
+ },
1613
+ "onLayoutChange": {
1614
+ "type": "(layout: Record<string, number>) => void"
1615
+ },
1616
+ "children": {
1617
+ "type": "ReactNode"
1618
+ },
1619
+ "className": {
1620
+ "type": "string"
1621
+ }
1622
+ },
1623
+ "surfaces": [
1624
+ "web"
1625
+ ],
1626
+ "a11y": [
1627
+ "a divider is role=separator, focusable and reachable by Tab, with aria-orientation on the opposite axis to the group, aria-controls naming the panel before it and aria-valuenow/aria-valuemin/aria-valuemax reporting that panel's current share and the window the divider can actually move it through, narrowed by whatever its neighbour can give up; the arrow keys move the pair by 5 percent (on the group's own axis), Home and End send it to an end, and Enter collapses a collapsible panel to its collapsed size and brings it back. Give the group a size: it fills its parent, and every size in this port is a percentage (a pixel size is not supported)"
1628
+ ]
1629
+ },
1630
+ "Menubar": {
1631
+ "summary": "A bar of menus in one Tab stop: the arrow keys walk its triggers and a pointer sliding along it switches menus (ported from shadcn/ui's Menubar; Radix's primitive is replaced by hand).",
1632
+ "props": {
1633
+ "onValueChange": {
1634
+ "type": "(menuId: string | null) => void"
1635
+ },
1636
+ "children": {
1637
+ "type": "ReactNode"
1638
+ },
1639
+ "className": {
1640
+ "type": "string"
1641
+ }
1642
+ },
1643
+ "surfaces": [
1644
+ "web"
1645
+ ],
1646
+ "a11y": [
1647
+ "the bar is role=menubar with aria-orientation=horizontal and is a single Tab stop, the arrow keys plus Home/End walking its triggers and opening the one they land on when a menu is already open; each trigger is a menuitem with aria-haspopup, aria-expanded and aria-controls, and a panel is role=menu whose rows are menuitem, menuitemcheckbox or menuitemradio, walked by the same keys a menu uses, with Escape closing and focusing the trigger. The submenu family is not ported in this pass, and panels are not portalled"
1648
+ ]
1649
+ },
1650
+ "NavigationMenu": {
1651
+ "summary": "A navigation bar whose panels share one surface under the whole bar, opening after a hover that rests (ported from shadcn/ui's Navigation Menu; Radix's primitive is replaced by hand).",
1652
+ "props": {
1653
+ "viewport": {
1654
+ "type": "boolean"
1655
+ },
1656
+ "children": {
1657
+ "type": "ReactNode"
1658
+ },
1659
+ "className": {
1660
+ "type": "string"
1661
+ }
1662
+ },
1663
+ "surfaces": [
1664
+ "web"
1665
+ ],
1666
+ "a11y": [
1667
+ "the bar is a nav whose list is one Tab stop, aria-expanded and aria-controls tying each trigger to its panel, and the arrow keys plus Home/End walking the triggers; Escape closes the open panel and returns focus to its trigger; links mark the current page with aria-current=page. Indicator and the panel morph animation are not ported"
1668
+ ]
1669
+ },
1670
+ "Calendar": {
1671
+ "summary": "A month grid that reports the day the reader chooses, or a range of them (ported from shadcn/ui's Calendar; react-day-picker and date-fns are replaced by the platform's own date arithmetic).",
1672
+ "props": {
1673
+ "mode": {
1674
+ "type": "'single' | 'range'"
1675
+ },
1676
+ "selected": {
1677
+ "type": "Date | CalendarRange"
1678
+ },
1679
+ "onSelect": {
1680
+ "type": "(selection: CalendarSelection) => void"
1681
+ },
1682
+ "month": {
1683
+ "type": "Date"
1684
+ },
1685
+ "defaultMonth": {
1686
+ "type": "Date"
1687
+ },
1688
+ "onMonthChange": {
1689
+ "type": "(month: Date) => void"
1690
+ },
1691
+ "showOutsideDays": {
1692
+ "type": "boolean"
1693
+ },
1694
+ "weekStartsOn": {
1695
+ "type": "0 | 1 | 2 | 3 | 4 | 5 | 6"
1696
+ },
1697
+ "locale": {
1698
+ "type": "string"
1699
+ },
1700
+ "disabled": {
1701
+ "type": "(date: Date) => boolean"
1702
+ },
1703
+ "className": {
1704
+ "type": "string"
1705
+ }
1706
+ },
1707
+ "surfaces": [
1708
+ "web"
1709
+ ],
1710
+ "a11y": [
1711
+ "the days are a real grid: role=grid with column headers for the weekdays, one aria-selected per cell, and each day button's accessible name is its full date; the keyboard model is roving - one day holds the tab stop, the arrows move by day and by week, Home and End reach the week's ends, PageUp/PageDown change the month and the grid follows the focused day, and Enter or Space chooses. A disabled day is a disabled button. Multi-month, week numbers, the dropdown caption and react-day-picker's matchers are not ported"
1712
+ ]
1713
+ },
1714
+ "Sidebar": {
1715
+ "summary": "A collapsible rail with groups of rows and an inset for the content beside it, with one keyboard shortcut and one state (ported from shadcn/ui's Sidebar; every part is written by hand).",
1716
+ "props": {
1717
+ "defaultOpen": {
1718
+ "type": "boolean"
1719
+ },
1720
+ "open": {
1721
+ "type": "boolean"
1722
+ },
1723
+ "onOpenChange": {
1724
+ "type": "(open: boolean) => void"
1725
+ },
1726
+ "side": {
1727
+ "type": "'left' | 'right'"
1728
+ },
1729
+ "variant": {
1730
+ "type": "'sidebar' | 'floating' | 'inset'"
1731
+ },
1732
+ "collapsible": {
1733
+ "type": "'offcanvas' | 'icon' | 'none'"
1734
+ },
1735
+ "isActive": {
1736
+ "type": "boolean"
1737
+ },
1738
+ "className": {
1739
+ "type": "string"
1740
+ }
1741
+ },
1742
+ "surfaces": [
1743
+ "web"
1744
+ ],
1745
+ "a11y": [
1746
+ "the toggle is a real button with a screen-reader label and Mod+B does the same thing from the keyboard, so the state is reachable either way; the active row reports aria-current=page, a group is grouped markup and the separator is role=separator; the rail strip that a reader grabs to bring a collapsed rail back is aria-hidden, because the trigger and the shortcut are the accessible paths. The mobile rail (a Sheet upstream), the collapsed-state tooltips and the cookie that remembers the state are not ported"
1747
+ ]
1748
+ }
1749
+ },
1750
+ "helpers": {
1751
+ "footerAction": {
1752
+ "summary": "Register a component in the sidebar footer (root scope, receives { wide }).",
1753
+ "slot": "sidebar.footer.action"
1754
+ },
1755
+ "headerAction": {
1756
+ "summary": "Register a component next to the conversation title (session scope).",
1757
+ "slot": "conversation.session.header.actions"
1758
+ },
1759
+ "sidebarTab": {
1760
+ "summary": "Register a tab in the right sidebar (session scope).",
1761
+ "slot": "sidebar.right.pane.tab"
1762
+ },
1763
+ "settingsSection": {
1764
+ "summary": "Add a page to the Settings screen (a nav entry beside General, Models, Plugins). Give `label` for the nav text.",
1765
+ "slot": "settings.section"
1766
+ }
1767
+ },
1768
+ "reexports": {
1769
+ "note": "Straight from the app's primitives so a consumer needs one import.",
1770
+ "names": [
1771
+ "Button",
1772
+ "Tag",
1773
+ "Pill",
1774
+ "Toast",
1775
+ "Modal",
1776
+ "Tooltip",
1777
+ "classifyLinkPath",
1778
+ "classifyFileType",
1779
+ "fileExtension"
1780
+ ]
1781
+ },
1782
+ "roles": {
1783
+ "note": "Semantic role CSS variables (--acryl-<role>), mapped to the app tokens in contracts/tokens.json.",
1784
+ "source": "contracts/tokens.json"
1785
+ },
1786
+ "notes": {
1787
+ "tui": "The terminal library (plugins/acryl-ui-tui) implements every component with pi-tui: the props above, keyboard instead of pointer (arrow keys, space, enter, y/n, escape), and no line ever wider than the terminal."
1788
+ }
1789
+ }