@estiva-app/ui 0.21.1 → 0.22.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 (58) hide show
  1. package/dist/Avatar.d.ts +3 -0
  2. package/dist/Avatar.d.ts.map +1 -1
  3. package/dist/ChipInput.d.ts +3 -0
  4. package/dist/ChipInput.d.ts.map +1 -1
  5. package/dist/CommandPalette.d.ts +6 -0
  6. package/dist/CommandPalette.d.ts.map +1 -1
  7. package/dist/IdentityMenu.d.ts +3 -0
  8. package/dist/IdentityMenu.d.ts.map +1 -1
  9. package/dist/Menu.d.ts +7 -0
  10. package/dist/Menu.d.ts.map +1 -1
  11. package/dist/Skeleton.d.ts +2 -0
  12. package/dist/Skeleton.d.ts.map +1 -1
  13. package/dist/Toast.d.ts +5 -0
  14. package/dist/Toast.d.ts.map +1 -1
  15. package/dist/Toolbar.d.ts +4 -0
  16. package/dist/Toolbar.d.ts.map +1 -1
  17. package/dist/Tooltip.d.ts +4 -0
  18. package/dist/Tooltip.d.ts.map +1 -1
  19. package/dist/index.js.map +2 -2
  20. package/dist/registry/build-GOVLABI6.js +13 -0
  21. package/dist/registry/build-GOVLABI6.js.map +7 -0
  22. package/dist/registry/build.d.ts +29 -0
  23. package/dist/registry/build.d.ts.map +1 -0
  24. package/dist/registry/chunk-IJNCYVH4.js +163 -0
  25. package/dist/registry/chunk-IJNCYVH4.js.map +7 -0
  26. package/dist/registry/chunk-MRSBS5OP.js +99 -0
  27. package/dist/registry/chunk-MRSBS5OP.js.map +7 -0
  28. package/dist/registry/chunk-QDYGB3QN.js +352 -0
  29. package/dist/registry/chunk-QDYGB3QN.js.map +7 -0
  30. package/dist/registry/cli.d.ts +2 -0
  31. package/dist/registry/cli.d.ts.map +1 -0
  32. package/dist/registry/cli.js +121 -0
  33. package/dist/registry/cli.js.map +7 -0
  34. package/dist/registry/find.d.ts +43 -0
  35. package/dist/registry/find.d.ts.map +1 -0
  36. package/dist/registry/index.d.ts +14 -0
  37. package/dist/registry/index.d.ts.map +1 -0
  38. package/dist/registry/index.js +26 -0
  39. package/dist/registry/index.js.map +7 -0
  40. package/dist/registry/schema.d.ts +147 -0
  41. package/dist/registry/schema.d.ts.map +1 -0
  42. package/package.json +15 -2
  43. package/registry.json +4470 -0
  44. package/src/Avatar.tsx +3 -0
  45. package/src/ChipInput.tsx +3 -0
  46. package/src/CommandPalette.tsx +6 -0
  47. package/src/IdentityMenu.tsx +3 -0
  48. package/src/Menu.tsx +7 -0
  49. package/src/Skeleton.tsx +2 -0
  50. package/src/Toast.tsx +5 -0
  51. package/src/Toolbar.tsx +4 -0
  52. package/src/Tooltip.tsx +4 -0
  53. package/src/registry/build.ts +590 -0
  54. package/src/registry/cli.ts +141 -0
  55. package/src/registry/find.ts +195 -0
  56. package/src/registry/index.ts +24 -0
  57. package/src/registry/registry.test.ts +448 -0
  58. package/src/registry/schema.ts +268 -0
package/registry.json ADDED
@@ -0,0 +1,4470 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "builtFrom": {
4
+ "repo": "estiva-ui",
5
+ "package": "@estiva-app/ui",
6
+ "packageVersion": "0.22.0",
7
+ "exports": 81,
8
+ "typeExports": 91
9
+ },
10
+ "storybook": {
11
+ "docsPath": "/?path=/docs/{docsId}",
12
+ "storyPath": "/?path=/story/{storyId}",
13
+ "devUrl": "http://localhost:6008"
14
+ },
15
+ "entries": [
16
+ {
17
+ "name": "AppShell",
18
+ "repo": "estiva-ui",
19
+ "kind": "component",
20
+ "importPath": "@estiva-app/ui",
21
+ "sourceFile": "src/AppShell.tsx",
22
+ "purpose": "The frame of an app, in the two manners that pair: `solid` — the structured frame, a solid TopBar over a Sidebar and the content beside it — and `floating` — the TopBar floating over the top edge, a Rail standing on the background, and the content living in the rounded card.",
23
+ "purposeFrom": "page",
24
+ "props": [
25
+ {
26
+ "name": "variant",
27
+ "takes": "solid | floating",
28
+ "required": false,
29
+ "note": null
30
+ },
31
+ {
32
+ "name": "menu",
33
+ "takes": "anything",
34
+ "required": false,
35
+ "note": "The top bar's menu button, in an app whose navigation collapses."
36
+ },
37
+ {
38
+ "name": "logo",
39
+ "takes": "anything",
40
+ "required": false,
41
+ "note": "The top bar's left: the app's logo mark, or its name as text."
42
+ },
43
+ {
44
+ "name": "search",
45
+ "takes": "anything",
46
+ "required": false,
47
+ "note": "The top bar's centre — a search field, when there is one."
48
+ },
49
+ {
50
+ "name": "identity",
51
+ "takes": "anything",
52
+ "required": false,
53
+ "note": "The top bar's right cluster — an `IdentityMenu`."
54
+ },
55
+ {
56
+ "name": "banner",
57
+ "takes": "anything",
58
+ "required": false,
59
+ "note": "A `Banner`, or nothing — drawn at the top of the content area."
60
+ },
61
+ {
62
+ "name": "nav",
63
+ "takes": "anything",
64
+ "required": true,
65
+ "note": "The navigation: a `Sidebar` in the solid manner, a `Rail` in the floating one."
66
+ },
67
+ {
68
+ "name": "children",
69
+ "takes": "anything",
70
+ "required": true,
71
+ "note": null
72
+ }
73
+ ],
74
+ "variants": [
75
+ {
76
+ "prop": "variant",
77
+ "values": [
78
+ "solid",
79
+ "floating"
80
+ ]
81
+ }
82
+ ],
83
+ "ownsBehaviours": [],
84
+ "status": "stable",
85
+ "migrationStage": null,
86
+ "docsId": "frame-appshell--docs",
87
+ "storyId": "frame-appshell--solid",
88
+ "docPage": "src/AppShell.mdx"
89
+ },
90
+ {
91
+ "name": "AttachmentCard",
92
+ "repo": "estiva-ui",
93
+ "kind": "component",
94
+ "importPath": "@estiva-app/ui",
95
+ "sourceFile": "src/AttachmentCard.tsx",
96
+ "purpose": "Something attached — a document or an image — drawn as a card: posted, or waiting to be sent.",
97
+ "purposeFrom": "page",
98
+ "props": [
99
+ {
100
+ "name": "name",
101
+ "takes": "text",
102
+ "required": true,
103
+ "note": "The name it was attached under, extension included: it decides the icon and the type label."
104
+ },
105
+ {
106
+ "name": "size",
107
+ "takes": "number",
108
+ "required": false,
109
+ "note": "In bytes."
110
+ },
111
+ {
112
+ "name": "contentType",
113
+ "takes": "text",
114
+ "required": false,
115
+ "note": "Its MIME type, where known: an `image/…` type is an image whatever its name."
116
+ },
117
+ {
118
+ "name": "href",
119
+ "takes": "text",
120
+ "required": false,
121
+ "note": "Where a document opens, in a new tab. Without it the row is dimmed and opens nothing."
122
+ },
123
+ {
124
+ "name": "src",
125
+ "takes": "text",
126
+ "required": false,
127
+ "note": "The picture an image card draws. Without it an image is drawn as a row."
128
+ },
129
+ {
130
+ "name": "onOpen",
131
+ "takes": "a handler",
132
+ "required": false,
133
+ "note": "What a click on an image's picture does — the app's full-screen view."
134
+ },
135
+ {
136
+ "name": "onDownload",
137
+ "takes": "a handler",
138
+ "required": false,
139
+ "note": "Shows a download control on hover or focus, and calls this."
140
+ },
141
+ {
142
+ "name": "pending",
143
+ "takes": "true/false",
144
+ "required": false,
145
+ "note": "Waiting to be sent: the composer's 200px row, with a remove control on its corner."
146
+ },
147
+ {
148
+ "name": "onRemove",
149
+ "takes": "a handler",
150
+ "required": false,
151
+ "note": "Removes a pending card."
152
+ },
153
+ {
154
+ "name": "state",
155
+ "takes": "ready | loading | unreadable | uploading | failed | warning",
156
+ "required": false,
157
+ "note": "`ready` · `loading` (an image on its way) · `unreadable` (it could not be read) · `uploading`, `failed`, `warning` (while pending)."
158
+ },
159
+ {
160
+ "name": "note",
161
+ "takes": "text",
162
+ "required": false,
163
+ "note": "The line under the name, in place of its type and size — why it failed, or what the warning is."
164
+ },
165
+ {
166
+ "name": "noteHint",
167
+ "takes": "text",
168
+ "required": false,
169
+ "note": "The note's full words, on hover, where the line is short."
170
+ }
171
+ ],
172
+ "variants": [
173
+ {
174
+ "prop": "state",
175
+ "values": [
176
+ "ready",
177
+ "loading",
178
+ "unreadable",
179
+ "uploading",
180
+ "failed",
181
+ "warning"
182
+ ]
183
+ }
184
+ ],
185
+ "ownsBehaviours": [],
186
+ "status": "stable",
187
+ "migrationStage": null,
188
+ "docsId": "components-attachmentcard--docs",
189
+ "storyId": "components-attachmentcard--document",
190
+ "docPage": "src/AttachmentCard.mdx"
191
+ },
192
+ {
193
+ "name": "Avatar",
194
+ "repo": "estiva-ui",
195
+ "kind": "component",
196
+ "importPath": "@estiva-app/ui",
197
+ "sourceFile": "src/Avatar.tsx",
198
+ "purpose": "A person's face: their picture, or their initials on a colour that is theirs, or — when there is no name to take initials from — a silhouette.",
199
+ "purposeFrom": "page",
200
+ "props": [
201
+ {
202
+ "name": "src",
203
+ "takes": "text",
204
+ "required": false,
205
+ "note": "The picture URL, resolved by the caller."
206
+ },
207
+ {
208
+ "name": "name",
209
+ "takes": "text",
210
+ "required": false,
211
+ "note": "The person's name — where the initials and the colour come from."
212
+ },
213
+ {
214
+ "name": "alt",
215
+ "takes": "text",
216
+ "required": false,
217
+ "note": "Alt text for the picture; the name when absent."
218
+ },
219
+ {
220
+ "name": "size",
221
+ "takes": "number",
222
+ "required": false,
223
+ "note": "Pixels. The scale: 16 · 24 · 32 · 36 (default)."
224
+ },
225
+ {
226
+ "name": "label",
227
+ "takes": "text",
228
+ "required": false,
229
+ "note": "Say the person's name out loud, for a face that stands on its own — `PersonTrigger`'s compact shape, a stack of members."
230
+ },
231
+ {
232
+ "name": "className",
233
+ "takes": "text",
234
+ "required": false,
235
+ "note": null
236
+ }
237
+ ],
238
+ "variants": [],
239
+ "ownsBehaviours": [
240
+ {
241
+ "id": "base-ui",
242
+ "behaviour": "Is built on Base UI"
243
+ }
244
+ ],
245
+ "status": "stable",
246
+ "migrationStage": null,
247
+ "docsId": "primitives-avatar--docs",
248
+ "storyId": "primitives-avatar--initials",
249
+ "docPage": "src/Avatar.mdx"
250
+ },
251
+ {
252
+ "name": "AvatarGroup",
253
+ "repo": "estiva-ui",
254
+ "kind": "component",
255
+ "importPath": "@estiva-app/ui",
256
+ "sourceFile": "src/AvatarGroup.tsx",
257
+ "purpose": "Up to three overlapping 24px faces with a surface-coloured ring — the member stack for anywhere a group is shown at a glance.",
258
+ "purposeFrom": "page",
259
+ "props": [
260
+ {
261
+ "name": "members",
262
+ "takes": "AvatarGroupMember[]",
263
+ "required": true,
264
+ "note": null
265
+ },
266
+ {
267
+ "name": "size",
268
+ "takes": "number",
269
+ "required": false,
270
+ "note": "Face size in pixels; the overlap follows it. 24 is the members pill, 18 the replies row (Katerina, 2026-09-03) — that row drew its own stack for two months for want of this one number, and drifted while it did."
271
+ }
272
+ ],
273
+ "variants": [],
274
+ "ownsBehaviours": [],
275
+ "status": "stable",
276
+ "migrationStage": null,
277
+ "docsId": "primitives-avatargroup--docs",
278
+ "storyId": "primitives-avatargroup--three-members",
279
+ "docPage": "src/AvatarGroup.mdx"
280
+ },
281
+ {
282
+ "name": "Banner",
283
+ "repo": "estiva-ui",
284
+ "kind": "component",
285
+ "importPath": "@estiva-app/ui",
286
+ "sourceFile": "src/Banner.tsx",
287
+ "purpose": "The strip under the header where the app says something happened: one line, one of four tones, gone when there is nothing to say.",
288
+ "purposeFrom": "page",
289
+ "props": [
290
+ {
291
+ "name": "tone",
292
+ "takes": "ok | error | info | warning",
293
+ "required": true,
294
+ "note": null
295
+ },
296
+ {
297
+ "name": "children",
298
+ "takes": "text",
299
+ "required": true,
300
+ "note": null
301
+ },
302
+ {
303
+ "name": "onDismiss",
304
+ "takes": "a handler",
305
+ "required": false,
306
+ "note": "Adds an `✕` at the right-hand end. Absent: the app removes the banner."
307
+ },
308
+ {
309
+ "name": "dismissLabel",
310
+ "takes": "text",
311
+ "required": false,
312
+ "note": "The dismiss button's accessible name. Defaults to \"Dismiss\"."
313
+ },
314
+ {
315
+ "name": "className",
316
+ "takes": "text",
317
+ "required": false,
318
+ "note": null
319
+ }
320
+ ],
321
+ "variants": [
322
+ {
323
+ "prop": "tone",
324
+ "values": [
325
+ "ok",
326
+ "error",
327
+ "info",
328
+ "warning"
329
+ ]
330
+ }
331
+ ],
332
+ "ownsBehaviours": [
333
+ {
334
+ "id": "role",
335
+ "behaviour": "Says what it is to assistive technology"
336
+ }
337
+ ],
338
+ "status": "stable",
339
+ "migrationStage": null,
340
+ "docsId": "feedback-banner--docs",
341
+ "storyId": "feedback-banner--ok",
342
+ "docPage": "src/Banner.mdx"
343
+ },
344
+ {
345
+ "name": "Breadcrumb",
346
+ "repo": "estiva-ui",
347
+ "kind": "component",
348
+ "importPath": "@estiva-app/ui",
349
+ "sourceFile": "src/Breadcrumb.tsx",
350
+ "purpose": "A trail: where you are, and the way back up.",
351
+ "purposeFrom": "page",
352
+ "props": [
353
+ {
354
+ "name": "items",
355
+ "takes": "Crumb[]",
356
+ "required": true,
357
+ "note": null
358
+ },
359
+ {
360
+ "name": "className",
361
+ "takes": "text",
362
+ "required": false,
363
+ "note": null
364
+ }
365
+ ],
366
+ "variants": [],
367
+ "ownsBehaviours": [],
368
+ "status": "stable",
369
+ "migrationStage": null,
370
+ "docsId": "navigation-breadcrumb--docs",
371
+ "storyId": "navigation-breadcrumb--on-an-item",
372
+ "docPage": "src/Breadcrumb.mdx"
373
+ },
374
+ {
375
+ "name": "Button",
376
+ "repo": "estiva-ui",
377
+ "kind": "component",
378
+ "importPath": "@estiva-app/ui",
379
+ "sourceFile": "src/Button.tsx",
380
+ "purpose": "The push-button for an action: a verb, clicked once — \"Create\", \"Save\", \"Delete project\".",
381
+ "purposeFrom": "page",
382
+ "props": [
383
+ {
384
+ "name": "variant",
385
+ "takes": "primary | outlined | muted | destructive | resolve",
386
+ "required": false,
387
+ "note": null
388
+ },
389
+ {
390
+ "name": "size",
391
+ "takes": "default | small",
392
+ "required": false,
393
+ "note": null
394
+ },
395
+ {
396
+ "name": "leadingIcon",
397
+ "takes": "anything",
398
+ "required": false,
399
+ "note": "16px, stroke 1.5 on the default size; 14px on small."
400
+ },
401
+ {
402
+ "name": "disabledReason",
403
+ "takes": "text",
404
+ "required": false,
405
+ "note": "Why the action cannot succeed right now."
406
+ },
407
+ {
408
+ "name": "children",
409
+ "takes": "anything",
410
+ "required": true,
411
+ "note": null
412
+ }
413
+ ],
414
+ "variants": [
415
+ {
416
+ "prop": "variant",
417
+ "values": [
418
+ "primary",
419
+ "outlined",
420
+ "muted",
421
+ "destructive",
422
+ "resolve"
423
+ ]
424
+ },
425
+ {
426
+ "prop": "size",
427
+ "values": [
428
+ "default",
429
+ "small"
430
+ ]
431
+ }
432
+ ],
433
+ "ownsBehaviours": [
434
+ {
435
+ "id": "base-ui",
436
+ "behaviour": "Is built on Base UI"
437
+ },
438
+ {
439
+ "id": "role",
440
+ "behaviour": "Says what it is to assistive technology"
441
+ },
442
+ {
443
+ "id": "tab-stop",
444
+ "behaviour": "Is reachable with Tab"
445
+ }
446
+ ],
447
+ "status": "stable",
448
+ "migrationStage": null,
449
+ "docsId": "primitives-button--docs",
450
+ "storyId": "primitives-button--primary",
451
+ "docPage": "src/Button.mdx"
452
+ },
453
+ {
454
+ "name": "Card",
455
+ "repo": "estiva-ui",
456
+ "kind": "component",
457
+ "importPath": "@estiva-app/ui",
458
+ "sourceFile": "src/Card.tsx",
459
+ "purpose": "A box that stands for one thing — drawn as its frame: 8px corners, a fill and a hairline.",
460
+ "purposeFrom": "page",
461
+ "props": [
462
+ {
463
+ "name": "fill",
464
+ "takes": "surface | elevated | inset | none",
465
+ "required": false,
466
+ "note": "What the card sits on. Default `surface`."
467
+ },
468
+ {
469
+ "name": "href",
470
+ "takes": "text",
471
+ "required": false,
472
+ "note": "The whole card is a link: an anchor, and its hairline answers the pointer."
473
+ },
474
+ {
475
+ "name": "hover",
476
+ "takes": "none | hairline | fill",
477
+ "required": false,
478
+ "note": "How it answers the pointer. Default `hairline` with an `href`, `none` without."
479
+ },
480
+ {
481
+ "name": "quietUntilHover",
482
+ "takes": "true/false",
483
+ "required": false,
484
+ "note": "No hairline until it is pointed at — a row in a feed that shows its edge only when you are on it."
485
+ },
486
+ {
487
+ "name": "hovered",
488
+ "takes": "true/false",
489
+ "required": false,
490
+ "note": "Draw the hover look now, whatever the pointer does."
491
+ },
492
+ {
493
+ "name": "selected",
494
+ "takes": "true/false",
495
+ "required": false,
496
+ "note": "The one you are on: the selected fill, a subtle hairline, and no hover."
497
+ },
498
+ {
499
+ "name": "active",
500
+ "takes": "true/false",
501
+ "required": false,
502
+ "note": "Being changed in place: the selected fill with the accent hairline, and no hover."
503
+ },
504
+ {
505
+ "name": "attention",
506
+ "takes": "accent | warning",
507
+ "required": false,
508
+ "note": "A hairline that asks to be looked at — something new (`accent`), or urgent (`warning`)."
509
+ },
510
+ {
511
+ "name": "unreadable",
512
+ "takes": "true/false",
513
+ "required": false,
514
+ "note": "It stands for something that could not be read: the hairline is dashed."
515
+ },
516
+ {
517
+ "name": "clip",
518
+ "takes": "true/false",
519
+ "required": false,
520
+ "note": "What is inside is cut to the card's rounded corners: a strip or a picture that runs edge to edge (UIG-9, 17 September; the apps passed `overflow-hidden`)."
521
+ },
522
+ {
523
+ "name": "children",
524
+ "takes": "anything",
525
+ "required": true,
526
+ "note": null
527
+ }
528
+ ],
529
+ "variants": [
530
+ {
531
+ "prop": "fill",
532
+ "values": [
533
+ "surface",
534
+ "elevated",
535
+ "inset",
536
+ "none"
537
+ ]
538
+ },
539
+ {
540
+ "prop": "hover",
541
+ "values": [
542
+ "none",
543
+ "hairline",
544
+ "fill"
545
+ ]
546
+ },
547
+ {
548
+ "prop": "attention",
549
+ "values": [
550
+ "accent",
551
+ "warning"
552
+ ]
553
+ }
554
+ ],
555
+ "ownsBehaviours": [],
556
+ "status": "stable",
557
+ "migrationStage": null,
558
+ "docsId": "primitives-card--docs",
559
+ "storyId": "primitives-card--surface",
560
+ "docPage": "src/Card.mdx"
561
+ },
562
+ {
563
+ "name": "Checkbox",
564
+ "repo": "estiva-ui",
565
+ "kind": "component",
566
+ "importPath": "@estiva-app/ui",
567
+ "sourceFile": "src/Checkbox.tsx",
568
+ "purpose": "A 16px square that fills with the accent when checked.",
569
+ "purposeFrom": "page",
570
+ "props": [
571
+ {
572
+ "name": "checked",
573
+ "takes": "true/false",
574
+ "required": true,
575
+ "note": null
576
+ },
577
+ {
578
+ "name": "onChange",
579
+ "takes": "a handler",
580
+ "required": false,
581
+ "note": null
582
+ },
583
+ {
584
+ "name": "disabled",
585
+ "takes": "true/false",
586
+ "required": false,
587
+ "note": null
588
+ },
589
+ {
590
+ "name": "label",
591
+ "takes": "text",
592
+ "required": false,
593
+ "note": "Words beside the box. With `onChange`, clicking them toggles it too, and they name it, so no `aria-label` is needed."
594
+ },
595
+ {
596
+ "name": "row",
597
+ "takes": "true/false",
598
+ "required": false,
599
+ "note": "The whole row is the target: `leading`, then the words, then the box at the end; the row fills on hover and while checked."
600
+ },
601
+ {
602
+ "name": "leading",
603
+ "takes": "anything",
604
+ "required": false,
605
+ "note": "In a `row`, a picture before the words: an icon, a status."
606
+ },
607
+ {
608
+ "name": "aria-label",
609
+ "takes": "text",
610
+ "required": false,
611
+ "note": null
612
+ },
613
+ {
614
+ "name": "aria-required",
615
+ "takes": "boolean | 'true' | 'false'",
616
+ "required": false,
617
+ "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
618
+ },
619
+ {
620
+ "name": "className",
621
+ "takes": "text",
622
+ "required": false,
623
+ "note": null
624
+ }
625
+ ],
626
+ "variants": [],
627
+ "ownsBehaviours": [
628
+ {
629
+ "id": "base-ui",
630
+ "behaviour": "Is built on Base UI"
631
+ },
632
+ {
633
+ "id": "role",
634
+ "behaviour": "Says what it is to assistive technology"
635
+ }
636
+ ],
637
+ "status": "stable",
638
+ "migrationStage": null,
639
+ "docsId": "inputs-checkbox--docs",
640
+ "storyId": "inputs-checkbox--unchecked",
641
+ "docPage": "src/Checkbox.mdx"
642
+ },
643
+ {
644
+ "name": "Chip",
645
+ "repo": "estiva-ui",
646
+ "kind": "component",
647
+ "importPath": "@estiva-app/ui",
648
+ "sourceFile": "src/Chip.tsx",
649
+ "purpose": "A 20px pill for a small piece of standing information — a status, a count, a category — in one of six colour types.",
650
+ "purposeFrom": "page",
651
+ "props": [
652
+ {
653
+ "name": "type",
654
+ "takes": "neutral | brand | info | warning | success | error",
655
+ "required": false,
656
+ "note": null
657
+ },
658
+ {
659
+ "name": "label",
660
+ "takes": "text",
661
+ "required": false,
662
+ "note": null
663
+ },
664
+ {
665
+ "name": "leadingIcon",
666
+ "takes": "anything",
667
+ "required": false,
668
+ "note": null
669
+ },
670
+ {
671
+ "name": "trailingIcon",
672
+ "takes": "anything",
673
+ "required": false,
674
+ "note": null
675
+ },
676
+ {
677
+ "name": "className",
678
+ "takes": "text",
679
+ "required": false,
680
+ "note": null
681
+ }
682
+ ],
683
+ "variants": [
684
+ {
685
+ "prop": "type",
686
+ "values": [
687
+ "neutral",
688
+ "brand",
689
+ "info",
690
+ "warning",
691
+ "success",
692
+ "error"
693
+ ]
694
+ }
695
+ ],
696
+ "ownsBehaviours": [],
697
+ "status": "stable",
698
+ "migrationStage": null,
699
+ "docsId": "primitives-chip--docs",
700
+ "storyId": "primitives-chip--neutral",
701
+ "docPage": "src/Chip.mdx"
702
+ },
703
+ {
704
+ "name": "ChipInput",
705
+ "repo": "estiva-ui",
706
+ "kind": "component",
707
+ "importPath": "@estiva-app/ui",
708
+ "sourceFile": "src/ChipInput.tsx",
709
+ "purpose": "A multi-select input: chips for the chosen, a typeahead for the rest.",
710
+ "purposeFrom": "page",
711
+ "props": [
712
+ {
713
+ "name": "value",
714
+ "takes": "T[]",
715
+ "required": true,
716
+ "note": null
717
+ },
718
+ {
719
+ "name": "onChange",
720
+ "takes": "a handler",
721
+ "required": true,
722
+ "note": null
723
+ },
724
+ {
725
+ "name": "options",
726
+ "takes": "T[]",
727
+ "required": true,
728
+ "note": "The directory the typeahead searches."
729
+ },
730
+ {
731
+ "name": "placeholder",
732
+ "takes": "text",
733
+ "required": false,
734
+ "note": null
735
+ },
736
+ {
737
+ "name": "autoFocus",
738
+ "takes": "true/false",
739
+ "required": false,
740
+ "note": null
741
+ },
742
+ {
743
+ "name": "excludeIds",
744
+ "takes": "string[]",
745
+ "required": false,
746
+ "note": "Option ids excluded from the suggestion list (e.g., the current user)."
747
+ },
748
+ {
749
+ "name": "chipLeading",
750
+ "takes": "a handler",
751
+ "required": false,
752
+ "note": "Before a chip's label, 16px — a face, an icon."
753
+ },
754
+ {
755
+ "name": "rowLeading",
756
+ "takes": "a handler",
757
+ "required": false,
758
+ "note": "Before a suggestion row's label, 32px."
759
+ },
760
+ {
761
+ "name": "aria-required",
762
+ "takes": "boolean | 'true' | 'false'",
763
+ "required": false,
764
+ "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
765
+ },
766
+ {
767
+ "name": "aria-label",
768
+ "takes": "text",
769
+ "required": false,
770
+ "note": "The field's name, for a caller that is not inside a `Field` — a `Field`'s label names it already."
771
+ },
772
+ {
773
+ "name": "aria-labelledby",
774
+ "takes": "text",
775
+ "required": false,
776
+ "note": "The id of what names the field on the page — a visible \"To:\", say."
777
+ }
778
+ ],
779
+ "variants": [],
780
+ "ownsBehaviours": [
781
+ {
782
+ "id": "base-ui",
783
+ "behaviour": "Is built on Base UI"
784
+ },
785
+ {
786
+ "id": "portal",
787
+ "behaviour": "Floats on top of the page"
788
+ },
789
+ {
790
+ "id": "walking",
791
+ "behaviour": "Moves through its items with the arrow keys"
792
+ },
793
+ {
794
+ "id": "role",
795
+ "behaviour": "Says what it is to assistive technology"
796
+ }
797
+ ],
798
+ "status": "stable",
799
+ "migrationStage": null,
800
+ "docsId": "inputs-chipinput--docs",
801
+ "storyId": "inputs-chipinput--type-to-search",
802
+ "docPage": "src/ChipInput.mdx"
803
+ },
804
+ {
805
+ "name": "cn",
806
+ "repo": "estiva-ui",
807
+ "kind": "helper",
808
+ "importPath": "@estiva-app/ui",
809
+ "sourceFile": "src/cn.ts",
810
+ "purpose": "Merge class names, last-one-wins on conflicting Tailwind utilities.",
811
+ "purposeFrom": "comment",
812
+ "props": [],
813
+ "variants": [],
814
+ "ownsBehaviours": [],
815
+ "status": "stable",
816
+ "migrationStage": null,
817
+ "docsId": null,
818
+ "storyId": null,
819
+ "docPage": null
820
+ },
821
+ {
822
+ "name": "CollapsibleSection",
823
+ "repo": "estiva-ui",
824
+ "kind": "component",
825
+ "importPath": "@estiva-app/ui",
826
+ "sourceFile": "src/CollapsibleSection.tsx",
827
+ "purpose": "A section that opens and closes: a SectionHeader whose title is the toggle, and the rows under it, sliding shut and open.",
828
+ "purposeFrom": "page",
829
+ "props": [
830
+ {
831
+ "name": "title",
832
+ "takes": "text",
833
+ "required": true,
834
+ "note": null
835
+ },
836
+ {
837
+ "name": "defaultOpen",
838
+ "takes": "true/false",
839
+ "required": false,
840
+ "note": "Open unless told otherwise."
841
+ },
842
+ {
843
+ "name": "open",
844
+ "takes": "true/false",
845
+ "required": false,
846
+ "note": "The caller owns the state."
847
+ },
848
+ {
849
+ "name": "onOpenChange",
850
+ "takes": "a handler",
851
+ "required": false,
852
+ "note": null
853
+ },
854
+ {
855
+ "name": "storageKey",
856
+ "takes": "text",
857
+ "required": false,
858
+ "note": "Remember open or closed in this browser, under this key."
859
+ },
860
+ {
861
+ "name": "trailing",
862
+ "takes": "anything",
863
+ "required": false,
864
+ "note": "Beside the title and always visible, before the actions — a count."
865
+ },
866
+ {
867
+ "name": "actions",
868
+ "takes": "SectionAction[]",
869
+ "required": false,
870
+ "note": "Beside the title, revealed on hover or focus — `SectionHeader`'s."
871
+ },
872
+ {
873
+ "name": "showActions",
874
+ "takes": "hover | always",
875
+ "required": false,
876
+ "note": null
877
+ },
878
+ {
879
+ "name": "children",
880
+ "takes": "anything",
881
+ "required": true,
882
+ "note": "The rows."
883
+ },
884
+ {
885
+ "name": "className",
886
+ "takes": "text",
887
+ "required": false,
888
+ "note": "On the section's box: `mt-2` between groups, `shrink-0` in a scrolling column."
889
+ },
890
+ {
891
+ "name": "contentClassName",
892
+ "takes": "text",
893
+ "required": false,
894
+ "note": "On the box the rows sit in: the gap between them."
895
+ }
896
+ ],
897
+ "variants": [
898
+ {
899
+ "prop": "showActions",
900
+ "values": [
901
+ "hover",
902
+ "always"
903
+ ]
904
+ }
905
+ ],
906
+ "ownsBehaviours": [
907
+ {
908
+ "id": "base-ui",
909
+ "behaviour": "Is built on Base UI"
910
+ }
911
+ ],
912
+ "status": "stable",
913
+ "migrationStage": null,
914
+ "docsId": "navigation-collapsiblesection--docs",
915
+ "storyId": "navigation-collapsiblesection--default",
916
+ "docPage": "src/CollapsibleSection.mdx"
917
+ },
918
+ {
919
+ "name": "CommandPalette",
920
+ "repo": "estiva-ui",
921
+ "kind": "component",
922
+ "importPath": "@estiva-app/ui",
923
+ "sourceFile": "src/CommandPalette.tsx",
924
+ "purpose": "A window that searches and runs things: a field, rows in groups, and a footer naming the keys that work right now.",
925
+ "purposeFrom": "page",
926
+ "props": [
927
+ {
928
+ "name": "open",
929
+ "takes": "true/false",
930
+ "required": true,
931
+ "note": null
932
+ },
933
+ {
934
+ "name": "onOpenChange",
935
+ "takes": "a handler",
936
+ "required": true,
937
+ "note": null
938
+ },
939
+ {
940
+ "name": "label",
941
+ "takes": "text",
942
+ "required": true,
943
+ "note": "The window's name for a screen reader — there is no title on screen."
944
+ },
945
+ {
946
+ "name": "where",
947
+ "takes": "text",
948
+ "required": false,
949
+ "note": "The footer's left side: where the palette was opened from."
950
+ },
951
+ {
952
+ "name": "modKey",
953
+ "takes": "text",
954
+ "required": false,
955
+ "note": "How the footer spells the modifier in `Ctrl+Backspace` and `Ctrl+Enter` — `Cmd` on a Mac."
956
+ },
957
+ {
958
+ "name": "children",
959
+ "takes": "anything",
960
+ "required": true,
961
+ "note": "One level: a `CommandPaletteSearch` or a `CommandPaletteForm`."
962
+ }
963
+ ],
964
+ "variants": [],
965
+ "ownsBehaviours": [
966
+ {
967
+ "id": "base-ui",
968
+ "behaviour": "Is built on Base UI"
969
+ },
970
+ {
971
+ "id": "portal",
972
+ "behaviour": "Floats on top of the page"
973
+ },
974
+ {
975
+ "id": "focus",
976
+ "behaviour": "Holds focus inside while open, and gives it back"
977
+ },
978
+ {
979
+ "id": "walking",
980
+ "behaviour": "Moves through its items with the arrow keys"
981
+ },
982
+ {
983
+ "id": "role",
984
+ "behaviour": "Says what it is to assistive technology"
985
+ }
986
+ ],
987
+ "status": "stable",
988
+ "migrationStage": null,
989
+ "docsId": "overlays-commandpalette--docs",
990
+ "storyId": "overlays-commandpalette--first-level",
991
+ "docPage": "src/CommandPalette.mdx"
992
+ },
993
+ {
994
+ "name": "CommandPaletteAnswer",
995
+ "repo": "estiva-ui",
996
+ "kind": "component",
997
+ "importPath": "@estiva-app/ui",
998
+ "sourceFile": "src/CommandPalette.tsx",
999
+ "purpose": "A written answer, with marks that point at the rows it came from.",
1000
+ "purposeFrom": "comment",
1001
+ "props": [
1002
+ {
1003
+ "name": "children",
1004
+ "takes": "text",
1005
+ "required": true,
1006
+ "note": "The answer's text. A blank line starts a new paragraph, and a number in square brackets — `[1]` — is drawn as a small mark pointing at the row of the same number below."
1007
+ },
1008
+ {
1009
+ "name": "note",
1010
+ "takes": "text",
1011
+ "required": false,
1012
+ "note": "A quiet line under the answer — what a key will do now."
1013
+ }
1014
+ ],
1015
+ "variants": [],
1016
+ "ownsBehaviours": [],
1017
+ "status": "stable",
1018
+ "migrationStage": null,
1019
+ "docsId": "overlays-commandpalette--docs",
1020
+ "storyId": "overlays-commandpalette--first-level",
1021
+ "docPage": null
1022
+ },
1023
+ {
1024
+ "name": "CommandPaletteForm",
1025
+ "repo": "estiva-ui",
1026
+ "kind": "component",
1027
+ "importPath": "@estiva-app/ui",
1028
+ "sourceFile": "src/CommandPalette.tsx",
1029
+ "purpose": "The palette as a form: fields, one submit button, and Ctrl+Enter — both ways in run Base UI's field check.",
1030
+ "purposeFrom": "comment",
1031
+ "props": [
1032
+ {
1033
+ "name": "chip",
1034
+ "takes": "CommandPaletteChip",
1035
+ "required": true,
1036
+ "note": "Names what the form makes, and goes back when removed."
1037
+ },
1038
+ {
1039
+ "name": "icon",
1040
+ "takes": "anything",
1041
+ "required": false,
1042
+ "note": "Before the chip, 16px — the mark of whatever the form writes to."
1043
+ },
1044
+ {
1045
+ "name": "submitLabel",
1046
+ "takes": "text",
1047
+ "required": true,
1048
+ "note": "The button's word, and the footer's beside Ctrl+Enter."
1049
+ },
1050
+ {
1051
+ "name": "onSubmit",
1052
+ "takes": "a handler",
1053
+ "required": true,
1054
+ "note": null
1055
+ },
1056
+ {
1057
+ "name": "submitWaits",
1058
+ "takes": "text",
1059
+ "required": false,
1060
+ "note": "Why submitting has to wait — nothing changed yet."
1061
+ },
1062
+ {
1063
+ "name": "working",
1064
+ "takes": "{ button: string; line: string }",
1065
+ "required": false,
1066
+ "note": "While the thing is being made: the fields lock, the button reads `button`, and `line` says what is happening."
1067
+ },
1068
+ {
1069
+ "name": "error",
1070
+ "takes": "text",
1071
+ "required": false,
1072
+ "note": "What went wrong, beside the button."
1073
+ },
1074
+ {
1075
+ "name": "children",
1076
+ "takes": "anything",
1077
+ "required": true,
1078
+ "note": "The fields, each in a `Field`."
1079
+ }
1080
+ ],
1081
+ "variants": [],
1082
+ "ownsBehaviours": [],
1083
+ "status": "stable",
1084
+ "migrationStage": null,
1085
+ "docsId": "overlays-commandpalette--docs",
1086
+ "storyId": "overlays-commandpalette--first-level",
1087
+ "docPage": null
1088
+ },
1089
+ {
1090
+ "name": "CommandPaletteQuote",
1091
+ "repo": "estiva-ui",
1092
+ "kind": "component",
1093
+ "importPath": "@estiva-app/ui",
1094
+ "sourceFile": "src/CommandPalette.tsx",
1095
+ "purpose": "Text written to be used elsewhere, set off by a rule at its left edge.",
1096
+ "purposeFrom": "comment",
1097
+ "props": [
1098
+ {
1099
+ "name": "children",
1100
+ "takes": "text",
1101
+ "required": true,
1102
+ "note": "Text written for someone to use — shown as it will be used, line breaks kept."
1103
+ }
1104
+ ],
1105
+ "variants": [],
1106
+ "ownsBehaviours": [],
1107
+ "status": "stable",
1108
+ "migrationStage": null,
1109
+ "docsId": "overlays-commandpalette--docs",
1110
+ "storyId": "overlays-commandpalette--first-level",
1111
+ "docPage": null
1112
+ },
1113
+ {
1114
+ "name": "CommandPaletteSearch",
1115
+ "repo": "estiva-ui",
1116
+ "kind": "component",
1117
+ "importPath": "@estiva-app/ui",
1118
+ "sourceFile": "src/CommandPalette.tsx",
1119
+ "purpose": "The palette as a search: a query field, rows in labelled groups walked with the arrow keys, and what to show while nothing has arrived and when nothing matches.",
1120
+ "purposeFrom": "comment",
1121
+ "props": [
1122
+ {
1123
+ "name": "query",
1124
+ "takes": "text",
1125
+ "required": true,
1126
+ "note": null
1127
+ },
1128
+ {
1129
+ "name": "onQueryChange",
1130
+ "takes": "a handler",
1131
+ "required": true,
1132
+ "note": null
1133
+ },
1134
+ {
1135
+ "name": "placeholder",
1136
+ "takes": "text",
1137
+ "required": true,
1138
+ "note": null
1139
+ },
1140
+ {
1141
+ "name": "groups",
1142
+ "takes": "CommandPaletteGroup[]",
1143
+ "required": true,
1144
+ "note": null
1145
+ },
1146
+ {
1147
+ "name": "chip",
1148
+ "takes": "CommandPaletteChip",
1149
+ "required": false,
1150
+ "note": "The level you are in. Without one, this is the first level and there is nowhere to go back to."
1151
+ },
1152
+ {
1153
+ "name": "pending",
1154
+ "takes": "text",
1155
+ "required": false,
1156
+ "note": "A line under the rows while more are on their way — \"Searching…\"."
1157
+ },
1158
+ {
1159
+ "name": "notes",
1160
+ "takes": "string[]",
1161
+ "required": false,
1162
+ "note": "Quiet lines under the rows, for what a person should know about them and cannot act on — \"2 more where you cannot open them\", \"the search was refused, so this list is incomplete\"."
1163
+ },
1164
+ {
1165
+ "name": "empty",
1166
+ "takes": "text",
1167
+ "required": false,
1168
+ "note": "The line when there are no rows. Leave it out while rows are still on their way."
1169
+ },
1170
+ {
1171
+ "name": "children",
1172
+ "takes": "anything",
1173
+ "required": false,
1174
+ "note": "Above the rows: a `CommandPaletteWorking`, `CommandPaletteAnswer` or `CommandPaletteQuote`."
1175
+ }
1176
+ ],
1177
+ "variants": [],
1178
+ "ownsBehaviours": [],
1179
+ "status": "stable",
1180
+ "migrationStage": null,
1181
+ "docsId": "overlays-commandpalette--docs",
1182
+ "storyId": "overlays-commandpalette--first-level",
1183
+ "docPage": null
1184
+ },
1185
+ {
1186
+ "name": "CommandPaletteWorking",
1187
+ "repo": "estiva-ui",
1188
+ "kind": "component",
1189
+ "importPath": "@estiva-app/ui",
1190
+ "sourceFile": "src/CommandPalette.tsx",
1191
+ "purpose": "A line saying what is being worked on, with grey bars where the result will land.",
1192
+ "purposeFrom": "comment",
1193
+ "props": [
1194
+ {
1195
+ "name": "children",
1196
+ "takes": "anything",
1197
+ "required": true,
1198
+ "note": "What is happening — \"Reading 12 messages…\"."
1199
+ },
1200
+ {
1201
+ "name": "bars",
1202
+ "takes": "0 | 1 | 2 | 3",
1203
+ "required": false,
1204
+ "note": "Grey bars under the line, where the result will be."
1205
+ }
1206
+ ],
1207
+ "variants": [],
1208
+ "ownsBehaviours": [],
1209
+ "status": "stable",
1210
+ "migrationStage": null,
1211
+ "docsId": "overlays-commandpalette--docs",
1212
+ "storyId": "overlays-commandpalette--first-level",
1213
+ "docPage": null
1214
+ },
1215
+ {
1216
+ "name": "ConfirmDialog",
1217
+ "repo": "estiva-ui",
1218
+ "kind": "component",
1219
+ "importPath": "@estiva-app/ui",
1220
+ "sourceFile": "src/ConfirmDialog.tsx",
1221
+ "purpose": "A question with two answers, asked before something a person would want back.",
1222
+ "purposeFrom": "page",
1223
+ "props": [
1224
+ {
1225
+ "name": "title",
1226
+ "takes": "text",
1227
+ "required": true,
1228
+ "note": null
1229
+ },
1230
+ {
1231
+ "name": "children",
1232
+ "takes": "anything",
1233
+ "required": true,
1234
+ "note": "The body — plain sentences, body-2."
1235
+ },
1236
+ {
1237
+ "name": "confirmLabel",
1238
+ "takes": "text",
1239
+ "required": true,
1240
+ "note": null
1241
+ },
1242
+ {
1243
+ "name": "destructive",
1244
+ "takes": "true/false",
1245
+ "required": false,
1246
+ "note": null
1247
+ },
1248
+ {
1249
+ "name": "onConfirm",
1250
+ "takes": "a handler",
1251
+ "required": true,
1252
+ "note": null
1253
+ },
1254
+ {
1255
+ "name": "onClose",
1256
+ "takes": "a handler",
1257
+ "required": true,
1258
+ "note": null
1259
+ }
1260
+ ],
1261
+ "variants": [],
1262
+ "ownsBehaviours": [
1263
+ {
1264
+ "id": "base-ui",
1265
+ "behaviour": "Is built on Base UI"
1266
+ },
1267
+ {
1268
+ "id": "portal",
1269
+ "behaviour": "Floats on top of the page"
1270
+ },
1271
+ {
1272
+ "id": "role",
1273
+ "behaviour": "Says what it is to assistive technology"
1274
+ }
1275
+ ],
1276
+ "status": "stable",
1277
+ "migrationStage": null,
1278
+ "docsId": "overlays-confirmdialog--docs",
1279
+ "storyId": "overlays-confirmdialog--destructive",
1280
+ "docPage": "src/ConfirmDialog.mdx"
1281
+ },
1282
+ {
1283
+ "name": "DialogShell",
1284
+ "repo": "estiva-ui",
1285
+ "kind": "component",
1286
+ "importPath": "@estiva-app/ui",
1287
+ "sourceFile": "src/DialogShell.tsx",
1288
+ "purpose": "The dialog, minus what it says: the portal, the backdrop, a 502px card, a 48px header with the title and a close button, a body, and a 48px footer for the buttons.",
1289
+ "purposeFrom": "page",
1290
+ "props": [
1291
+ {
1292
+ "name": "title",
1293
+ "takes": "text",
1294
+ "required": true,
1295
+ "note": "Labels the dialog for assistive tech, and renders as the header text unless `headerContent` replaces it."
1296
+ },
1297
+ {
1298
+ "name": "onClose",
1299
+ "takes": "a handler",
1300
+ "required": true,
1301
+ "note": null
1302
+ },
1303
+ {
1304
+ "name": "headerContent",
1305
+ "takes": "anything",
1306
+ "required": false,
1307
+ "note": "Replaces the title text in the header — a back button beside the title, a count chip after it."
1308
+ },
1309
+ {
1310
+ "name": "footer",
1311
+ "takes": "anything",
1312
+ "required": false,
1313
+ "note": "Absent: no footer row, and the body keeps the card's own bottom edge (a roster that simply ends)."
1314
+ },
1315
+ {
1316
+ "name": "children",
1317
+ "takes": "anything",
1318
+ "required": true,
1319
+ "note": null
1320
+ },
1321
+ {
1322
+ "name": "bodyClassName",
1323
+ "takes": "text",
1324
+ "required": false,
1325
+ "note": "Extra classes on the body: its layout and any padding override (`flex flex-col gap-6`, `p-0 py-2`)."
1326
+ },
1327
+ {
1328
+ "name": "bodyMaxHeight",
1329
+ "takes": "text",
1330
+ "required": false,
1331
+ "note": "How tall the body may get before it scrolls, as the cap class — `max-h-[400px]`, `max-h-[70vh]`."
1332
+ },
1333
+ {
1334
+ "name": "width",
1335
+ "takes": "number",
1336
+ "required": false,
1337
+ "note": null
1338
+ },
1339
+ {
1340
+ "name": "alert",
1341
+ "takes": "true/false",
1342
+ "required": false,
1343
+ "note": "A question that has to be answered rather than clicked away: a press on the backdrop no longer closes it, and it announces itself as an alert."
1344
+ }
1345
+ ],
1346
+ "variants": [],
1347
+ "ownsBehaviours": [
1348
+ {
1349
+ "id": "base-ui",
1350
+ "behaviour": "Is built on Base UI"
1351
+ },
1352
+ {
1353
+ "id": "portal",
1354
+ "behaviour": "Floats on top of the page"
1355
+ },
1356
+ {
1357
+ "id": "press-outside",
1358
+ "behaviour": "Closes on a press outside"
1359
+ },
1360
+ {
1361
+ "id": "page-keys",
1362
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
1363
+ },
1364
+ {
1365
+ "id": "focus",
1366
+ "behaviour": "Holds focus inside while open, and gives it back"
1367
+ },
1368
+ {
1369
+ "id": "scroll-lock",
1370
+ "behaviour": "Stops the page behind it scrolling"
1371
+ },
1372
+ {
1373
+ "id": "role",
1374
+ "behaviour": "Says what it is to assistive technology"
1375
+ }
1376
+ ],
1377
+ "status": "stable",
1378
+ "migrationStage": null,
1379
+ "docsId": "overlays-dialogshell--docs",
1380
+ "storyId": "overlays-dialogshell--default",
1381
+ "docPage": "src/DialogShell.mdx"
1382
+ },
1383
+ {
1384
+ "name": "Divider",
1385
+ "repo": "estiva-ui",
1386
+ "kind": "component",
1387
+ "importPath": "@estiva-app/ui",
1388
+ "sourceFile": "src/Divider.tsx",
1389
+ "purpose": "A hairline in `border-subtle`. Horizontal it is inset 12px each side; `orientation=\"vertical\"` stands it up to its row's height, no inset.",
1390
+ "purposeFrom": "page",
1391
+ "props": [
1392
+ {
1393
+ "name": "orientation",
1394
+ "takes": "horizontal | vertical",
1395
+ "required": false,
1396
+ "note": null
1397
+ },
1398
+ {
1399
+ "name": "label",
1400
+ "takes": "text",
1401
+ "required": false,
1402
+ "note": "Words in the middle of the line — \"New since you last read this\", a date."
1403
+ },
1404
+ {
1405
+ "name": "tone",
1406
+ "takes": "default | warning",
1407
+ "required": false,
1408
+ "note": "`warning` for a line that asks for attention: the label in the warning colour, the lines in its wash."
1409
+ },
1410
+ {
1411
+ "name": "className",
1412
+ "takes": "text",
1413
+ "required": false,
1414
+ "note": null
1415
+ }
1416
+ ],
1417
+ "variants": [
1418
+ {
1419
+ "prop": "orientation",
1420
+ "values": [
1421
+ "horizontal",
1422
+ "vertical"
1423
+ ]
1424
+ },
1425
+ {
1426
+ "prop": "tone",
1427
+ "values": [
1428
+ "default",
1429
+ "warning"
1430
+ ]
1431
+ }
1432
+ ],
1433
+ "ownsBehaviours": [
1434
+ {
1435
+ "id": "base-ui",
1436
+ "behaviour": "Is built on Base UI"
1437
+ },
1438
+ {
1439
+ "id": "role",
1440
+ "behaviour": "Says what it is to assistive technology"
1441
+ }
1442
+ ],
1443
+ "status": "stable",
1444
+ "migrationStage": null,
1445
+ "docsId": "primitives-divider--docs",
1446
+ "storyId": "primitives-divider--default",
1447
+ "docPage": "src/Divider.mdx"
1448
+ },
1449
+ {
1450
+ "name": "EditableText",
1451
+ "repo": "estiva-ui",
1452
+ "kind": "component",
1453
+ "importPath": "@estiva-app/ui",
1454
+ "sourceFile": "src/EditableText.tsx",
1455
+ "purpose": "Text you click to edit. It reads as text until clicked; then it is a field.",
1456
+ "purposeFrom": "page",
1457
+ "props": [
1458
+ {
1459
+ "name": "value",
1460
+ "takes": "text",
1461
+ "required": true,
1462
+ "note": null
1463
+ },
1464
+ {
1465
+ "name": "placeholder",
1466
+ "takes": "text",
1467
+ "required": true,
1468
+ "note": null
1469
+ },
1470
+ {
1471
+ "name": "onCommit",
1472
+ "takes": "a handler",
1473
+ "required": true,
1474
+ "note": "Resolve `true` when saved; `false` (or throw) keeps the field open with the text."
1475
+ },
1476
+ {
1477
+ "name": "multiline",
1478
+ "takes": "true/false",
1479
+ "required": false,
1480
+ "note": null
1481
+ },
1482
+ {
1483
+ "name": "className",
1484
+ "takes": "text",
1485
+ "required": false,
1486
+ "note": "Applied to both the text and the field, so they are the same size."
1487
+ },
1488
+ {
1489
+ "name": "label",
1490
+ "takes": "text",
1491
+ "required": true,
1492
+ "note": "The accessible name of the field — \"Title\", \"Description\"."
1493
+ },
1494
+ {
1495
+ "name": "display",
1496
+ "takes": "text",
1497
+ "required": false,
1498
+ "note": "What to *show* when not editing, when that differs from what is edited — a value carrying a raw reference that the caller renders as a live object below the text, say."
1499
+ },
1500
+ {
1501
+ "name": "displayNode",
1502
+ "takes": "anything",
1503
+ "required": false,
1504
+ "note": "What to *draw* when not editing, when the value is structured rather than a line of prose."
1505
+ },
1506
+ {
1507
+ "name": "readOnly",
1508
+ "takes": "true/false",
1509
+ "required": false,
1510
+ "note": "Show the value only — no edit affordance."
1511
+ }
1512
+ ],
1513
+ "variants": [],
1514
+ "ownsBehaviours": [],
1515
+ "status": "stable",
1516
+ "migrationStage": null,
1517
+ "docsId": "inputs-editabletext--docs",
1518
+ "storyId": "inputs-editabletext--title",
1519
+ "docPage": "src/EditableText.mdx"
1520
+ },
1521
+ {
1522
+ "name": "EmptyState",
1523
+ "repo": "estiva-ui",
1524
+ "kind": "component",
1525
+ "importPath": "@estiva-app/ui",
1526
+ "sourceFile": "src/EmptyState.tsx",
1527
+ "purpose": "The place where content will be once there is some, in two manners: a 16px icon over a centred line when the whole page is empty, the line alone and left-aligned when one section of a page is.",
1528
+ "purposeFrom": "page",
1529
+ "props": [
1530
+ {
1531
+ "name": "icon",
1532
+ "takes": "anything",
1533
+ "required": false,
1534
+ "note": "16px, stroke 1.5. A speech bubble when absent."
1535
+ },
1536
+ {
1537
+ "name": "message",
1538
+ "takes": "text",
1539
+ "required": true,
1540
+ "note": null
1541
+ },
1542
+ {
1543
+ "name": "scope",
1544
+ "takes": "page | section",
1545
+ "required": false,
1546
+ "note": "`page` when the whole page is empty; `section` when one part of it is."
1547
+ },
1548
+ {
1549
+ "name": "className",
1550
+ "takes": "text",
1551
+ "required": false,
1552
+ "note": null
1553
+ }
1554
+ ],
1555
+ "variants": [
1556
+ {
1557
+ "prop": "scope",
1558
+ "values": [
1559
+ "page",
1560
+ "section"
1561
+ ]
1562
+ }
1563
+ ],
1564
+ "ownsBehaviours": [],
1565
+ "status": "stable",
1566
+ "migrationStage": null,
1567
+ "docsId": "feedback-emptystate--docs",
1568
+ "storyId": "feedback-emptystate--page",
1569
+ "docPage": "src/EmptyState.mdx"
1570
+ },
1571
+ {
1572
+ "name": "EnterHint",
1573
+ "repo": "estiva-ui",
1574
+ "kind": "component",
1575
+ "importPath": "@estiva-app/ui",
1576
+ "sourceFile": "src/Menu.tsx",
1577
+ "purpose": "The keyboard hint a picker row shows while highlighted — hand-rolled in five files before this (2026-09-01), and drawn as its own thing until 2026-09-05, when it became the `Kbd` chip every other key hint uses.",
1578
+ "purposeFrom": "comment",
1579
+ "props": [
1580
+ {
1581
+ "name": "target",
1582
+ "takes": "text",
1583
+ "required": false,
1584
+ "note": null
1585
+ }
1586
+ ],
1587
+ "variants": [],
1588
+ "ownsBehaviours": [],
1589
+ "status": "stable",
1590
+ "migrationStage": null,
1591
+ "docsId": "overlays-menu--docs",
1592
+ "storyId": "overlays-menu--items",
1593
+ "docPage": null
1594
+ },
1595
+ {
1596
+ "name": "Field",
1597
+ "repo": "estiva-ui",
1598
+ "kind": "component",
1599
+ "importPath": "@estiva-app/ui",
1600
+ "sourceFile": "src/Field.tsx",
1601
+ "purpose": "A label over a control — the form row. The label is the `input-label` token; `required` marks it with the error-coloured asterisk.",
1602
+ "purposeFrom": "page",
1603
+ "props": [
1604
+ {
1605
+ "name": "label",
1606
+ "takes": "text",
1607
+ "required": true,
1608
+ "note": null
1609
+ },
1610
+ {
1611
+ "name": "required",
1612
+ "takes": "true/false",
1613
+ "required": false,
1614
+ "note": "Draws the asterisk and marks the control `aria-required`, so the mark means something to a reader who cannot see it."
1615
+ },
1616
+ {
1617
+ "name": "helper",
1618
+ "takes": "text",
1619
+ "required": false,
1620
+ "note": "A hint under the control — what the format is, what happens if it is left empty."
1621
+ },
1622
+ {
1623
+ "name": "error",
1624
+ "takes": "text",
1625
+ "required": false,
1626
+ "note": "What is wrong, in the same place as the helper and in the error colour."
1627
+ },
1628
+ {
1629
+ "name": "children",
1630
+ "takes": "anything",
1631
+ "required": true,
1632
+ "note": null
1633
+ }
1634
+ ],
1635
+ "variants": [],
1636
+ "ownsBehaviours": [
1637
+ {
1638
+ "id": "base-ui",
1639
+ "behaviour": "Is built on Base UI"
1640
+ }
1641
+ ],
1642
+ "status": "stable",
1643
+ "migrationStage": null,
1644
+ "docsId": "inputs-field--docs",
1645
+ "storyId": "inputs-field--default",
1646
+ "docPage": "src/Field.mdx"
1647
+ },
1648
+ {
1649
+ "name": "FieldLine",
1650
+ "repo": "estiva-ui",
1651
+ "kind": "component",
1652
+ "importPath": "@estiva-app/ui",
1653
+ "sourceFile": "src/Field.tsx",
1654
+ "purpose": "The small line a Field draws under a control — on its own, for the places where there is no single control to draw it under.",
1655
+ "purposeFrom": "page",
1656
+ "props": [
1657
+ {
1658
+ "name": "tone",
1659
+ "takes": "helper | warning | error",
1660
+ "required": false,
1661
+ "note": "`helper` (muted) is a hint; `warning` (amber) and `error` (red) are outcomes."
1662
+ },
1663
+ {
1664
+ "name": "children",
1665
+ "takes": "anything",
1666
+ "required": true,
1667
+ "note": null
1668
+ },
1669
+ {
1670
+ "name": "className",
1671
+ "takes": "text",
1672
+ "required": false,
1673
+ "note": null
1674
+ }
1675
+ ],
1676
+ "variants": [
1677
+ {
1678
+ "prop": "tone",
1679
+ "values": [
1680
+ "helper",
1681
+ "warning",
1682
+ "error"
1683
+ ]
1684
+ }
1685
+ ],
1686
+ "ownsBehaviours": [
1687
+ {
1688
+ "id": "role",
1689
+ "behaviour": "Says what it is to assistive technology"
1690
+ }
1691
+ ],
1692
+ "status": "stable",
1693
+ "migrationStage": null,
1694
+ "docsId": "inputs-field-line--docs",
1695
+ "storyId": "inputs-field-line--helper",
1696
+ "docPage": "src/FieldLine.mdx"
1697
+ },
1698
+ {
1699
+ "name": "FilePicker",
1700
+ "repo": "estiva-ui",
1701
+ "kind": "component",
1702
+ "importPath": "@estiva-app/ui",
1703
+ "sourceFile": "src/FilePicker.tsx",
1704
+ "purpose": "The browser's file picker, with nothing drawn.",
1705
+ "purposeFrom": "page",
1706
+ "props": [
1707
+ {
1708
+ "name": "onPick",
1709
+ "takes": "a handler",
1710
+ "required": true,
1711
+ "note": "The chosen files, in the order the picker gave them."
1712
+ }
1713
+ ],
1714
+ "variants": [],
1715
+ "ownsBehaviours": [],
1716
+ "status": "stable",
1717
+ "migrationStage": null,
1718
+ "docsId": "inputs-filepicker--docs",
1719
+ "storyId": "inputs-filepicker--default",
1720
+ "docPage": "src/FilePicker.mdx"
1721
+ },
1722
+ {
1723
+ "name": "Form",
1724
+ "repo": "estiva-ui",
1725
+ "kind": "component",
1726
+ "importPath": "@estiva-app/ui",
1727
+ "sourceFile": "src/Form.tsx",
1728
+ "purpose": "The fields and the button that sends them.",
1729
+ "purposeFrom": "page",
1730
+ "props": [
1731
+ {
1732
+ "name": "onSubmit",
1733
+ "takes": "a handler",
1734
+ "required": true,
1735
+ "note": "Enter in a field, or a submit button. The page's own submit is already prevented."
1736
+ },
1737
+ {
1738
+ "name": "busy",
1739
+ "takes": "true/false",
1740
+ "required": false,
1741
+ "note": "While sending: every field and button inside is switched off, and focus waits on the form."
1742
+ },
1743
+ {
1744
+ "name": "enterSends",
1745
+ "takes": "true/false",
1746
+ "required": false,
1747
+ "note": "Whether Enter in a one-line field sends."
1748
+ },
1749
+ {
1750
+ "name": "children",
1751
+ "takes": "anything",
1752
+ "required": true,
1753
+ "note": null
1754
+ }
1755
+ ],
1756
+ "variants": [],
1757
+ "ownsBehaviours": [
1758
+ {
1759
+ "id": "base-ui",
1760
+ "behaviour": "Is built on Base UI"
1761
+ }
1762
+ ],
1763
+ "status": "stable",
1764
+ "migrationStage": null,
1765
+ "docsId": "inputs-form--docs",
1766
+ "storyId": "inputs-form--default",
1767
+ "docPage": "src/Form.mdx"
1768
+ },
1769
+ {
1770
+ "name": "hueFor",
1771
+ "repo": "estiva-ui",
1772
+ "kind": "helper",
1773
+ "importPath": "@estiva-app/ui",
1774
+ "sourceFile": "src/Avatar.tsx",
1775
+ "purpose": "The colour a person's initials sit on, chosen from a key: the same key always gives the same hue, so a face reads as theirs in every app.",
1776
+ "purposeFrom": "comment",
1777
+ "props": [],
1778
+ "variants": [],
1779
+ "ownsBehaviours": [],
1780
+ "status": "stable",
1781
+ "migrationStage": null,
1782
+ "docsId": "primitives-avatar--docs",
1783
+ "storyId": "primitives-avatar--initials",
1784
+ "docPage": null
1785
+ },
1786
+ {
1787
+ "name": "IconButton",
1788
+ "repo": "estiva-ui",
1789
+ "kind": "component",
1790
+ "importPath": "@estiva-app/ui",
1791
+ "sourceFile": "src/IconButton.tsx",
1792
+ "purpose": "A square button around a 16px icon: 4px padding, 8px radius, three variants.",
1793
+ "purposeFrom": "page",
1794
+ "props": [
1795
+ {
1796
+ "name": "variant",
1797
+ "takes": "muted | outlined | primary | current | resolve",
1798
+ "required": false,
1799
+ "note": "`current` takes the colour of what it sits in — the ✕ on a `Banner` wears the banner's tone."
1800
+ },
1801
+ {
1802
+ "name": "pressed",
1803
+ "takes": "true/false",
1804
+ "required": false,
1805
+ "note": "On, like a Bold button while the selection is bold: the active fill, and `aria-pressed`."
1806
+ },
1807
+ {
1808
+ "name": "glow",
1809
+ "takes": "true/false",
1810
+ "required": false,
1811
+ "note": "A glow in Signal — the send arrow while there is something to send."
1812
+ },
1813
+ {
1814
+ "name": "tooltip",
1815
+ "takes": "text",
1816
+ "required": false,
1817
+ "note": null
1818
+ },
1819
+ {
1820
+ "name": "tooltipShortcut",
1821
+ "takes": "text",
1822
+ "required": false,
1823
+ "note": "A key hint drawn as the `Kbd` chip inside the tooltip — for a button whose only other affordance is a keyboard shortcut."
1824
+ },
1825
+ {
1826
+ "name": "tooltipPlacement",
1827
+ "takes": "top | bottom",
1828
+ "required": false,
1829
+ "note": null
1830
+ },
1831
+ {
1832
+ "name": "disabledReason",
1833
+ "takes": "text",
1834
+ "required": false,
1835
+ "note": "Why the action cannot succeed right now."
1836
+ },
1837
+ {
1838
+ "name": "children",
1839
+ "takes": "anything",
1840
+ "required": true,
1841
+ "note": "The icon: 16px, stroke 1.5."
1842
+ }
1843
+ ],
1844
+ "variants": [
1845
+ {
1846
+ "prop": "variant",
1847
+ "values": [
1848
+ "muted",
1849
+ "outlined",
1850
+ "primary",
1851
+ "current",
1852
+ "resolve"
1853
+ ]
1854
+ },
1855
+ {
1856
+ "prop": "tooltipPlacement",
1857
+ "values": [
1858
+ "top",
1859
+ "bottom"
1860
+ ]
1861
+ }
1862
+ ],
1863
+ "ownsBehaviours": [
1864
+ {
1865
+ "id": "base-ui",
1866
+ "behaviour": "Is built on Base UI"
1867
+ },
1868
+ {
1869
+ "id": "role",
1870
+ "behaviour": "Says what it is to assistive technology"
1871
+ },
1872
+ {
1873
+ "id": "tab-stop",
1874
+ "behaviour": "Is reachable with Tab"
1875
+ }
1876
+ ],
1877
+ "status": "stable",
1878
+ "migrationStage": null,
1879
+ "docsId": "primitives-iconbutton--docs",
1880
+ "storyId": "primitives-iconbutton--muted",
1881
+ "docPage": "src/IconButton.mdx"
1882
+ },
1883
+ {
1884
+ "name": "IdentityMenu",
1885
+ "repo": "estiva-ui",
1886
+ "kind": "component",
1887
+ "importPath": "@estiva-app/ui",
1888
+ "sourceFile": "src/IdentityMenu.tsx",
1889
+ "purpose": "Who you are, and where you are: the identity trigger for a top bar, and the menu it opens — ready-made, because every app needs one and it is built of nothing but shared parts.",
1890
+ "purposeFrom": "page",
1891
+ "props": [
1892
+ {
1893
+ "name": "me",
1894
+ "takes": "Identity",
1895
+ "required": true,
1896
+ "note": null
1897
+ },
1898
+ {
1899
+ "name": "signedIn",
1900
+ "takes": "true/false",
1901
+ "required": true,
1902
+ "note": "Signed in through Estiva ID, as opposed to a browser-held key."
1903
+ },
1904
+ {
1905
+ "name": "relayUrl",
1906
+ "takes": "text",
1907
+ "required": false,
1908
+ "note": "Names the workspace; absent hides the workspace section."
1909
+ },
1910
+ {
1911
+ "name": "idBase",
1912
+ "takes": "text",
1913
+ "required": false,
1914
+ "note": "Estiva ID's base URL when this build offers sign-in; absent = anonymous-only build."
1915
+ },
1916
+ {
1917
+ "name": "onCopyKey",
1918
+ "takes": "a handler",
1919
+ "required": false,
1920
+ "note": "\"Copy public key\" appears only when the app can supply one."
1921
+ },
1922
+ {
1923
+ "name": "onSignOut",
1924
+ "takes": "a handler",
1925
+ "required": false,
1926
+ "note": null
1927
+ },
1928
+ {
1929
+ "name": "compact",
1930
+ "takes": "true/false",
1931
+ "required": false,
1932
+ "note": "Face-only trigger, 36px — no chevron, no name beside it."
1933
+ },
1934
+ {
1935
+ "name": "className",
1936
+ "takes": "text",
1937
+ "required": false,
1938
+ "note": null
1939
+ },
1940
+ {
1941
+ "name": "children",
1942
+ "takes": "anything",
1943
+ "required": false,
1944
+ "note": "App-specific rows, drawn as their own group between the workspace section and the actions."
1945
+ }
1946
+ ],
1947
+ "variants": [],
1948
+ "ownsBehaviours": [],
1949
+ "status": "stable",
1950
+ "migrationStage": null,
1951
+ "docsId": "navigation-identitymenu--docs",
1952
+ "storyId": "navigation-identitymenu--anonymous",
1953
+ "docPage": "src/IdentityMenu.mdx"
1954
+ },
1955
+ {
1956
+ "name": "IdentityPanel",
1957
+ "repo": "estiva-ui",
1958
+ "kind": "component",
1959
+ "importPath": "@estiva-app/ui",
1960
+ "sourceFile": "src/IdentityMenu.tsx",
1961
+ "purpose": "The identity rows on a panel of their own, with no menu around them — for a docs page, or anywhere the panel is already placed.",
1962
+ "purposeFrom": "comment",
1963
+ "props": [
1964
+ {
1965
+ "name": "onClose",
1966
+ "takes": "a handler",
1967
+ "required": false,
1968
+ "note": "Called when a row asks the menu to close."
1969
+ },
1970
+ {
1971
+ "name": "me",
1972
+ "takes": "Identity",
1973
+ "required": true,
1974
+ "note": null
1975
+ },
1976
+ {
1977
+ "name": "signedIn",
1978
+ "takes": "true/false",
1979
+ "required": true,
1980
+ "note": "Signed in through Estiva ID, as opposed to a browser-held key."
1981
+ },
1982
+ {
1983
+ "name": "relayUrl",
1984
+ "takes": "text",
1985
+ "required": false,
1986
+ "note": "Names the workspace; absent hides the workspace section."
1987
+ },
1988
+ {
1989
+ "name": "idBase",
1990
+ "takes": "text",
1991
+ "required": false,
1992
+ "note": "Estiva ID's base URL when this build offers sign-in; absent = anonymous-only build."
1993
+ },
1994
+ {
1995
+ "name": "onCopyKey",
1996
+ "takes": "a handler",
1997
+ "required": false,
1998
+ "note": "\"Copy public key\" appears only when the app can supply one."
1999
+ },
2000
+ {
2001
+ "name": "onSignOut",
2002
+ "takes": "a handler",
2003
+ "required": false,
2004
+ "note": null
2005
+ },
2006
+ {
2007
+ "name": "className",
2008
+ "takes": "text",
2009
+ "required": false,
2010
+ "note": null
2011
+ },
2012
+ {
2013
+ "name": "children",
2014
+ "takes": "anything",
2015
+ "required": false,
2016
+ "note": "App-specific rows, drawn as their own group between the workspace section and the actions."
2017
+ }
2018
+ ],
2019
+ "variants": [],
2020
+ "ownsBehaviours": [],
2021
+ "status": "stable",
2022
+ "migrationStage": null,
2023
+ "docsId": "navigation-identitymenu--docs",
2024
+ "storyId": "navigation-identitymenu--anonymous",
2025
+ "docPage": null
2026
+ },
2027
+ {
2028
+ "name": "initialsFor",
2029
+ "repo": "estiva-ui",
2030
+ "kind": "helper",
2031
+ "importPath": "@estiva-app/ui",
2032
+ "sourceFile": "src/Avatar.tsx",
2033
+ "purpose": "Peek's rule, sharpened: the first letter of the first two words — counting only words that begin with a letter or digit, so \"Claude (steered by Katerina Kelepouri)\" shows \"C\", never \"C(\" (Katerina, 2026-09-01: a name carrying such symbols gets a single letter rather than one of them).",
2034
+ "purposeFrom": "comment",
2035
+ "props": [],
2036
+ "variants": [],
2037
+ "ownsBehaviours": [],
2038
+ "status": "stable",
2039
+ "migrationStage": null,
2040
+ "docsId": "primitives-avatar--docs",
2041
+ "storyId": "primitives-avatar--initials",
2042
+ "docPage": null
2043
+ },
2044
+ {
2045
+ "name": "INLINE_CHIP_CLASSES",
2046
+ "repo": "estiva-ui",
2047
+ "kind": "helper",
2048
+ "importPath": "@estiva-app/ui",
2049
+ "sourceFile": "src/InlineChip.tsx",
2050
+ "purpose": "The shape every tone shares. Exported for a rich-text editor that renders chips from strings.",
2051
+ "purposeFrom": "comment",
2052
+ "props": [],
2053
+ "variants": [],
2054
+ "ownsBehaviours": [],
2055
+ "status": "stable",
2056
+ "migrationStage": null,
2057
+ "docsId": "components-inlinechip--docs",
2058
+ "storyId": "components-inlinechip--neutral",
2059
+ "docPage": null
2060
+ },
2061
+ {
2062
+ "name": "INLINE_CHIP_TONE_CLASSES",
2063
+ "repo": "estiva-ui",
2064
+ "kind": "helper",
2065
+ "importPath": "@estiva-app/ui",
2066
+ "sourceFile": "src/InlineChip.tsx",
2067
+ "purpose": "What a chip is made of, by what it stands for.",
2068
+ "purposeFrom": "comment",
2069
+ "props": [],
2070
+ "variants": [],
2071
+ "ownsBehaviours": [],
2072
+ "status": "stable",
2073
+ "migrationStage": null,
2074
+ "docsId": "components-inlinechip--docs",
2075
+ "storyId": "components-inlinechip--neutral",
2076
+ "docPage": null
2077
+ },
2078
+ {
2079
+ "name": "InlineChip",
2080
+ "repo": "estiva-ui",
2081
+ "kind": "component",
2082
+ "importPath": "@estiva-app/ui",
2083
+ "sourceFile": "src/InlineChip.tsx",
2084
+ "purpose": "A word in a sentence that stands for something — a person, a place, a thing — drawn as a small tinted box exactly one line high, with its words level with the text around it.",
2085
+ "purposeFrom": "page",
2086
+ "props": [
2087
+ {
2088
+ "name": "tone",
2089
+ "takes": "InlineChipTone",
2090
+ "required": false,
2091
+ "note": "What the chip stands for. Default `neutral`."
2092
+ },
2093
+ {
2094
+ "name": "icon",
2095
+ "takes": "anything",
2096
+ "required": false,
2097
+ "note": "Drawn before the label in a 16px box: a 16px icon, or a 14px one it centres."
2098
+ },
2099
+ {
2100
+ "name": "href",
2101
+ "takes": "text",
2102
+ "required": false,
2103
+ "note": "Where the chip leads. With it the chip is an anchor; without it, a span."
2104
+ },
2105
+ {
2106
+ "name": "children",
2107
+ "takes": "anything",
2108
+ "required": true,
2109
+ "note": null
2110
+ }
2111
+ ],
2112
+ "variants": [],
2113
+ "ownsBehaviours": [],
2114
+ "status": "stable",
2115
+ "migrationStage": null,
2116
+ "docsId": "components-inlinechip--docs",
2117
+ "storyId": "components-inlinechip--neutral",
2118
+ "docPage": "src/InlineChip.mdx"
2119
+ },
2120
+ {
2121
+ "name": "inlineChipClassName",
2122
+ "repo": "estiva-ui",
2123
+ "kind": "helper",
2124
+ "importPath": "@estiva-app/ui",
2125
+ "sourceFile": "src/InlineChip.tsx",
2126
+ "purpose": "The chip's classes for a tone, with anything the caller adds.",
2127
+ "purposeFrom": "comment",
2128
+ "props": [],
2129
+ "variants": [],
2130
+ "ownsBehaviours": [],
2131
+ "status": "stable",
2132
+ "migrationStage": null,
2133
+ "docsId": "components-inlinechip--docs",
2134
+ "storyId": "components-inlinechip--neutral",
2135
+ "docPage": null
2136
+ },
2137
+ {
2138
+ "name": "InputChip",
2139
+ "repo": "estiva-ui",
2140
+ "kind": "component",
2141
+ "importPath": "@estiva-app/ui",
2142
+ "sourceFile": "src/ChipInput.tsx",
2143
+ "purpose": "A chip standing on its own: a label, an optional leading icon, an optional ✕.",
2144
+ "purposeFrom": "comment",
2145
+ "props": [
2146
+ {
2147
+ "name": "label",
2148
+ "takes": "text",
2149
+ "required": true,
2150
+ "note": null
2151
+ },
2152
+ {
2153
+ "name": "leading",
2154
+ "takes": "anything",
2155
+ "required": false,
2156
+ "note": "Before the label, 16px — an Avatar, an icon."
2157
+ },
2158
+ {
2159
+ "name": "onRemove",
2160
+ "takes": "a handler",
2161
+ "required": false,
2162
+ "note": "Draws the ✕; absent, the chip is display-only."
2163
+ },
2164
+ {
2165
+ "name": "removeLabel",
2166
+ "takes": "text",
2167
+ "required": false,
2168
+ "note": "The ✕'s name for a screen reader. `Remove <label>` when not given."
2169
+ },
2170
+ {
2171
+ "name": "truncate",
2172
+ "takes": "true/false",
2173
+ "required": false,
2174
+ "note": "Cut a long label with an ellipsis once the chip is capped, by a `max-w-*` on `className`."
2175
+ },
2176
+ {
2177
+ "name": "className",
2178
+ "takes": "text",
2179
+ "required": false,
2180
+ "note": null
2181
+ }
2182
+ ],
2183
+ "variants": [],
2184
+ "ownsBehaviours": [],
2185
+ "status": "stable",
2186
+ "migrationStage": null,
2187
+ "docsId": "inputs-chipinput--docs",
2188
+ "storyId": "inputs-chipinput--type-to-search",
2189
+ "docPage": null
2190
+ },
2191
+ {
2192
+ "name": "Kbd",
2193
+ "repo": "estiva-ui",
2194
+ "kind": "component",
2195
+ "importPath": "@estiva-app/ui",
2196
+ "sourceFile": "src/Kbd.tsx",
2197
+ "purpose": "The small chip that names the key which does the same thing.",
2198
+ "purposeFrom": "page",
2199
+ "props": [
2200
+ {
2201
+ "name": "children",
2202
+ "takes": "anything",
2203
+ "required": true,
2204
+ "note": null
2205
+ },
2206
+ {
2207
+ "name": "className",
2208
+ "takes": "text",
2209
+ "required": false,
2210
+ "note": null
2211
+ }
2212
+ ],
2213
+ "variants": [],
2214
+ "ownsBehaviours": [],
2215
+ "status": "stable",
2216
+ "migrationStage": null,
2217
+ "docsId": "primitives-kbd--docs",
2218
+ "storyId": "primitives-kbd--default",
2219
+ "docPage": "src/Kbd.mdx"
2220
+ },
2221
+ {
2222
+ "name": "Link",
2223
+ "repo": "estiva-ui",
2224
+ "kind": "component",
2225
+ "importPath": "@estiva-app/ui",
2226
+ "sourceFile": "src/Link.tsx",
2227
+ "purpose": "A link, in one of four looks. It is a real anchor with a real address, and the app decides how it navigates.",
2228
+ "purposeFrom": "page",
2229
+ "props": [
2230
+ {
2231
+ "name": "href",
2232
+ "takes": "text",
2233
+ "required": true,
2234
+ "note": null
2235
+ },
2236
+ {
2237
+ "name": "variant",
2238
+ "takes": "text | quiet | underlined | plain",
2239
+ "required": false,
2240
+ "note": "Default `text`."
2241
+ },
2242
+ {
2243
+ "name": "external",
2244
+ "takes": "true/false",
2245
+ "required": false,
2246
+ "note": "Another site, or another app: opens in a new tab, with `noopener noreferrer` so the page it opens cannot reach back into this one."
2247
+ },
2248
+ {
2249
+ "name": "truncate",
2250
+ "takes": "true/false",
2251
+ "required": false,
2252
+ "note": "One line, cut with an ellipsis when it does not fit — a title that is a link."
2253
+ },
2254
+ {
2255
+ "name": "children",
2256
+ "takes": "anything",
2257
+ "required": true,
2258
+ "note": null
2259
+ }
2260
+ ],
2261
+ "variants": [
2262
+ {
2263
+ "prop": "variant",
2264
+ "values": [
2265
+ "text",
2266
+ "quiet",
2267
+ "underlined",
2268
+ "plain"
2269
+ ]
2270
+ }
2271
+ ],
2272
+ "ownsBehaviours": [
2273
+ {
2274
+ "id": "role",
2275
+ "behaviour": "Says what it is to assistive technology"
2276
+ },
2277
+ {
2278
+ "id": "tab-stop",
2279
+ "behaviour": "Is reachable with Tab"
2280
+ }
2281
+ ],
2282
+ "status": "stable",
2283
+ "migrationStage": null,
2284
+ "docsId": "navigation-link--docs",
2285
+ "storyId": "navigation-link--text",
2286
+ "docPage": "src/Link.mdx"
2287
+ },
2288
+ {
2289
+ "name": "Menu",
2290
+ "repo": "estiva-ui",
2291
+ "kind": "component",
2292
+ "importPath": "@estiva-app/ui",
2293
+ "sourceFile": "src/Menu.tsx",
2294
+ "purpose": "A list of actions from a trigger. The menu owns the trigger, so a caller writes no open state, no placement and no dismiss — it hands over the control and the rows, and everything else is Base UI's.",
2295
+ "purposeFrom": "page",
2296
+ "props": [
2297
+ {
2298
+ "name": "trigger",
2299
+ "takes": "anything",
2300
+ "required": true,
2301
+ "note": "The control that opens the menu. Any element that forwards its ref and spreads its props — this package's `Button`, `IconButton` and `PersonTrigger` all do."
2302
+ },
2303
+ {
2304
+ "name": "align",
2305
+ "takes": "left | right",
2306
+ "required": false,
2307
+ "note": "Which of the menu's edges hangs from the trigger's."
2308
+ },
2309
+ {
2310
+ "name": "openOnHover",
2311
+ "takes": "true/false",
2312
+ "required": false,
2313
+ "note": "Open on hover, and close shortly after the pointer leaves — for a control that only appears while the pointer is on a card."
2314
+ },
2315
+ {
2316
+ "name": "open",
2317
+ "takes": "true/false",
2318
+ "required": false,
2319
+ "note": "Controlled, for a caller that must know or must force it."
2320
+ },
2321
+ {
2322
+ "name": "onOpenChange",
2323
+ "takes": "a handler",
2324
+ "required": false,
2325
+ "note": null
2326
+ },
2327
+ {
2328
+ "name": "actionsRef",
2329
+ "takes": "a handler",
2330
+ "required": false,
2331
+ "note": "Base UI's imperative handle. `actions.current?.close()` shuts the menu — for a row that must close it before opening what it opens."
2332
+ },
2333
+ {
2334
+ "name": "children",
2335
+ "takes": "anything",
2336
+ "required": true,
2337
+ "note": null
2338
+ },
2339
+ {
2340
+ "name": "className",
2341
+ "takes": "text",
2342
+ "required": false,
2343
+ "note": "On the menu's surface — its width. Not its padding: see `contentClassName`."
2344
+ },
2345
+ {
2346
+ "name": "contentClassName",
2347
+ "takes": "text",
2348
+ "required": false,
2349
+ "note": "The padding around the rows, as a class."
2350
+ }
2351
+ ],
2352
+ "variants": [
2353
+ {
2354
+ "prop": "align",
2355
+ "values": [
2356
+ "left",
2357
+ "right"
2358
+ ]
2359
+ }
2360
+ ],
2361
+ "ownsBehaviours": [
2362
+ {
2363
+ "id": "base-ui",
2364
+ "behaviour": "Is built on Base UI"
2365
+ },
2366
+ {
2367
+ "id": "portal",
2368
+ "behaviour": "Floats on top of the page"
2369
+ },
2370
+ {
2371
+ "id": "press-outside",
2372
+ "behaviour": "Closes on a press outside"
2373
+ },
2374
+ {
2375
+ "id": "page-keys",
2376
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
2377
+ },
2378
+ {
2379
+ "id": "follow",
2380
+ "behaviour": "Stays attached to its anchor on scroll and resize"
2381
+ },
2382
+ {
2383
+ "id": "walking",
2384
+ "behaviour": "Moves through its items with the arrow keys"
2385
+ },
2386
+ {
2387
+ "id": "role",
2388
+ "behaviour": "Says what it is to assistive technology"
2389
+ }
2390
+ ],
2391
+ "status": "stable",
2392
+ "migrationStage": null,
2393
+ "docsId": "overlays-menu--docs",
2394
+ "storyId": "overlays-menu--items",
2395
+ "docPage": "src/Menu.mdx"
2396
+ },
2397
+ {
2398
+ "name": "MenuItem",
2399
+ "repo": "estiva-ui",
2400
+ "kind": "component",
2401
+ "importPath": "@estiva-app/ui",
2402
+ "sourceFile": "src/Menu.tsx",
2403
+ "purpose": "The row of a menu: label, and around it everything a row can carry — a `leading` icon or face, a `description` second line, a `shortcut` kbd chip, a `submenu` chevron, a `trailing` anything (which wins over the other two), `destructive` in the error colour, `selected` as the fill.",
2404
+ "purposeFrom": "page",
2405
+ "props": [
2406
+ {
2407
+ "name": "label",
2408
+ "takes": "text",
2409
+ "required": false,
2410
+ "note": null
2411
+ },
2412
+ {
2413
+ "name": "children",
2414
+ "takes": "anything",
2415
+ "required": false,
2416
+ "note": "Replaces the label/description block — for rows whose middle is richer than text (the launcher's form rows)."
2417
+ },
2418
+ {
2419
+ "name": "size",
2420
+ "takes": "default | tall",
2421
+ "required": false,
2422
+ "note": "`tall` is the picker row — content height with a 40px floor, px-3, gap-3, room for a 32px face or icon tile and the description line."
2423
+ },
2424
+ {
2425
+ "name": "description",
2426
+ "takes": "text",
2427
+ "required": false,
2428
+ "note": "A second line under the label — a role, an address — 12px, secondary, truncating."
2429
+ },
2430
+ {
2431
+ "name": "leading",
2432
+ "takes": "anything",
2433
+ "required": false,
2434
+ "note": "Before the label: a 16px icon (stroke 1.5, secondary), or an Avatar, for rows led by a face."
2435
+ },
2436
+ {
2437
+ "name": "trailing",
2438
+ "takes": "anything",
2439
+ "required": false,
2440
+ "note": "At the right edge: a hint, a value — anything."
2441
+ },
2442
+ {
2443
+ "name": "hint",
2444
+ "takes": "anything",
2445
+ "required": false,
2446
+ "note": "Shown at the right edge only while this row is the one you are pointing at or have arrowed onto — an `EnterHint`, typically."
2447
+ },
2448
+ {
2449
+ "name": "shortcut",
2450
+ "takes": "text",
2451
+ "required": false,
2452
+ "note": "A keyboard hint, drawn as the kbd chip."
2453
+ },
2454
+ {
2455
+ "name": "submenu",
2456
+ "takes": "true/false",
2457
+ "required": false,
2458
+ "note": "The row opens another menu: draws the chevron at the right edge."
2459
+ },
2460
+ {
2461
+ "name": "destructive",
2462
+ "takes": "true/false",
2463
+ "required": false,
2464
+ "note": null
2465
+ },
2466
+ {
2467
+ "name": "selected",
2468
+ "takes": "true/false",
2469
+ "required": false,
2470
+ "note": "The row the menu currently points at (a submenu's chosen value)."
2471
+ }
2472
+ ],
2473
+ "variants": [
2474
+ {
2475
+ "prop": "size",
2476
+ "values": [
2477
+ "default",
2478
+ "tall"
2479
+ ]
2480
+ }
2481
+ ],
2482
+ "ownsBehaviours": [],
2483
+ "status": "stable",
2484
+ "migrationStage": null,
2485
+ "docsId": "overlays-menuitem--docs",
2486
+ "storyId": "overlays-menuitem--default",
2487
+ "docPage": "src/MenuItem.mdx"
2488
+ },
2489
+ {
2490
+ "name": "MenuPanel",
2491
+ "repo": "estiva-ui",
2492
+ "kind": "component",
2493
+ "importPath": "@estiva-app/ui",
2494
+ "sourceFile": "src/Menu.tsx",
2495
+ "purpose": "The menu's surface without the menu: the elevated box, the rows' padding, and a divider that runs the full width of what it separates.",
2496
+ "purposeFrom": "comment",
2497
+ "props": [
2498
+ {
2499
+ "name": "children",
2500
+ "takes": "anything",
2501
+ "required": false,
2502
+ "note": "Optional only because Base UI fills it in when this is a `render` target: `Menu.Popup` supplies the children."
2503
+ }
2504
+ ],
2505
+ "variants": [],
2506
+ "ownsBehaviours": [],
2507
+ "status": "stable",
2508
+ "migrationStage": null,
2509
+ "docsId": "overlays-menu--docs",
2510
+ "storyId": "overlays-menu--items",
2511
+ "docPage": null
2512
+ },
2513
+ {
2514
+ "name": "MenuRow",
2515
+ "repo": "estiva-ui",
2516
+ "kind": "component",
2517
+ "importPath": "@estiva-app/ui",
2518
+ "sourceFile": "src/Menu.tsx",
2519
+ "purpose": "A non-interactive row inside a menu, at the item's own geometry.",
2520
+ "purposeFrom": "comment",
2521
+ "props": [
2522
+ {
2523
+ "name": "children",
2524
+ "takes": "anything",
2525
+ "required": true,
2526
+ "note": null
2527
+ },
2528
+ {
2529
+ "name": "className",
2530
+ "takes": "text",
2531
+ "required": false,
2532
+ "note": null
2533
+ }
2534
+ ],
2535
+ "variants": [],
2536
+ "ownsBehaviours": [],
2537
+ "status": "stable",
2538
+ "migrationStage": null,
2539
+ "docsId": "overlays-menu--docs",
2540
+ "storyId": "overlays-menu--items",
2541
+ "docPage": null
2542
+ },
2543
+ {
2544
+ "name": "MenuSection",
2545
+ "repo": "estiva-ui",
2546
+ "kind": "component",
2547
+ "importPath": "@estiva-app/ui",
2548
+ "sourceFile": "src/Menu.tsx",
2549
+ "purpose": "A section heading inside a menu: the 32px row with a SectionLabel, read secondary — a heading inside a menu labels the rows, it is not one of them (Katerina, 2026-09-01).",
2550
+ "purposeFrom": "comment",
2551
+ "props": [
2552
+ {
2553
+ "name": "label",
2554
+ "takes": "text",
2555
+ "required": true,
2556
+ "note": null
2557
+ },
2558
+ {
2559
+ "name": "children",
2560
+ "takes": "anything",
2561
+ "required": true,
2562
+ "note": null
2563
+ },
2564
+ {
2565
+ "name": "className",
2566
+ "takes": "text",
2567
+ "required": false,
2568
+ "note": null
2569
+ }
2570
+ ],
2571
+ "variants": [],
2572
+ "ownsBehaviours": [],
2573
+ "status": "stable",
2574
+ "migrationStage": null,
2575
+ "docsId": "overlays-menu--docs",
2576
+ "storyId": "overlays-menu--items",
2577
+ "docPage": null
2578
+ },
2579
+ {
2580
+ "name": "MenuSub",
2581
+ "repo": "estiva-ui",
2582
+ "kind": "component",
2583
+ "importPath": "@estiva-app/ui",
2584
+ "sourceFile": "src/Menu.tsx",
2585
+ "purpose": "A row that opens another menu beside it; its rows are this row's children.",
2586
+ "purposeFrom": "comment",
2587
+ "props": [
2588
+ {
2589
+ "name": "label",
2590
+ "takes": "text",
2591
+ "required": true,
2592
+ "note": "The trigger row's label."
2593
+ },
2594
+ {
2595
+ "name": "leading",
2596
+ "takes": "anything",
2597
+ "required": false,
2598
+ "note": null
2599
+ },
2600
+ {
2601
+ "name": "selected",
2602
+ "takes": "true/false",
2603
+ "required": false,
2604
+ "note": "Mark the trigger row as holding a current value."
2605
+ },
2606
+ {
2607
+ "name": "children",
2608
+ "takes": "anything",
2609
+ "required": true,
2610
+ "note": "The submenu's rows."
2611
+ },
2612
+ {
2613
+ "name": "className",
2614
+ "takes": "text",
2615
+ "required": false,
2616
+ "note": "On the submenu panel."
2617
+ }
2618
+ ],
2619
+ "variants": [],
2620
+ "ownsBehaviours": [],
2621
+ "status": "stable",
2622
+ "migrationStage": null,
2623
+ "docsId": "overlays-menu--docs",
2624
+ "storyId": "overlays-menu--items",
2625
+ "docPage": null
2626
+ },
2627
+ {
2628
+ "name": "NavItem",
2629
+ "repo": "estiva-ui",
2630
+ "kind": "component",
2631
+ "importPath": "@estiva-app/ui",
2632
+ "sourceFile": "src/NavItem.tsx",
2633
+ "purpose": "One row of a sidebar: an optional 16px icon, a label, and an optional count — a muted mono number whose tooltip says what it counts.",
2634
+ "purposeFrom": "page",
2635
+ "props": [
2636
+ {
2637
+ "name": "label",
2638
+ "takes": "text",
2639
+ "required": true,
2640
+ "note": null
2641
+ },
2642
+ {
2643
+ "name": "href",
2644
+ "takes": "text",
2645
+ "required": true,
2646
+ "note": null
2647
+ },
2648
+ {
2649
+ "name": "count",
2650
+ "takes": "number",
2651
+ "required": false,
2652
+ "note": "`0` or absent renders no counter."
2653
+ },
2654
+ {
2655
+ "name": "countLabel",
2656
+ "takes": "text",
2657
+ "required": false,
2658
+ "note": "What the count counts, for the tooltip — \"18 open\", \"5 active\"."
2659
+ },
2660
+ {
2661
+ "name": "active",
2662
+ "takes": "true/false",
2663
+ "required": false,
2664
+ "note": null
2665
+ },
2666
+ {
2667
+ "name": "icon",
2668
+ "takes": "anything",
2669
+ "required": false,
2670
+ "note": "16px, stroke 1.5."
2671
+ },
2672
+ {
2673
+ "name": "className",
2674
+ "takes": "text",
2675
+ "required": false,
2676
+ "note": null
2677
+ }
2678
+ ],
2679
+ "variants": [],
2680
+ "ownsBehaviours": [],
2681
+ "status": "stable",
2682
+ "migrationStage": null,
2683
+ "docsId": "frame-navitem--docs",
2684
+ "storyId": "frame-navitem--default",
2685
+ "docPage": "src/NavItem.mdx"
2686
+ },
2687
+ {
2688
+ "name": "Person",
2689
+ "repo": "estiva-ui",
2690
+ "kind": "component",
2691
+ "importPath": "@estiva-app/ui",
2692
+ "sourceFile": "src/Person.tsx",
2693
+ "purpose": "A face beside a name — the inline mention of a human.",
2694
+ "purposeFrom": "page",
2695
+ "props": [
2696
+ {
2697
+ "name": "name",
2698
+ "takes": "text",
2699
+ "required": false,
2700
+ "note": null
2701
+ },
2702
+ {
2703
+ "name": "picture",
2704
+ "takes": "text",
2705
+ "required": false,
2706
+ "note": null
2707
+ },
2708
+ {
2709
+ "name": "fallback",
2710
+ "takes": "text",
2711
+ "required": false,
2712
+ "note": "Shown in place of a missing name."
2713
+ },
2714
+ {
2715
+ "name": "size",
2716
+ "takes": "number",
2717
+ "required": false,
2718
+ "note": null
2719
+ },
2720
+ {
2721
+ "name": "className",
2722
+ "takes": "text",
2723
+ "required": false,
2724
+ "note": null
2725
+ }
2726
+ ],
2727
+ "variants": [],
2728
+ "ownsBehaviours": [],
2729
+ "status": "stable",
2730
+ "migrationStage": null,
2731
+ "docsId": "components-person--docs",
2732
+ "storyId": "components-person--named",
2733
+ "docPage": "src/Person.mdx"
2734
+ },
2735
+ {
2736
+ "name": "PersonTrigger",
2737
+ "repo": "estiva-ui",
2738
+ "kind": "component",
2739
+ "importPath": "@estiva-app/ui",
2740
+ "sourceFile": "src/PersonTrigger.tsx",
2741
+ "purpose": "The person, as the button that opens a menu.",
2742
+ "purposeFrom": "page",
2743
+ "props": [
2744
+ {
2745
+ "name": "open",
2746
+ "takes": "true/false",
2747
+ "required": false,
2748
+ "note": "Whether what it opens is open — the row shape holds its hover fill while so."
2749
+ },
2750
+ {
2751
+ "name": "compact",
2752
+ "takes": "true/false",
2753
+ "required": false,
2754
+ "note": "Face only — no chevron, no hover fill. Defaults the face to 36px; the row shape to 22px."
2755
+ },
2756
+ {
2757
+ "name": "name",
2758
+ "takes": "text",
2759
+ "required": false,
2760
+ "note": null
2761
+ },
2762
+ {
2763
+ "name": "picture",
2764
+ "takes": "text",
2765
+ "required": false,
2766
+ "note": null
2767
+ },
2768
+ {
2769
+ "name": "fallback",
2770
+ "takes": "text",
2771
+ "required": false,
2772
+ "note": "Shown in place of a missing name."
2773
+ },
2774
+ {
2775
+ "name": "size",
2776
+ "takes": "number",
2777
+ "required": false,
2778
+ "note": null
2779
+ }
2780
+ ],
2781
+ "variants": [],
2782
+ "ownsBehaviours": [],
2783
+ "status": "stable",
2784
+ "migrationStage": null,
2785
+ "docsId": "components-persontrigger--docs",
2786
+ "storyId": "components-persontrigger--row",
2787
+ "docPage": "src/PersonTrigger.mdx"
2788
+ },
2789
+ {
2790
+ "name": "Popover",
2791
+ "repo": "estiva-ui",
2792
+ "kind": "component",
2793
+ "importPath": "@estiva-app/ui",
2794
+ "sourceFile": "src/Popover.tsx",
2795
+ "purpose": "A floating panel from a trigger: the same elevated surface a Menu draws, with none of a menu's semantics.",
2796
+ "purposeFrom": "page",
2797
+ "props": [
2798
+ {
2799
+ "name": "trigger",
2800
+ "takes": "anything",
2801
+ "required": false,
2802
+ "note": "The control that opens the panel. Any element that forwards its ref and spreads its props — this package's `Button`, `IconButton` and `PersonTrigger` all do."
2803
+ },
2804
+ {
2805
+ "name": "anchor",
2806
+ "takes": "HTMLElement | DOMRect | null",
2807
+ "required": false,
2808
+ "note": "For a panel with no trigger element: an element, or a rect the caller measured — a text selection's."
2809
+ },
2810
+ {
2811
+ "name": "align",
2812
+ "takes": "left | center | right",
2813
+ "required": false,
2814
+ "note": "Which of the panel's edges hangs from the trigger's, or `center` to put the panel's middle over the anchor's."
2815
+ },
2816
+ {
2817
+ "name": "side",
2818
+ "takes": "top | bottom",
2819
+ "required": false,
2820
+ "note": "Which side of the trigger, or of the anchor, the panel prefers."
2821
+ },
2822
+ {
2823
+ "name": "open",
2824
+ "takes": "true/false",
2825
+ "required": false,
2826
+ "note": "Controlled, for a caller that must know or must force it."
2827
+ },
2828
+ {
2829
+ "name": "onOpenChange",
2830
+ "takes": "a handler",
2831
+ "required": false,
2832
+ "note": null
2833
+ },
2834
+ {
2835
+ "name": "finalFocus",
2836
+ "takes": "RefObject<HTMLElement | null>",
2837
+ "required": false,
2838
+ "note": "Where focus goes when the panel closes. With a `trigger` it goes back to the trigger and this is not needed."
2839
+ },
2840
+ {
2841
+ "name": "actionsRef",
2842
+ "takes": "a handler",
2843
+ "required": false,
2844
+ "note": "Base UI's imperative handle. `actions.current?.close()` shuts the panel — for the Cancel and Save buttons a form panel ends with."
2845
+ },
2846
+ {
2847
+ "name": "ariaLabel",
2848
+ "takes": "text",
2849
+ "required": false,
2850
+ "note": "Names the panel for assistive tech. A panel with a visible heading can point at it instead, with `aria-labelledby`."
2851
+ },
2852
+ {
2853
+ "name": "children",
2854
+ "takes": "anything",
2855
+ "required": true,
2856
+ "note": null
2857
+ },
2858
+ {
2859
+ "name": "className",
2860
+ "takes": "text",
2861
+ "required": false,
2862
+ "note": "On the panel's surface — its width. Not its padding: see `contentClassName`."
2863
+ },
2864
+ {
2865
+ "name": "contentClassName",
2866
+ "takes": "text",
2867
+ "required": false,
2868
+ "note": "The padding around the children, as a class."
2869
+ },
2870
+ {
2871
+ "name": "maxHeight",
2872
+ "takes": "text",
2873
+ "required": false,
2874
+ "note": "A cap on the scrolling box, as a class — `max-h-[360px]`."
2875
+ }
2876
+ ],
2877
+ "variants": [
2878
+ {
2879
+ "prop": "align",
2880
+ "values": [
2881
+ "left",
2882
+ "center",
2883
+ "right"
2884
+ ]
2885
+ },
2886
+ {
2887
+ "prop": "side",
2888
+ "values": [
2889
+ "top",
2890
+ "bottom"
2891
+ ]
2892
+ }
2893
+ ],
2894
+ "ownsBehaviours": [
2895
+ {
2896
+ "id": "base-ui",
2897
+ "behaviour": "Is built on Base UI"
2898
+ },
2899
+ {
2900
+ "id": "portal",
2901
+ "behaviour": "Floats on top of the page"
2902
+ },
2903
+ {
2904
+ "id": "press-outside",
2905
+ "behaviour": "Closes on a press outside"
2906
+ },
2907
+ {
2908
+ "id": "page-keys",
2909
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
2910
+ },
2911
+ {
2912
+ "id": "follow",
2913
+ "behaviour": "Stays attached to its anchor on scroll and resize"
2914
+ }
2915
+ ],
2916
+ "status": "stable",
2917
+ "migrationStage": null,
2918
+ "docsId": "overlays-popover--docs",
2919
+ "storyId": "overlays-popover--default",
2920
+ "docPage": "src/Popover.mdx"
2921
+ },
2922
+ {
2923
+ "name": "PreviewCard",
2924
+ "repo": "estiva-ui",
2925
+ "kind": "component",
2926
+ "importPath": "@estiva-app/ui",
2927
+ "sourceFile": "src/PreviewCard.tsx",
2928
+ "purpose": "More of a thing, on hover.",
2929
+ "purposeFrom": "page",
2930
+ "props": [
2931
+ {
2932
+ "name": "content",
2933
+ "takes": "anything",
2934
+ "required": true,
2935
+ "note": "What the card holds. Rendered only while it is open."
2936
+ },
2937
+ {
2938
+ "name": "children",
2939
+ "takes": "anything",
2940
+ "required": true,
2941
+ "note": "The row, name or avatar the card previews."
2942
+ },
2943
+ {
2944
+ "name": "side",
2945
+ "takes": "top | bottom | left | right",
2946
+ "required": false,
2947
+ "note": "Which side of the trigger to prefer. It flips when that side has no room."
2948
+ },
2949
+ {
2950
+ "name": "delay",
2951
+ "takes": "number",
2952
+ "required": false,
2953
+ "note": "Before it opens, in ms. Long enough that crossing a list does not flash a card at every row."
2954
+ },
2955
+ {
2956
+ "name": "closeDelay",
2957
+ "takes": "number",
2958
+ "required": false,
2959
+ "note": "After the pointer leaves, in ms — the grace that lets you cross the gap into the card."
2960
+ },
2961
+ {
2962
+ "name": "className",
2963
+ "takes": "text",
2964
+ "required": false,
2965
+ "note": "On the card's surface: its width, its padding, a max height."
2966
+ },
2967
+ {
2968
+ "name": "wrapperClassName",
2969
+ "takes": "text",
2970
+ "required": false,
2971
+ "note": "Extra classes on the trigger wrapper — e.g."
2972
+ }
2973
+ ],
2974
+ "variants": [
2975
+ {
2976
+ "prop": "side",
2977
+ "values": [
2978
+ "top",
2979
+ "bottom",
2980
+ "left",
2981
+ "right"
2982
+ ]
2983
+ }
2984
+ ],
2985
+ "ownsBehaviours": [
2986
+ {
2987
+ "id": "base-ui",
2988
+ "behaviour": "Is built on Base UI"
2989
+ },
2990
+ {
2991
+ "id": "portal",
2992
+ "behaviour": "Floats on top of the page"
2993
+ },
2994
+ {
2995
+ "id": "press-outside",
2996
+ "behaviour": "Closes on a press outside"
2997
+ },
2998
+ {
2999
+ "id": "follow",
3000
+ "behaviour": "Stays attached to its anchor on scroll and resize"
3001
+ }
3002
+ ],
3003
+ "status": "stable",
3004
+ "migrationStage": null,
3005
+ "docsId": "overlays-previewcard--docs",
3006
+ "storyId": "overlays-previewcard--default",
3007
+ "docPage": "src/PreviewCard.mdx"
3008
+ },
3009
+ {
3010
+ "name": "ProgressBar",
3011
+ "repo": "estiva-ui",
3012
+ "kind": "component",
3013
+ "importPath": "@estiva-app/ui",
3014
+ "sourceFile": "src/ProgressBar.tsx",
3015
+ "purpose": "How much of something is done: a thin rounded track with a success-coloured fill.",
3016
+ "purposeFrom": "page",
3017
+ "props": [
3018
+ {
3019
+ "name": "value",
3020
+ "takes": "number",
3021
+ "required": true,
3022
+ "note": "How many are done."
3023
+ },
3024
+ {
3025
+ "name": "max",
3026
+ "takes": "number",
3027
+ "required": true,
3028
+ "note": "How many there are. At `0` the bar is empty."
3029
+ },
3030
+ {
3031
+ "name": "label",
3032
+ "takes": "text",
3033
+ "required": true,
3034
+ "note": "The accessible name — \"Items done\"."
3035
+ },
3036
+ {
3037
+ "name": "variant",
3038
+ "takes": "default | quiet",
3039
+ "required": false,
3040
+ "note": "Default `default`."
3041
+ },
3042
+ {
3043
+ "name": "className",
3044
+ "takes": "text",
3045
+ "required": false,
3046
+ "note": "Placement only: a width, a margin, `flex-1` in a row."
3047
+ }
3048
+ ],
3049
+ "variants": [
3050
+ {
3051
+ "prop": "variant",
3052
+ "values": [
3053
+ "default",
3054
+ "quiet"
3055
+ ]
3056
+ }
3057
+ ],
3058
+ "ownsBehaviours": [
3059
+ {
3060
+ "id": "base-ui",
3061
+ "behaviour": "Is built on Base UI"
3062
+ },
3063
+ {
3064
+ "id": "role",
3065
+ "behaviour": "Says what it is to assistive technology"
3066
+ }
3067
+ ],
3068
+ "status": "stable",
3069
+ "migrationStage": null,
3070
+ "docsId": "feedback-progressbar--docs",
3071
+ "storyId": "feedback-progressbar--default",
3072
+ "docPage": "src/ProgressBar.mdx"
3073
+ },
3074
+ {
3075
+ "name": "Property",
3076
+ "repo": "estiva-ui",
3077
+ "kind": "component",
3078
+ "importPath": "@estiva-app/ui",
3079
+ "sourceFile": "src/Property.tsx",
3080
+ "purpose": "A labelled property — \"Status\", \"Lead\", and whatever else a surface declares.",
3081
+ "purposeFrom": "page",
3082
+ "props": [
3083
+ {
3084
+ "name": "label",
3085
+ "takes": "text",
3086
+ "required": true,
3087
+ "note": null
3088
+ },
3089
+ {
3090
+ "name": "layout",
3091
+ "takes": "row | stacked",
3092
+ "required": false,
3093
+ "note": null
3094
+ },
3095
+ {
3096
+ "name": "children",
3097
+ "takes": "anything",
3098
+ "required": true,
3099
+ "note": null
3100
+ },
3101
+ {
3102
+ "name": "className",
3103
+ "takes": "text",
3104
+ "required": false,
3105
+ "note": null
3106
+ }
3107
+ ],
3108
+ "variants": [
3109
+ {
3110
+ "prop": "layout",
3111
+ "values": [
3112
+ "row",
3113
+ "stacked"
3114
+ ]
3115
+ }
3116
+ ],
3117
+ "ownsBehaviours": [],
3118
+ "status": "stable",
3119
+ "migrationStage": null,
3120
+ "docsId": "primitives-property--docs",
3121
+ "storyId": "primitives-property--row",
3122
+ "docPage": "src/Property.mdx"
3123
+ },
3124
+ {
3125
+ "name": "Rail",
3126
+ "repo": "estiva-ui",
3127
+ "kind": "component",
3128
+ "importPath": "@estiva-app/ui",
3129
+ "sourceFile": "src/Rail.tsx",
3130
+ "purpose": "The 64px strip of icon tiles down the left of an app.",
3131
+ "purposeFrom": "page",
3132
+ "props": [
3133
+ {
3134
+ "name": "aria-label",
3135
+ "takes": "text",
3136
+ "required": false,
3137
+ "note": "Names the navigation region for assistive tech."
3138
+ },
3139
+ {
3140
+ "name": "children",
3141
+ "takes": "anything",
3142
+ "required": true,
3143
+ "note": null
3144
+ },
3145
+ {
3146
+ "name": "className",
3147
+ "takes": "text",
3148
+ "required": false,
3149
+ "note": null
3150
+ }
3151
+ ],
3152
+ "variants": [],
3153
+ "ownsBehaviours": [],
3154
+ "status": "stable",
3155
+ "migrationStage": null,
3156
+ "docsId": "frame-rail--docs",
3157
+ "storyId": "frame-rail--default",
3158
+ "docPage": "src/Rail.mdx"
3159
+ },
3160
+ {
3161
+ "name": "RailItem",
3162
+ "repo": "estiva-ui",
3163
+ "kind": "component",
3164
+ "importPath": "@estiva-app/ui",
3165
+ "sourceFile": "src/RailItem.tsx",
3166
+ "purpose": "One tile of an icon rail: the icon in its hover tile, a 9px label under it.",
3167
+ "purposeFrom": "page",
3168
+ "props": [
3169
+ {
3170
+ "name": "href",
3171
+ "takes": "text",
3172
+ "required": true,
3173
+ "note": null
3174
+ },
3175
+ {
3176
+ "name": "icon",
3177
+ "takes": "anything",
3178
+ "required": true,
3179
+ "note": "16px, stroke 1.5."
3180
+ },
3181
+ {
3182
+ "name": "label",
3183
+ "takes": "text",
3184
+ "required": true,
3185
+ "note": null
3186
+ },
3187
+ {
3188
+ "name": "active",
3189
+ "takes": "true/false",
3190
+ "required": false,
3191
+ "note": null
3192
+ },
3193
+ {
3194
+ "name": "className",
3195
+ "takes": "text",
3196
+ "required": false,
3197
+ "note": null
3198
+ }
3199
+ ],
3200
+ "variants": [],
3201
+ "ownsBehaviours": [],
3202
+ "status": "stable",
3203
+ "migrationStage": null,
3204
+ "docsId": "frame-railitem--docs",
3205
+ "storyId": "frame-railitem--default",
3206
+ "docPage": "src/RailItem.mdx"
3207
+ },
3208
+ {
3209
+ "name": "Reaction",
3210
+ "repo": "estiva-ui",
3211
+ "kind": "component",
3212
+ "importPath": "@estiva-app/ui",
3213
+ "sourceFile": "src/Reaction.tsx",
3214
+ "purpose": "An emoji, how many people chose it, and whether you are one of them.",
3215
+ "purposeFrom": "page",
3216
+ "props": [
3217
+ {
3218
+ "name": "emoji",
3219
+ "takes": "anything",
3220
+ "required": true,
3221
+ "note": "The emoji, drawn decoratively — name the control with `aria-label`."
3222
+ },
3223
+ {
3224
+ "name": "count",
3225
+ "takes": "number",
3226
+ "required": true,
3227
+ "note": "How many people reacted. Drawn as it is."
3228
+ },
3229
+ {
3230
+ "name": "pressed",
3231
+ "takes": "true/false",
3232
+ "required": false,
3233
+ "note": "You are one of them: the accent tint and edge, and `aria-pressed`."
3234
+ },
3235
+ {
3236
+ "name": "aria-label",
3237
+ "takes": "text",
3238
+ "required": true,
3239
+ "note": "Names the control. Required — the emoji is decorative and the count is the only visible text, so without this it is announced as a bare number."
3240
+ }
3241
+ ],
3242
+ "variants": [],
3243
+ "ownsBehaviours": [
3244
+ {
3245
+ "id": "base-ui",
3246
+ "behaviour": "Is built on Base UI"
3247
+ }
3248
+ ],
3249
+ "status": "stable",
3250
+ "migrationStage": null,
3251
+ "docsId": "components-reaction--docs",
3252
+ "storyId": "components-reaction--default",
3253
+ "docPage": "src/Reaction.mdx"
3254
+ },
3255
+ {
3256
+ "name": "ReactionPicker",
3257
+ "repo": "estiva-ui",
3258
+ "kind": "component",
3259
+ "importPath": "@estiva-app/ui",
3260
+ "sourceFile": "src/ReactionPicker.tsx",
3261
+ "purpose": "The reactions on offer, to choose one from — icon buttons holding emoji, on a Toolbar.",
3262
+ "purposeFrom": "page",
3263
+ "props": [
3264
+ {
3265
+ "name": "options",
3266
+ "takes": "ReactionOption[]",
3267
+ "required": true,
3268
+ "note": "What is on offer, in the order it is drawn."
3269
+ },
3270
+ {
3271
+ "name": "onSelect",
3272
+ "takes": "a handler",
3273
+ "required": true,
3274
+ "note": null
3275
+ },
3276
+ {
3277
+ "name": "aria-label",
3278
+ "takes": "text",
3279
+ "required": false,
3280
+ "note": "Names the row. Default \"Reactions\"."
3281
+ },
3282
+ {
3283
+ "name": "surface",
3284
+ "takes": "true/false",
3285
+ "required": false,
3286
+ "note": "The elevated box around the row, from `Toolbar`."
3287
+ },
3288
+ {
3289
+ "name": "className",
3290
+ "takes": "text",
3291
+ "required": false,
3292
+ "note": "The row's layout — its gap, its padding."
3293
+ }
3294
+ ],
3295
+ "variants": [],
3296
+ "ownsBehaviours": [],
3297
+ "status": "stable",
3298
+ "migrationStage": null,
3299
+ "docsId": "components-reactionpicker--docs",
3300
+ "storyId": "components-reactionpicker--default",
3301
+ "docPage": "src/ReactionPicker.mdx"
3302
+ },
3303
+ {
3304
+ "name": "ScrollArea",
3305
+ "repo": "estiva-ui",
3306
+ "kind": "component",
3307
+ "importPath": "@estiva-app/ui",
3308
+ "sourceFile": "src/ScrollArea.tsx",
3309
+ "purpose": "A region that scrolls without taking width for its scrollbar.",
3310
+ "purposeFrom": "page",
3311
+ "props": [
3312
+ {
3313
+ "name": "orientation",
3314
+ "takes": "vertical | horizontal | both",
3315
+ "required": false,
3316
+ "note": null
3317
+ },
3318
+ {
3319
+ "name": "className",
3320
+ "takes": "text",
3321
+ "required": false,
3322
+ "note": "On the region: its size and placement."
3323
+ },
3324
+ {
3325
+ "name": "viewportClassName",
3326
+ "takes": "text",
3327
+ "required": false,
3328
+ "note": "On the viewport, the box that scrolls: a `max-h-*` cap."
3329
+ },
3330
+ {
3331
+ "name": "contentClassName",
3332
+ "takes": "text",
3333
+ "required": false,
3334
+ "note": "On the content, the box the children sit in: padding, gap, layout."
3335
+ },
3336
+ {
3337
+ "name": "viewportRef",
3338
+ "takes": "Ref<HTMLDivElement>",
3339
+ "required": false,
3340
+ "note": "The scrolling box itself, for a region that reads or drives its own scrolling: `ref.current.scrollTop`, `scrollTo`, `scrollHeight`."
3341
+ },
3342
+ {
3343
+ "name": "onScroll",
3344
+ "takes": "UIEventHandler<HTMLDivElement>",
3345
+ "required": false,
3346
+ "note": "Fires as the viewport scrolls — the unread policy's input, beside `viewportRef`."
3347
+ },
3348
+ {
3349
+ "name": "children",
3350
+ "takes": "anything",
3351
+ "required": true,
3352
+ "note": null
3353
+ }
3354
+ ],
3355
+ "variants": [
3356
+ {
3357
+ "prop": "orientation",
3358
+ "values": [
3359
+ "vertical",
3360
+ "horizontal",
3361
+ "both"
3362
+ ]
3363
+ }
3364
+ ],
3365
+ "ownsBehaviours": [
3366
+ {
3367
+ "id": "base-ui",
3368
+ "behaviour": "Is built on Base UI"
3369
+ },
3370
+ {
3371
+ "id": "scroll",
3372
+ "behaviour": "Scrolls with our scrollbar"
3373
+ }
3374
+ ],
3375
+ "status": "stable",
3376
+ "migrationStage": null,
3377
+ "docsId": "layout-scrollarea--docs",
3378
+ "storyId": "layout-scrollarea--default",
3379
+ "docPage": "src/ScrollArea.mdx"
3380
+ },
3381
+ {
3382
+ "name": "SearchInput",
3383
+ "repo": "estiva-ui",
3384
+ "kind": "component",
3385
+ "importPath": "@estiva-app/ui",
3386
+ "sourceFile": "src/SearchInput.tsx",
3387
+ "purpose": "An inset field with a hairline border that strengthens on hover and on focus, and an optional keyboard hint at the right edge.",
3388
+ "purposeFrom": "page",
3389
+ "props": [
3390
+ {
3391
+ "name": "shortcut",
3392
+ "takes": "text",
3393
+ "required": false,
3394
+ "note": "A keyboard hint drawn at the right edge, e.g."
3395
+ },
3396
+ {
3397
+ "name": "className",
3398
+ "takes": "text",
3399
+ "required": false,
3400
+ "note": null
3401
+ }
3402
+ ],
3403
+ "variants": [],
3404
+ "ownsBehaviours": [
3405
+ {
3406
+ "id": "base-ui",
3407
+ "behaviour": "Is built on Base UI"
3408
+ }
3409
+ ],
3410
+ "status": "stable",
3411
+ "migrationStage": null,
3412
+ "docsId": "inputs-searchinput--docs",
3413
+ "storyId": "inputs-searchinput--default",
3414
+ "docPage": "src/SearchInput.mdx"
3415
+ },
3416
+ {
3417
+ "name": "SectionHeader",
3418
+ "repo": "estiva-ui",
3419
+ "kind": "component",
3420
+ "importPath": "@estiva-app/ui",
3421
+ "sourceFile": "src/SectionHeader.tsx",
3422
+ "purpose": "The 32px row a section starts with: a SectionLabel, and actions that appear on hover or focus as IconButtons with tooltips.",
3423
+ "purposeFrom": "page",
3424
+ "props": [
3425
+ {
3426
+ "name": "title",
3427
+ "takes": "text",
3428
+ "required": true,
3429
+ "note": null
3430
+ },
3431
+ {
3432
+ "name": "chevron",
3433
+ "takes": "true/false",
3434
+ "required": false,
3435
+ "note": "Collapsible: draws the chevron and makes the title a button that toggles."
3436
+ },
3437
+ {
3438
+ "name": "isExpanded",
3439
+ "takes": "true/false",
3440
+ "required": false,
3441
+ "note": null
3442
+ },
3443
+ {
3444
+ "name": "onToggle",
3445
+ "takes": "a handler",
3446
+ "required": false,
3447
+ "note": null
3448
+ },
3449
+ {
3450
+ "name": "trailing",
3451
+ "takes": "anything",
3452
+ "required": false,
3453
+ "note": "Beside the title and always visible, before the actions — a count."
3454
+ },
3455
+ {
3456
+ "name": "actions",
3457
+ "takes": "SectionAction[]",
3458
+ "required": false,
3459
+ "note": "Right-aligned, in the order given."
3460
+ },
3461
+ {
3462
+ "name": "showActions",
3463
+ "takes": "hover | always",
3464
+ "required": false,
3465
+ "note": "`hover` reveals the actions while the row is hovered or focused; `always` keeps them."
3466
+ },
3467
+ {
3468
+ "name": "render",
3469
+ "takes": "useRender.RenderProp",
3470
+ "required": false,
3471
+ "note": "What the title renders as, in Base UI's manner."
3472
+ },
3473
+ {
3474
+ "name": "className",
3475
+ "takes": "text",
3476
+ "required": false,
3477
+ "note": null
3478
+ }
3479
+ ],
3480
+ "variants": [
3481
+ {
3482
+ "prop": "showActions",
3483
+ "values": [
3484
+ "hover",
3485
+ "always"
3486
+ ]
3487
+ }
3488
+ ],
3489
+ "ownsBehaviours": [],
3490
+ "status": "stable",
3491
+ "migrationStage": null,
3492
+ "docsId": "navigation-sectionheader--docs",
3493
+ "storyId": "navigation-sectionheader--plain",
3494
+ "docPage": "src/SectionHeader.mdx"
3495
+ },
3496
+ {
3497
+ "name": "SectionLabel",
3498
+ "repo": "estiva-ui",
3499
+ "kind": "component",
3500
+ "importPath": "@estiva-app/ui",
3501
+ "sourceFile": "src/SectionLabel.tsx",
3502
+ "purpose": "The section-title span. Every section heading — sidebar sections, menu headings, panel titles — renders through it, so a change of voice is one edit. 12px / 500, primary text; some themes restyle it (the toolbar shows how).",
3503
+ "purposeFrom": "page",
3504
+ "props": [
3505
+ {
3506
+ "name": "children",
3507
+ "takes": "anything",
3508
+ "required": true,
3509
+ "note": null
3510
+ },
3511
+ {
3512
+ "name": "tone",
3513
+ "takes": "primary | secondary",
3514
+ "required": false,
3515
+ "note": null
3516
+ },
3517
+ {
3518
+ "name": "className",
3519
+ "takes": "text",
3520
+ "required": false,
3521
+ "note": null
3522
+ }
3523
+ ],
3524
+ "variants": [
3525
+ {
3526
+ "prop": "tone",
3527
+ "values": [
3528
+ "primary",
3529
+ "secondary"
3530
+ ]
3531
+ }
3532
+ ],
3533
+ "ownsBehaviours": [],
3534
+ "status": "stable",
3535
+ "migrationStage": null,
3536
+ "docsId": "primitives-sectionlabel--docs",
3537
+ "storyId": "primitives-sectionlabel--default",
3538
+ "docPage": "src/SectionLabel.mdx"
3539
+ },
3540
+ {
3541
+ "name": "Select",
3542
+ "repo": "estiva-ui",
3543
+ "kind": "component",
3544
+ "importPath": "@estiva-app/ui",
3545
+ "sourceFile": "src/Select.tsx",
3546
+ "purpose": "One value for a form field: a button that shows the choice and opens a portalled listbox under itself.",
3547
+ "purposeFrom": "page",
3548
+ "props": [
3549
+ {
3550
+ "name": "value",
3551
+ "takes": "text",
3552
+ "required": true,
3553
+ "note": null
3554
+ },
3555
+ {
3556
+ "name": "onChange",
3557
+ "takes": "a handler",
3558
+ "required": true,
3559
+ "note": null
3560
+ },
3561
+ {
3562
+ "name": "options",
3563
+ "takes": "SelectOption[]",
3564
+ "required": true,
3565
+ "note": null
3566
+ },
3567
+ {
3568
+ "name": "size",
3569
+ "takes": "default | small",
3570
+ "required": false,
3571
+ "note": null
3572
+ },
3573
+ {
3574
+ "name": "ariaLabel",
3575
+ "takes": "text",
3576
+ "required": false,
3577
+ "note": null
3578
+ },
3579
+ {
3580
+ "name": "aria-required",
3581
+ "takes": "boolean | 'true' | 'false'",
3582
+ "required": false,
3583
+ "note": "Set by a `Field` with `required`; a caller inside one owes nothing."
3584
+ },
3585
+ {
3586
+ "name": "placeholder",
3587
+ "takes": "text",
3588
+ "required": false,
3589
+ "note": null
3590
+ },
3591
+ {
3592
+ "name": "disabled",
3593
+ "takes": "true/false",
3594
+ "required": false,
3595
+ "note": null
3596
+ },
3597
+ {
3598
+ "name": "className",
3599
+ "takes": "text",
3600
+ "required": false,
3601
+ "note": null
3602
+ }
3603
+ ],
3604
+ "variants": [
3605
+ {
3606
+ "prop": "size",
3607
+ "values": [
3608
+ "default",
3609
+ "small"
3610
+ ]
3611
+ }
3612
+ ],
3613
+ "ownsBehaviours": [
3614
+ {
3615
+ "id": "base-ui",
3616
+ "behaviour": "Is built on Base UI"
3617
+ },
3618
+ {
3619
+ "id": "portal",
3620
+ "behaviour": "Floats on top of the page"
3621
+ },
3622
+ {
3623
+ "id": "press-outside",
3624
+ "behaviour": "Closes on a press outside"
3625
+ },
3626
+ {
3627
+ "id": "page-keys",
3628
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
3629
+ },
3630
+ {
3631
+ "id": "follow",
3632
+ "behaviour": "Stays attached to its anchor on scroll and resize"
3633
+ },
3634
+ {
3635
+ "id": "walking",
3636
+ "behaviour": "Moves through its items with the arrow keys"
3637
+ },
3638
+ {
3639
+ "id": "role",
3640
+ "behaviour": "Says what it is to assistive technology"
3641
+ }
3642
+ ],
3643
+ "status": "stable",
3644
+ "migrationStage": null,
3645
+ "docsId": "inputs-select--docs",
3646
+ "storyId": "inputs-select--default",
3647
+ "docPage": "src/Select.mdx"
3648
+ },
3649
+ {
3650
+ "name": "Sidebar",
3651
+ "repo": "estiva-ui",
3652
+ "kind": "component",
3653
+ "importPath": "@estiva-app/ui",
3654
+ "sourceFile": "src/Sidebar.tsx",
3655
+ "purpose": "The navigation column: 240px, a hairline on its right, the surface behind it, scrolling independently of the content beside it.",
3656
+ "purposeFrom": "page",
3657
+ "props": [
3658
+ {
3659
+ "name": "aria-label",
3660
+ "takes": "text",
3661
+ "required": false,
3662
+ "note": "Names the navigation region for assistive tech."
3663
+ },
3664
+ {
3665
+ "name": "children",
3666
+ "takes": "anything",
3667
+ "required": true,
3668
+ "note": null
3669
+ },
3670
+ {
3671
+ "name": "className",
3672
+ "takes": "text",
3673
+ "required": false,
3674
+ "note": null
3675
+ }
3676
+ ],
3677
+ "variants": [],
3678
+ "ownsBehaviours": [],
3679
+ "status": "stable",
3680
+ "migrationStage": null,
3681
+ "docsId": "frame-sidebar--docs",
3682
+ "storyId": "frame-sidebar--composed",
3683
+ "docPage": "src/Sidebar.mdx"
3684
+ },
3685
+ {
3686
+ "name": "SkeletonBar",
3687
+ "repo": "estiva-ui",
3688
+ "kind": "component",
3689
+ "importPath": "@estiva-app/ui",
3690
+ "sourceFile": "src/Skeleton.tsx",
3691
+ "purpose": "One pulsing bar at the inset colour: the piece every placeholder here is built from.",
3692
+ "purposeFrom": "comment",
3693
+ "props": [
3694
+ {
3695
+ "name": "className",
3696
+ "takes": "text",
3697
+ "required": false,
3698
+ "note": null
3699
+ },
3700
+ {
3701
+ "name": "style",
3702
+ "takes": "CSSProperties",
3703
+ "required": false,
3704
+ "note": null
3705
+ }
3706
+ ],
3707
+ "variants": [],
3708
+ "ownsBehaviours": [],
3709
+ "status": "stable",
3710
+ "migrationStage": null,
3711
+ "docsId": "feedback-skeleton--docs",
3712
+ "storyId": "feedback-skeleton--list",
3713
+ "docPage": null
3714
+ },
3715
+ {
3716
+ "name": "SkeletonList",
3717
+ "repo": "estiva-ui",
3718
+ "kind": "component",
3719
+ "importPath": "@estiva-app/ui",
3720
+ "sourceFile": "src/Skeleton.tsx",
3721
+ "purpose": "Rows of varied widths, so the placeholder does not read as a pattern.",
3722
+ "purposeFrom": "comment",
3723
+ "props": [
3724
+ {
3725
+ "name": "rows",
3726
+ "takes": "number",
3727
+ "required": false,
3728
+ "note": null
3729
+ },
3730
+ {
3731
+ "name": "className",
3732
+ "takes": "text",
3733
+ "required": false,
3734
+ "note": null
3735
+ }
3736
+ ],
3737
+ "variants": [],
3738
+ "ownsBehaviours": [],
3739
+ "status": "stable",
3740
+ "migrationStage": null,
3741
+ "docsId": "feedback-skeleton--docs",
3742
+ "storyId": "feedback-skeleton--list",
3743
+ "docPage": null
3744
+ },
3745
+ {
3746
+ "name": "SkeletonRow",
3747
+ "repo": "estiva-ui",
3748
+ "kind": "component",
3749
+ "importPath": "@estiva-app/ui",
3750
+ "sourceFile": "src/Skeleton.tsx",
3751
+ "purpose": "A 32px row: a 16px square and a bar, like a row with a face and a name.",
3752
+ "purposeFrom": "comment",
3753
+ "props": [
3754
+ {
3755
+ "name": "barWidth",
3756
+ "takes": "number",
3757
+ "required": false,
3758
+ "note": null
3759
+ }
3760
+ ],
3761
+ "variants": [],
3762
+ "ownsBehaviours": [],
3763
+ "status": "stable",
3764
+ "migrationStage": null,
3765
+ "docsId": "feedback-skeleton--docs",
3766
+ "storyId": "feedback-skeleton--list",
3767
+ "docPage": null
3768
+ },
3769
+ {
3770
+ "name": "Tabs",
3771
+ "repo": "estiva-ui",
3772
+ "kind": "component",
3773
+ "importPath": "@estiva-app/ui",
3774
+ "sourceFile": "src/Tabs.tsx",
3775
+ "purpose": "A row of tabs for switching between views of one thing.",
3776
+ "purposeFrom": "page",
3777
+ "props": [
3778
+ {
3779
+ "name": "tabs",
3780
+ "takes": "TabDef<T>[]",
3781
+ "required": true,
3782
+ "note": null
3783
+ },
3784
+ {
3785
+ "name": "active",
3786
+ "takes": "T",
3787
+ "required": true,
3788
+ "note": null
3789
+ },
3790
+ {
3791
+ "name": "onChange",
3792
+ "takes": "a handler",
3793
+ "required": true,
3794
+ "note": null
3795
+ },
3796
+ {
3797
+ "name": "size",
3798
+ "takes": "default | small",
3799
+ "required": false,
3800
+ "note": "`default` 14px; `small` 12px, the denser geometry."
3801
+ },
3802
+ {
3803
+ "name": "aria-label",
3804
+ "takes": "text",
3805
+ "required": false,
3806
+ "note": "Names the row for assistive tech — \"Views\", \"Filters\"."
3807
+ },
3808
+ {
3809
+ "name": "aria-labelledby",
3810
+ "takes": "text",
3811
+ "required": false,
3812
+ "note": null
3813
+ },
3814
+ {
3815
+ "name": "className",
3816
+ "takes": "text",
3817
+ "required": false,
3818
+ "note": "Lands on the outer box, around the row."
3819
+ }
3820
+ ],
3821
+ "variants": [
3822
+ {
3823
+ "prop": "size",
3824
+ "values": [
3825
+ "default",
3826
+ "small"
3827
+ ]
3828
+ }
3829
+ ],
3830
+ "ownsBehaviours": [
3831
+ {
3832
+ "id": "base-ui",
3833
+ "behaviour": "Is built on Base UI"
3834
+ },
3835
+ {
3836
+ "id": "page-keys",
3837
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
3838
+ },
3839
+ {
3840
+ "id": "walking",
3841
+ "behaviour": "Moves through its items with the arrow keys"
3842
+ },
3843
+ {
3844
+ "id": "role",
3845
+ "behaviour": "Says what it is to assistive technology"
3846
+ }
3847
+ ],
3848
+ "status": "stable",
3849
+ "migrationStage": null,
3850
+ "docsId": "navigation-tabs--docs",
3851
+ "storyId": "navigation-tabs--with-counts",
3852
+ "docPage": "src/Tabs.mdx"
3853
+ },
3854
+ {
3855
+ "name": "Textarea",
3856
+ "repo": "estiva-ui",
3857
+ "kind": "component",
3858
+ "importPath": "@estiva-app/ui",
3859
+ "sourceFile": "src/Textarea.tsx",
3860
+ "purpose": "TextInput's look on a multi-line field that does not resize.",
3861
+ "purposeFrom": "page",
3862
+ "props": [],
3863
+ "variants": [],
3864
+ "ownsBehaviours": [],
3865
+ "status": "stable",
3866
+ "migrationStage": null,
3867
+ "docsId": "inputs-textarea--docs",
3868
+ "storyId": "inputs-textarea--empty",
3869
+ "docPage": "src/Textarea.mdx"
3870
+ },
3871
+ {
3872
+ "name": "TextInput",
3873
+ "repo": "estiva-ui",
3874
+ "kind": "component",
3875
+ "importPath": "@estiva-app/ui",
3876
+ "sourceFile": "src/TextInput.tsx",
3877
+ "purpose": "The single-line field: inset surface, 8px radius, 14px text, a stronger border on hover, the focus border in every theme.",
3878
+ "purposeFrom": "page",
3879
+ "props": [
3880
+ {
3881
+ "name": "size",
3882
+ "takes": "default | small",
3883
+ "required": false,
3884
+ "note": "`small` is 24px tall with 12px text — the small `Select`'s size, so a field can share a dense row with small selects (D67, 2026-09-13: Peek's reference widget hand-built one because this was 38px)."
3885
+ }
3886
+ ],
3887
+ "variants": [
3888
+ {
3889
+ "prop": "size",
3890
+ "values": [
3891
+ "default",
3892
+ "small"
3893
+ ]
3894
+ }
3895
+ ],
3896
+ "ownsBehaviours": [
3897
+ {
3898
+ "id": "base-ui",
3899
+ "behaviour": "Is built on Base UI"
3900
+ }
3901
+ ],
3902
+ "status": "stable",
3903
+ "migrationStage": null,
3904
+ "docsId": "inputs-textinput--docs",
3905
+ "storyId": "inputs-textinput--empty",
3906
+ "docPage": "src/TextInput.mdx"
3907
+ },
3908
+ {
3909
+ "name": "Toast",
3910
+ "repo": "estiva-ui",
3911
+ "kind": "component",
3912
+ "importPath": "@estiva-app/ui",
3913
+ "sourceFile": "src/Toast.tsx",
3914
+ "purpose": "A pill that says what just happened — three types, an optional leading check, an optional action — and ToastProvider/useToast, which own the positioning (bottom-left), the portal, and the auto-dismiss.",
3915
+ "purposeFrom": "page",
3916
+ "props": [
3917
+ {
3918
+ "name": "label",
3919
+ "takes": "text",
3920
+ "required": true,
3921
+ "note": null
3922
+ },
3923
+ {
3924
+ "name": "type",
3925
+ "takes": "success | brand | neutral | warning | error",
3926
+ "required": false,
3927
+ "note": "Which of the five this is. It decides the surface in the light themes, and under Signal — where every pill is the same dark overlay — the icon and its colour."
3928
+ },
3929
+ {
3930
+ "name": "leadingIcon",
3931
+ "takes": "true/false",
3932
+ "required": false,
3933
+ "note": "Show the leading icon — a check, a `!` or an `×`, per `type`."
3934
+ },
3935
+ {
3936
+ "name": "actionLabel",
3937
+ "takes": "text",
3938
+ "required": false,
3939
+ "note": "When set together with onAction, renders a clickable action on the right side."
3940
+ },
3941
+ {
3942
+ "name": "onAction",
3943
+ "takes": "a handler",
3944
+ "required": false,
3945
+ "note": null
3946
+ },
3947
+ {
3948
+ "name": "className",
3949
+ "takes": "text",
3950
+ "required": false,
3951
+ "note": null
3952
+ }
3953
+ ],
3954
+ "variants": [
3955
+ {
3956
+ "prop": "type",
3957
+ "values": [
3958
+ "success",
3959
+ "brand",
3960
+ "neutral",
3961
+ "warning",
3962
+ "error"
3963
+ ]
3964
+ }
3965
+ ],
3966
+ "ownsBehaviours": [
3967
+ {
3968
+ "id": "base-ui",
3969
+ "behaviour": "Is built on Base UI"
3970
+ },
3971
+ {
3972
+ "id": "portal",
3973
+ "behaviour": "Floats on top of the page"
3974
+ },
3975
+ {
3976
+ "id": "role",
3977
+ "behaviour": "Says what it is to assistive technology"
3978
+ }
3979
+ ],
3980
+ "status": "stable",
3981
+ "migrationStage": null,
3982
+ "docsId": "feedback-toast--docs",
3983
+ "storyId": "feedback-toast--neutral",
3984
+ "docPage": "src/Toast.mdx"
3985
+ },
3986
+ {
3987
+ "name": "ToastProvider",
3988
+ "repo": "estiva-ui",
3989
+ "kind": "component",
3990
+ "importPath": "@estiva-app/ui",
3991
+ "sourceFile": "src/Toast.tsx",
3992
+ "purpose": "Mount once, near the top of an app. It owns the stack, the timers and the portal every toast goes through, and it is what `useToast` talks to.",
3993
+ "purposeFrom": "comment",
3994
+ "props": [
3995
+ {
3996
+ "name": "children",
3997
+ "takes": "anything",
3998
+ "required": true,
3999
+ "note": null
4000
+ }
4001
+ ],
4002
+ "variants": [],
4003
+ "ownsBehaviours": [],
4004
+ "status": "stable",
4005
+ "migrationStage": null,
4006
+ "docsId": "feedback-toast--docs",
4007
+ "storyId": "feedback-toast--neutral",
4008
+ "docPage": null
4009
+ },
4010
+ {
4011
+ "name": "Toolbar",
4012
+ "repo": "estiva-ui",
4013
+ "kind": "component",
4014
+ "importPath": "@estiva-app/ui",
4015
+ "sourceFile": "src/Toolbar.tsx",
4016
+ "purpose": "A strip of controls that behaves as one control: Tab in, arrow keys along, Tab out — on the elevated box a floating strip needs.",
4017
+ "purposeFrom": "page",
4018
+ "props": [
4019
+ {
4020
+ "name": "aria-label",
4021
+ "takes": "text",
4022
+ "required": true,
4023
+ "note": "Names the strip for assistive tech — \"Formatting\", \"Reactions\"."
4024
+ },
4025
+ {
4026
+ "name": "orientation",
4027
+ "takes": "horizontal | vertical",
4028
+ "required": false,
4029
+ "note": "`horizontal` walks with ← →, `vertical` with ↑ ↓."
4030
+ },
4031
+ {
4032
+ "name": "loopFocus",
4033
+ "takes": "true/false",
4034
+ "required": false,
4035
+ "note": "Whether the arrow keys wrap at the ends."
4036
+ },
4037
+ {
4038
+ "name": "surface",
4039
+ "takes": "true/false",
4040
+ "required": false,
4041
+ "note": "The elevated box around the strip. On by default — a toolbar floats, and this is what floating looks like here."
4042
+ },
4043
+ {
4044
+ "name": "children",
4045
+ "takes": "anything",
4046
+ "required": true,
4047
+ "note": null
4048
+ },
4049
+ {
4050
+ "name": "className",
4051
+ "takes": "text",
4052
+ "required": false,
4053
+ "note": "The row's own layout — its gap, its padding, its wrapping."
4054
+ }
4055
+ ],
4056
+ "variants": [
4057
+ {
4058
+ "prop": "orientation",
4059
+ "values": [
4060
+ "horizontal",
4061
+ "vertical"
4062
+ ]
4063
+ }
4064
+ ],
4065
+ "ownsBehaviours": [
4066
+ {
4067
+ "id": "base-ui",
4068
+ "behaviour": "Is built on Base UI"
4069
+ },
4070
+ {
4071
+ "id": "page-keys",
4072
+ "behaviour": "Closes on Escape, and takes its keys, by itself"
4073
+ },
4074
+ {
4075
+ "id": "walking",
4076
+ "behaviour": "Moves through its items with the arrow keys"
4077
+ },
4078
+ {
4079
+ "id": "role",
4080
+ "behaviour": "Says what it is to assistive technology"
4081
+ }
4082
+ ],
4083
+ "status": "stable",
4084
+ "migrationStage": null,
4085
+ "docsId": "primitives-toolbar--docs",
4086
+ "storyId": "primitives-toolbar--default",
4087
+ "docPage": "src/Toolbar.mdx"
4088
+ },
4089
+ {
4090
+ "name": "ToolbarButton",
4091
+ "repo": "estiva-ui",
4092
+ "kind": "component",
4093
+ "importPath": "@estiva-app/ui",
4094
+ "sourceFile": "src/Toolbar.tsx",
4095
+ "purpose": "An `IconButton` that is an item of a `Toolbar`: the arrow keys reach it, and a disabled one stays in the walk so its reason can still be read.",
4096
+ "purposeFrom": "comment",
4097
+ "props": [
4098
+ {
4099
+ "name": "ref",
4100
+ "takes": "Ref<HTMLButtonElement>",
4101
+ "required": false,
4102
+ "note": null
4103
+ },
4104
+ {
4105
+ "name": "variant",
4106
+ "takes": "muted | outlined | primary | current | resolve",
4107
+ "required": false,
4108
+ "note": "`current` takes the colour of what it sits in — the ✕ on a `Banner` wears the banner's tone."
4109
+ },
4110
+ {
4111
+ "name": "pressed",
4112
+ "takes": "true/false",
4113
+ "required": false,
4114
+ "note": "On, like a Bold button while the selection is bold: the active fill, and `aria-pressed`."
4115
+ },
4116
+ {
4117
+ "name": "glow",
4118
+ "takes": "true/false",
4119
+ "required": false,
4120
+ "note": "A glow in Signal — the send arrow while there is something to send."
4121
+ },
4122
+ {
4123
+ "name": "tooltip",
4124
+ "takes": "text",
4125
+ "required": false,
4126
+ "note": null
4127
+ },
4128
+ {
4129
+ "name": "tooltipShortcut",
4130
+ "takes": "text",
4131
+ "required": false,
4132
+ "note": "A key hint drawn as the `Kbd` chip inside the tooltip — for a button whose only other affordance is a keyboard shortcut."
4133
+ },
4134
+ {
4135
+ "name": "tooltipPlacement",
4136
+ "takes": "top | bottom",
4137
+ "required": false,
4138
+ "note": null
4139
+ },
4140
+ {
4141
+ "name": "disabledReason",
4142
+ "takes": "text",
4143
+ "required": false,
4144
+ "note": "Why the action cannot succeed right now."
4145
+ },
4146
+ {
4147
+ "name": "children",
4148
+ "takes": "anything",
4149
+ "required": true,
4150
+ "note": "The icon: 16px, stroke 1.5."
4151
+ }
4152
+ ],
4153
+ "variants": [
4154
+ {
4155
+ "prop": "variant",
4156
+ "values": [
4157
+ "muted",
4158
+ "outlined",
4159
+ "primary",
4160
+ "current",
4161
+ "resolve"
4162
+ ]
4163
+ },
4164
+ {
4165
+ "prop": "tooltipPlacement",
4166
+ "values": [
4167
+ "top",
4168
+ "bottom"
4169
+ ]
4170
+ }
4171
+ ],
4172
+ "ownsBehaviours": [],
4173
+ "status": "stable",
4174
+ "migrationStage": null,
4175
+ "docsId": "primitives-toolbar--docs",
4176
+ "storyId": "primitives-toolbar--default",
4177
+ "docPage": null
4178
+ },
4179
+ {
4180
+ "name": "ToolbarInput",
4181
+ "repo": "estiva-ui",
4182
+ "kind": "component",
4183
+ "importPath": "@estiva-app/ui",
4184
+ "sourceFile": "src/Toolbar.tsx",
4185
+ "purpose": "A `TextInput` that is an item of a `Toolbar`, so the arrow keys walk into the field and out of it again.",
4186
+ "purposeFrom": "comment",
4187
+ "props": [
4188
+ {
4189
+ "name": "size",
4190
+ "takes": "default | small",
4191
+ "required": false,
4192
+ "note": "`small` is 24px tall with 12px text — the small `Select`'s size, so a field can share a dense row with small selects (D67, 2026-09-13: Peek's reference widget hand-built one because this was 38px)."
4193
+ }
4194
+ ],
4195
+ "variants": [
4196
+ {
4197
+ "prop": "size",
4198
+ "values": [
4199
+ "default",
4200
+ "small"
4201
+ ]
4202
+ }
4203
+ ],
4204
+ "ownsBehaviours": [],
4205
+ "status": "stable",
4206
+ "migrationStage": null,
4207
+ "docsId": "primitives-toolbar--docs",
4208
+ "storyId": "primitives-toolbar--default",
4209
+ "docPage": null
4210
+ },
4211
+ {
4212
+ "name": "ToolbarSeparator",
4213
+ "repo": "estiva-ui",
4214
+ "kind": "component",
4215
+ "importPath": "@estiva-app/ui",
4216
+ "sourceFile": "src/Toolbar.tsx",
4217
+ "purpose": "The hairline between two groups of controls.",
4218
+ "purposeFrom": "comment",
4219
+ "props": [
4220
+ {
4221
+ "name": "className",
4222
+ "takes": "text",
4223
+ "required": false,
4224
+ "note": null
4225
+ }
4226
+ ],
4227
+ "variants": [],
4228
+ "ownsBehaviours": [],
4229
+ "status": "stable",
4230
+ "migrationStage": null,
4231
+ "docsId": "primitives-toolbar--docs",
4232
+ "storyId": "primitives-toolbar--default",
4233
+ "docPage": null
4234
+ },
4235
+ {
4236
+ "name": "Tooltip",
4237
+ "repo": "estiva-ui",
4238
+ "kind": "component",
4239
+ "importPath": "@estiva-app/ui",
4240
+ "sourceFile": "src/Tooltip.tsx",
4241
+ "purpose": "A 30px elevated pill with a caption, and WithTooltip, the wrapper that shows it beside a trigger — on hover, and on keyboard focus.",
4242
+ "purposeFrom": "page",
4243
+ "props": [
4244
+ {
4245
+ "name": "label",
4246
+ "takes": "text",
4247
+ "required": true,
4248
+ "note": null
4249
+ },
4250
+ {
4251
+ "name": "shortcut",
4252
+ "takes": "text",
4253
+ "required": false,
4254
+ "note": "The key that does the same thing, drawn as the `Kbd` chip after the label."
4255
+ }
4256
+ ],
4257
+ "variants": [],
4258
+ "ownsBehaviours": [
4259
+ {
4260
+ "id": "base-ui",
4261
+ "behaviour": "Is built on Base UI"
4262
+ },
4263
+ {
4264
+ "id": "portal",
4265
+ "behaviour": "Floats on top of the page"
4266
+ },
4267
+ {
4268
+ "id": "follow",
4269
+ "behaviour": "Stays attached to its anchor on scroll and resize"
4270
+ },
4271
+ {
4272
+ "id": "role",
4273
+ "behaviour": "Says what it is to assistive technology"
4274
+ }
4275
+ ],
4276
+ "status": "stable",
4277
+ "migrationStage": null,
4278
+ "docsId": "primitives-tooltip--docs",
4279
+ "storyId": "primitives-tooltip--default",
4280
+ "docPage": "src/Tooltip.mdx"
4281
+ },
4282
+ {
4283
+ "name": "TooltipProvider",
4284
+ "repo": "estiva-ui",
4285
+ "kind": "component",
4286
+ "importPath": "@estiva-app/ui",
4287
+ "sourceFile": "src/Tooltip.tsx",
4288
+ "purpose": "Mount once at the top of an app: it makes every tooltip below it share one delay, so the second and third open instantly while the group is warm.",
4289
+ "purposeFrom": "comment",
4290
+ "props": [
4291
+ {
4292
+ "name": "delay",
4293
+ "takes": "number",
4294
+ "required": false,
4295
+ "note": "Before the first tooltip in the group opens."
4296
+ },
4297
+ {
4298
+ "name": "closeDelay",
4299
+ "takes": "number",
4300
+ "required": false,
4301
+ "note": "Before one closes. Default: immediately, as it always has."
4302
+ },
4303
+ {
4304
+ "name": "timeout",
4305
+ "takes": "number",
4306
+ "required": false,
4307
+ "note": "How long after one closes its neighbours still open instantly."
4308
+ },
4309
+ {
4310
+ "name": "children",
4311
+ "takes": "anything",
4312
+ "required": true,
4313
+ "note": null
4314
+ }
4315
+ ],
4316
+ "variants": [],
4317
+ "ownsBehaviours": [],
4318
+ "status": "stable",
4319
+ "migrationStage": null,
4320
+ "docsId": "primitives-tooltip--docs",
4321
+ "storyId": "primitives-tooltip--default",
4322
+ "docPage": null
4323
+ },
4324
+ {
4325
+ "name": "TopBar",
4326
+ "repo": "estiva-ui",
4327
+ "kind": "component",
4328
+ "importPath": "@estiva-app/ui",
4329
+ "sourceFile": "src/TopBar.tsx",
4330
+ "purpose": "The 52px top bar: `menu` and `logo` on the left, a `search` slot in the centre, the identity cluster on the right.",
4331
+ "purposeFrom": "page",
4332
+ "props": [
4333
+ {
4334
+ "name": "variant",
4335
+ "takes": "solid | floating",
4336
+ "required": false,
4337
+ "note": null
4338
+ },
4339
+ {
4340
+ "name": "menu",
4341
+ "takes": "anything",
4342
+ "required": false,
4343
+ "note": "Far left: the menu button, in an app whose navigation collapses."
4344
+ },
4345
+ {
4346
+ "name": "logo",
4347
+ "takes": "anything",
4348
+ "required": false,
4349
+ "note": "Beside the menu button: the app's logo mark, or its name as text."
4350
+ },
4351
+ {
4352
+ "name": "search",
4353
+ "takes": "anything",
4354
+ "required": false,
4355
+ "note": "The centre: a search field, or a launcher affordance — or nothing; the slot holds its place."
4356
+ },
4357
+ {
4358
+ "name": "right",
4359
+ "takes": "anything",
4360
+ "required": false,
4361
+ "note": "The right cluster — an `IdentityMenu` and its neighbours."
4362
+ },
4363
+ {
4364
+ "name": "className",
4365
+ "takes": "text",
4366
+ "required": false,
4367
+ "note": null
4368
+ }
4369
+ ],
4370
+ "variants": [
4371
+ {
4372
+ "prop": "variant",
4373
+ "values": [
4374
+ "solid",
4375
+ "floating"
4376
+ ]
4377
+ }
4378
+ ],
4379
+ "ownsBehaviours": [],
4380
+ "status": "stable",
4381
+ "migrationStage": null,
4382
+ "docsId": "frame-topbar--docs",
4383
+ "storyId": "frame-topbar--solid",
4384
+ "docPage": "src/TopBar.mdx"
4385
+ },
4386
+ {
4387
+ "name": "useToast",
4388
+ "repo": "estiva-ui",
4389
+ "kind": "hook",
4390
+ "importPath": "@estiva-app/ui",
4391
+ "sourceFile": "src/Toast.tsx",
4392
+ "purpose": "How anything under a `ToastProvider` raises a toast (`showToast`) or takes one away (`dismissToast`).",
4393
+ "purposeFrom": "comment",
4394
+ "props": [],
4395
+ "variants": [],
4396
+ "ownsBehaviours": [],
4397
+ "status": "stable",
4398
+ "migrationStage": null,
4399
+ "docsId": "feedback-toast--docs",
4400
+ "storyId": "feedback-toast--neutral",
4401
+ "docPage": null
4402
+ },
4403
+ {
4404
+ "name": "WithTooltip",
4405
+ "repo": "estiva-ui",
4406
+ "kind": "component",
4407
+ "importPath": "@estiva-app/ui",
4408
+ "sourceFile": "src/Tooltip.tsx",
4409
+ "purpose": "A tooltip on something that cannot be its own trigger — a span, a `Chip`, an icon.",
4410
+ "purposeFrom": "comment",
4411
+ "props": [
4412
+ {
4413
+ "name": "label",
4414
+ "takes": "text",
4415
+ "required": true,
4416
+ "note": null
4417
+ },
4418
+ {
4419
+ "name": "shortcut",
4420
+ "takes": "text",
4421
+ "required": false,
4422
+ "note": "Passed straight to the surface — see `TooltipProps.shortcut`."
4423
+ },
4424
+ {
4425
+ "name": "placement",
4426
+ "takes": "top | bottom",
4427
+ "required": false,
4428
+ "note": null
4429
+ },
4430
+ {
4431
+ "name": "wrapperClassName",
4432
+ "takes": "text",
4433
+ "required": false,
4434
+ "note": "Extra classes on the wrapper — e.g. `min-w-0 shrink` so a truncating label keeps truncating inside it."
4435
+ },
4436
+ {
4437
+ "name": "children",
4438
+ "takes": "anything",
4439
+ "required": true,
4440
+ "note": null
4441
+ }
4442
+ ],
4443
+ "variants": [
4444
+ {
4445
+ "prop": "placement",
4446
+ "values": [
4447
+ "top",
4448
+ "bottom"
4449
+ ]
4450
+ }
4451
+ ],
4452
+ "ownsBehaviours": [
4453
+ {
4454
+ "id": "base-ui",
4455
+ "behaviour": "Is built on Base UI"
4456
+ },
4457
+ {
4458
+ "id": "role",
4459
+ "behaviour": "Says what it is to assistive technology"
4460
+ }
4461
+ ],
4462
+ "status": "stable",
4463
+ "migrationStage": null,
4464
+ "docsId": "primitives-tooltip--docs",
4465
+ "storyId": "primitives-tooltip--default",
4466
+ "docPage": null
4467
+ }
4468
+ ],
4469
+ "excluded": []
4470
+ }