@agentero/design-system 0.24.3 → 0.24.5

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 (47) hide show
  1. package/mcp/manifests/components.html +1714 -1001
  2. package/mcp/manifests/components.json +6985 -1
  3. package/mcp/server.mjs +3921 -2320
  4. package/package.json +1 -1
  5. package/src/accordion/accordion.d.ts +35 -23
  6. package/src/accordion/accordion.js +1 -8
  7. package/src/accordion/index.d.ts +18 -1
  8. package/src/accordion/index.js +10 -2
  9. package/src/avatar-group/avatar-group.d.ts +2 -0
  10. package/src/avatar-group/avatar-group.js +0 -1
  11. package/src/button/button.js +0 -1
  12. package/src/check-list/check-list.d.ts +15 -14
  13. package/src/check-list/check-list.js +1 -6
  14. package/src/check-list/index.d.ts +11 -1
  15. package/src/check-list/index.js +8 -2
  16. package/src/command/command.d.ts +117 -43
  17. package/src/command/command.js +1 -9
  18. package/src/command/index.d.ts +86 -1
  19. package/src/command/index.js +12 -2
  20. package/src/data-table/data-table.d.ts +81 -46
  21. package/src/data-table/data-table.js +71 -78
  22. package/src/data-table/index.d.ts +175 -2
  23. package/src/data-table/index.js +22 -3
  24. package/src/data-table/table.d.ts +107 -44
  25. package/src/data-table/table.js +1 -12
  26. package/src/divider/divider.js +0 -1
  27. package/src/dropdown-menu/dropdown-menu.d.ts +254 -136
  28. package/src/dropdown-menu/dropdown-menu.js +1 -14
  29. package/src/dropdown-menu/index.d.ts +51 -1
  30. package/src/dropdown-menu/index.js +16 -2
  31. package/src/hover-card/hover-card.d.ts +40 -26
  32. package/src/hover-card/hover-card.js +1 -9
  33. package/src/hover-card/index.d.ts +20 -1
  34. package/src/hover-card/index.js +11 -2
  35. package/src/label/label.js +0 -1
  36. package/src/modal/index.d.ts +38 -1
  37. package/src/modal/index.js +14 -2
  38. package/src/modal/modal.d.ts +125 -81
  39. package/src/modal/modal.js +1 -11
  40. package/src/popover/index.d.ts +24 -1
  41. package/src/popover/index.js +12 -2
  42. package/src/popover/popover.d.ts +30 -30
  43. package/src/popover/popover.js +1 -10
  44. package/src/skeleton/skeleton.js +0 -1
  45. package/src/tag/tag.js +0 -1
  46. package/src/validation-list/validation-list.d.ts +2 -0
  47. package/src/validation-list/validation-list.js +0 -1
@@ -250,6 +250,7 @@
250
250
  .tg-info:checked + label.as-toggle,
251
251
  .tg-stories:checked + label.as-toggle,
252
252
  .tg-docs:checked + label.as-toggle,
253
+ .tg-subcomponents:checked + label.as-toggle,
253
254
  .tg-content:checked + label.as-toggle,
254
255
  .tg-props:checked + label.as-toggle {
255
256
  box-shadow: 0 0 0 var(--active-ring) currentColor;
@@ -285,6 +286,11 @@
285
286
  gap: 8px;
286
287
  }
287
288
 
289
+ .tg-subcomponents:checked ~ .panels .panel-subcomponents {
290
+ display: grid;
291
+ gap: 8px;
292
+ }
293
+
288
294
  .tg-content:checked ~ .panels .panel-content {
289
295
  display: grid;
290
296
  gap: 8px;
@@ -507,6 +513,10 @@
507
513
  display: grid;
508
514
  }
509
515
 
516
+ .card > .tg-subcomponents:checked ~ .panels .panel-subcomponents {
517
+ display: grid;
518
+ }
519
+
510
520
  .card > .tg-content:checked ~ .panels .panel-content {
511
521
  display: grid;
512
522
  }
@@ -516,6 +526,7 @@
516
526
  .card > .tg-info:checked ~ .panels,
517
527
  .card > .tg-stories:checked ~ .panels,
518
528
  .card > .tg-docs:checked ~ .panels,
529
+ .card > .tg-subcomponents:checked ~ .panels,
519
530
  .card > .tg-content:checked ~ .panels,
520
531
  .card > .tg-props:checked ~ .panels {
521
532
  margin: 10px 0;
@@ -527,6 +538,7 @@
527
538
  .card:has(.tg-info:checked) label[for$='-info'],
528
539
  .card:has(.tg-stories:checked) label[for$='-stories'],
529
540
  .card:has(.tg-docs:checked) label[for$='-docs'],
541
+ .card:has(.tg-subcomponents:checked) label[for$='-subcomponents'],
530
542
  .card:has(.tg-content:checked) label[for$='-content'],
531
543
  .card:has(.tg-props:checked) label[for$='-props'] {
532
544
  box-shadow: 0 0 0 1px currentColor;
@@ -576,13 +588,13 @@
576
588
  <header>
577
589
  <div class="wrap">
578
590
  <h1>Manifest Debugger</h1>
579
- <div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><a class="filter-pill err" data-k="errors" href="#filter-errors">1/25 prop type error</a><a class="filter-pill info" data-k="infos" href="#filter-infos">1/25 info</a><span class="filter-pill ok" aria-disabled="true">192 stories ok</span></div>
591
+ <div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><span class="filter-pill ok" aria-disabled="true">25 components ok</span><span class="filter-pill ok" aria-disabled="true">192 stories ok</span></div>
580
592
  </div>
581
593
  </header>
582
594
  <main>
583
595
  <div class="wrap">
584
596
  <div class="note ok" style="margin-bottom: 16px;">
585
- Using <code>react-docgen-typescript</code>. Generation took <strong>3.7s</strong>.
597
+ Using <code>react-component-meta</code>. Generation took <strong>3.7s</strong>.
586
598
  </div>
587
599
  <h2 class="section-title">Components</h2>
588
600
  <div class="grid" role="list">
@@ -599,16 +611,29 @@
599
611
  <div class="title">
600
612
  <h2><span class="status-dot dot-ok"></span> Accordion.Root</h2>
601
613
  <div class="badges">
602
-
614
+ <label for="c-0-components-accordion-props" class="badge ok as-toggle">10 prop types</label>
603
615
 
604
616
  <label for="c-0-components-accordion-stories" class="badge ok as-toggle">7 stories</label>
605
617
 
618
+
606
619
  </div>
607
620
  </div>
608
621
  <div class="meta" title="./src/accordion/accordion.stories.tsx">components-accordion · ./src/accordion/accordion.stories.tsx</div>
609
-
610
- <div class="hint">Stacked, collapsible sections built on Radix UI&#39;s Accordion (keyboard nav and ARIA come for free). Compose `Root` with `Item`s, each holding a `Trigger` and `Content`. `type=&quot;single&quot;` (optionally `collapsible`) opens one at a time; `type=&quot;multiple&quot;` opens sections independently. `enclosed` renders the group as a bordered card.</div>
611
-
622
+ <div>Root of a group of collapsible sections</div>
623
+ <div class="hint">Accordion is a compound built on Radix UI: `Root` holds the `Item`s, each
624
+ with a `Trigger` and a `Content`. `type=&quot;single&quot;` (with optional
625
+ `collapsible`) opens one section at a time; `type=&quot;multiple&quot;` opens them
626
+ independently. `enclosed` renders the group as a bordered card.</div>
627
+ <div class="kv"><span class="chip">summary: Root of a group of collapsible sections</span><span class="chip">example: ```tsx
628
+ import { Accordion } from &#39;@agentero/design-system/accordion&#39;;
629
+
630
+ &lt;Accordion.Root type=&quot;single&quot; collapsible&gt;
631
+ &lt;Accordion.Item value=&quot;coverages&quot;&gt;
632
+ &lt;Accordion.Trigger&gt;Coverages&lt;/Accordion.Trigger&gt;
633
+ &lt;Accordion.Content&gt;…&lt;/Accordion.Content&gt;
634
+ &lt;/Accordion.Item&gt;
635
+ &lt;/Accordion.Root&gt;
636
+ ```</span></div>
612
637
  </div>
613
638
 
614
639
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -617,11 +642,63 @@
617
642
  <input id="c-0-components-accordion-stories" class="tg tg-stories" type="checkbox" hidden />
618
643
 
619
644
 
645
+ <input id="c-0-components-accordion-props" class="tg tg-props" type="checkbox" hidden />
620
646
 
621
647
  <div class="panels">
622
648
 
623
649
 
624
650
 
651
+ <div class="panel panel-props">
652
+ <div class="note ok">
653
+ <div class="row">
654
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
655
+ <span class="badge ok">10 prop types</span>
656
+ </div>
657
+ <pre><code>Component: src/accordion/index.ts::Accordion</code></pre>
658
+ <pre><code>Props:</code></pre>
659
+ <pre><code>asChild?: boolean
660
+
661
+ /**
662
+ * Whether an accordion item can be collapsed after it has been opened.
663
+ */
664
+ collapsible?: boolean = false
665
+
666
+ /**
667
+ * The value of the item whose content is expanded when the accordion is initially rendered. Use
668
+ * `defaultValue` if you do not need to control the state of an accordion.
669
+ */
670
+ defaultValue?: string | string[] | undefined
671
+
672
+ /**
673
+ * The language read direction.
674
+ */
675
+ dir?: &quot;ltr&quot; | &quot;rtl&quot;
676
+
677
+ /**
678
+ * Whether or not an accordion is disabled from user interaction.
679
+ */
680
+ disabled?: boolean = false
681
+
682
+ enclosed?: boolean
683
+
684
+ /**
685
+ * The callback that fires when the state of the accordion changes.
686
+ */
687
+ onValueChange?: ((value: string) =&gt; void) | ((value: string[]) =&gt; void) | undefined
688
+
689
+ /**
690
+ * The layout in which the Accordion operates.
691
+ */
692
+ orientation?: &quot;horizontal&quot; | &quot;vertical&quot; = vertical
693
+
694
+ type: &quot;single&quot; | &quot;multiple&quot;
695
+
696
+ /**
697
+ * The controlled stateful value of the accordion item whose content is expanded.
698
+ */
699
+ value?: string | string[] | undefined</code></pre>
700
+ </div>
701
+ </div>
625
702
 
626
703
  <div class="panel panel-stories">
627
704
 
@@ -740,6 +817,7 @@
740
817
  </div>
741
818
  </div>
742
819
 
820
+
743
821
  </div>
744
822
  </article>
745
823
  <article
@@ -758,12 +836,32 @@
758
836
 
759
837
  <label for="c-1-components-alert-stories" class="badge ok as-toggle">23 stories</label>
760
838
 
839
+
761
840
  </div>
762
841
  </div>
763
842
  <div class="meta" title="./src/alert/alert.stories.tsx">components-alert · ./src/alert/alert.stories.tsx</div>
764
-
765
- <div class="hint">Alert surfaces feedback about outcomes or state changes — success, danger, warning, or info. Compose it from `Alert.Content`, `Alert.Title`, `Alert.Paragraph`, `Alert.Actions`, and `Alert.Button` to build the layout your flow needs. Eight colors, two sizes, and a ghost mode cover most feedback scenarios.</div>
766
-
843
+ <div>Feedback banner with color variants, optional icon, and dismiss</div>
844
+ <div class="hint">Alert surfaces feedback about outcomes or state changes — success, danger,
845
+ warning, or info. Compose it from `Alert.Content`, `Alert.Title`,
846
+ `Alert.Paragraph`, `Alert.Actions`, and `Alert.Button` to build the layout
847
+ your flow needs. Eight colors, two sizes, and a ghost mode cover most
848
+ feedback scenarios.</div>
849
+ <div class="kv"><span class="chip">summary: Feedback banner with color variants, optional icon, and dismiss</span><span class="chip">example: &lt;Alert color=&quot;success&quot; size=&quot;sm&quot;&gt;
850
+ &lt;Alert.Content&gt;
851
+ &lt;Alert.Title&gt;Policy saved&lt;/Alert.Title&gt;
852
+ &lt;Alert.Paragraph&gt;Your changes are live.&lt;/Alert.Paragraph&gt;
853
+ &lt;/Alert.Content&gt;
854
+ &lt;/Alert&gt;</span><span class="chip">example: &lt;Alert color=&quot;warning&quot; onDismiss={() =&gt; setOpen(false)}&gt;
855
+ &lt;Alert.Content&gt;
856
+ &lt;Alert.Title&gt;Session expiring&lt;/Alert.Title&gt;
857
+ &lt;Alert.Paragraph&gt;Renew to continue editing.&lt;/Alert.Paragraph&gt;
858
+ &lt;/Alert.Content&gt;
859
+ &lt;Alert.Actions&gt;
860
+ &lt;Alert.Button onClick={renew}&gt;Renew session&lt;/Alert.Button&gt;
861
+ &lt;/Alert.Actions&gt;
862
+ &lt;/Alert&gt;</span><span class="chip">example: &lt;Alert color=&quot;danger&quot; ghost&gt;
863
+ &lt;Alert.Paragraph&gt;This field is required.&lt;/Alert.Paragraph&gt;
864
+ &lt;/Alert&gt;</span></div>
767
865
  </div>
768
866
 
769
867
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -771,6 +869,7 @@
771
869
 
772
870
  <input id="c-1-components-alert-stories" class="tg tg-stories" type="checkbox" hidden />
773
871
 
872
+
774
873
  <input id="c-1-components-alert-props" class="tg tg-props" type="checkbox" hidden />
775
874
 
776
875
  <div class="panels">
@@ -780,7 +879,7 @@
780
879
  <div class="panel panel-props">
781
880
  <div class="note ok">
782
881
  <div class="row">
783
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
882
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
784
883
  <span class="badge ok">6 prop types</span>
785
884
  </div>
786
885
  <pre><code>Component: src/alert/alert.tsx::Alert</code></pre>
@@ -794,7 +893,7 @@
794
893
  * - `info` — informational highlight.
795
894
  * - `creative`, `dynamic`, `playful` — brand-aligned accents.
796
895
  */
797
- color?: &quot;neutral&quot; | &quot;success&quot; | &quot;danger&quot; | &quot;warning&quot; | &quot;info&quot; | &quot;creative&quot; | &quot;dynamic&quot; | &quot;playful&quot; = neutral
896
+ color?: &quot;neutral&quot; | &quot;success&quot; | &quot;danger&quot; | &quot;warning&quot; | &quot;info&quot; | &quot;creative&quot; | &quot;dynamic&quot; | &quot;playful&quot; = &#39;neutral&#39;
798
897
 
799
898
  /**
800
899
  * When `true`, removes background and padding so the alert blends inline
@@ -811,19 +910,19 @@ hasIcon?: boolean = true
811
910
  /**
812
911
  * Overrides the default icon for the current `color`. Receives the slot-computed className so color tokens still apply.
813
912
  */
814
- icon?: ComponentType&lt;SVGProps&lt;SVGSVGElement&gt;&gt;
913
+ icon?: ComponentType&lt;SVGProps&lt;SVGSVGElement&gt;&gt; | undefined
815
914
 
816
915
  /**
817
916
  * Fires when the dismiss button is clicked. When provided, renders an `iconOnly` close button with `aria-label=&quot;Dismiss&quot;`.
818
917
  */
819
- onDismiss?: (() =&gt; void)
918
+ onDismiss?: () =&gt; void
820
919
 
821
920
  /**
822
921
  * Size treatment. Defaults to `&#39;sm&#39;`.
823
922
  * - `sm` — compact inline alerts (1rem padding, 14/12px typography).
824
923
  * - `md` — prominent standalone alerts (2rem padding, 18/14px typography).
825
924
  */
826
- size?: AlertSizeType = sm</code></pre>
925
+ size?: &quot;sm&quot; | &quot;md&quot; = &#39;sm&#39;</code></pre>
827
926
  </div>
828
927
  </div>
829
928
 
@@ -845,7 +944,8 @@ size?: AlertSizeType = sm</code></pre>
845
944
  <span class="badge ok">story ok</span>
846
945
  </div>
847
946
  <div>Default args playground for Alert</div>
848
- <div class="hint">Args-controlled playground. Toggle `color`, `size`, `ghost`, `hasIcon`, and `onDismiss` from the Controls panel to explore every visual combination.</div>
947
+ <div class="hint">Args-controlled playground. Toggle `color`, `size`, `ghost`, `hasIcon`, and
948
+ `onDismiss` from the Controls panel to explore every visual combination.</div>
849
949
  <pre><code>const Default = () =&gt; &lt;Alert
850
950
  color=&quot;neutral&quot;
851
951
  size=&quot;sm&quot;
@@ -864,7 +964,8 @@ size?: AlertSizeType = sm</code></pre>
864
964
  <span class="badge ok">story ok</span>
865
965
  </div>
866
966
  <div>Neutral color (default)</div>
867
- <div class="hint">Neutral color is the default and carries no strong semantic signal — use it for generic inline information.</div>
967
+ <div class="hint">Neutral color is the default and carries no strong semantic signal — use it
968
+ for generic inline information.</div>
868
969
  <pre><code>const Neutral = () =&gt; &lt;Alert
869
970
  color=&quot;neutral&quot;
870
971
  size=&quot;sm&quot;
@@ -883,7 +984,8 @@ size?: AlertSizeType = sm</code></pre>
883
984
  <span class="badge ok">story ok</span>
884
985
  </div>
885
986
  <div>Success color for positive outcomes</div>
886
- <div class="hint">Success color confirms a positive outcome — saved record, completed task, healthy state.</div>
987
+ <div class="hint">Success color confirms a positive outcome — saved record, completed task,
988
+ healthy state.</div>
887
989
  <pre><code>const Success = () =&gt; &lt;Alert
888
990
  color=&quot;success&quot;
889
991
  size=&quot;sm&quot;
@@ -902,7 +1004,8 @@ size?: AlertSizeType = sm</code></pre>
902
1004
  <span class="badge ok">story ok</span>
903
1005
  </div>
904
1006
  <div>Danger color for errors and destructive outcomes</div>
905
- <div class="hint">Danger color flags errors and destructive outcomes that require the user&#39;s attention.</div>
1007
+ <div class="hint">Danger color flags errors and destructive outcomes that require the user&#39;s
1008
+ attention.</div>
906
1009
  <pre><code>const Danger = () =&gt; &lt;Alert
907
1010
  color=&quot;danger&quot;
908
1011
  size=&quot;sm&quot;
@@ -959,7 +1062,8 @@ size?: AlertSizeType = sm</code></pre>
959
1062
  <span class="badge ok">story ok</span>
960
1063
  </div>
961
1064
  <div>Creative brand accent color</div>
962
- <div class="hint">Creative color uses a brand-aligned purple accent for marketing or onboarding moments.</div>
1065
+ <div class="hint">Creative color uses a brand-aligned purple accent for marketing or
1066
+ onboarding moments.</div>
963
1067
  <pre><code>const Creative = () =&gt; &lt;Alert
964
1068
  color=&quot;creative&quot;
965
1069
  size=&quot;sm&quot;
@@ -978,7 +1082,8 @@ size?: AlertSizeType = sm</code></pre>
978
1082
  <span class="badge ok">story ok</span>
979
1083
  </div>
980
1084
  <div>Dynamic brand accent color</div>
981
- <div class="hint">Dynamic color uses a brand-aligned orange accent for activity or momentum-focused content.</div>
1085
+ <div class="hint">Dynamic color uses a brand-aligned orange accent for activity or
1086
+ momentum-focused content.</div>
982
1087
  <pre><code>const Dynamic = () =&gt; &lt;Alert
983
1088
  color=&quot;dynamic&quot;
984
1089
  size=&quot;sm&quot;
@@ -997,7 +1102,8 @@ size?: AlertSizeType = sm</code></pre>
997
1102
  <span class="badge ok">story ok</span>
998
1103
  </div>
999
1104
  <div>Playful brand accent color</div>
1000
- <div class="hint">Playful color uses a brand-aligned pink accent for lighter or celebratory content.</div>
1105
+ <div class="hint">Playful color uses a brand-aligned pink accent for lighter or celebratory
1106
+ content.</div>
1001
1107
  <pre><code>const Playful = () =&gt; &lt;Alert
1002
1108
  color=&quot;playful&quot;
1003
1109
  size=&quot;sm&quot;
@@ -1016,7 +1122,9 @@ size?: AlertSizeType = sm</code></pre>
1016
1122
  <span class="badge ok">story ok</span>
1017
1123
  </div>
1018
1124
  <div>Ghost mode for inline, low-emphasis alerts</div>
1019
- <div class="hint">Ghost mode removes the background and padding so the alert blends inline with surrounding text (e.g., form field errors). Colors switch to the ghost token ramp for lower visual weight.</div>
1125
+ <div class="hint">Ghost mode removes the background and padding so the alert blends inline
1126
+ with surrounding text (e.g., form field errors). Colors switch to the ghost
1127
+ token ramp for lower visual weight.</div>
1020
1128
  <pre><code>const Ghost = () =&gt; &lt;Alert
1021
1129
  color=&quot;danger&quot;
1022
1130
  size=&quot;sm&quot;
@@ -1035,7 +1143,8 @@ size?: AlertSizeType = sm</code></pre>
1035
1143
  <span class="badge ok">story ok</span>
1036
1144
  </div>
1037
1145
  <div>Small size (default, compact)</div>
1038
- <div class="hint">Small size (default) uses compact padding and 14/12px typography — suitable for inline alerts inside forms, tables, or cards.</div>
1146
+ <div class="hint">Small size (default) uses compact padding and 14/12px typography — suitable
1147
+ for inline alerts inside forms, tables, or cards.</div>
1039
1148
  <pre><code>const SmallSize = () =&gt; &lt;Alert
1040
1149
  color=&quot;neutral&quot;
1041
1150
  size=&quot;sm&quot;
@@ -1054,7 +1163,8 @@ size?: AlertSizeType = sm</code></pre>
1054
1163
  <span class="badge ok">story ok</span>
1055
1164
  </div>
1056
1165
  <div>Medium size (prominent, standalone)</div>
1057
- <div class="hint">Medium size uses larger padding and 18/14px typography — suitable for standalone alerts in empty states, modals, or dedicated feedback regions.</div>
1166
+ <div class="hint">Medium size uses larger padding and 18/14px typography — suitable for
1167
+ standalone alerts in empty states, modals, or dedicated feedback regions.</div>
1058
1168
  <pre><code>const MediumSize = () =&gt; &lt;Alert
1059
1169
  color=&quot;neutral&quot;
1060
1170
  size=&quot;md&quot;
@@ -1073,7 +1183,8 @@ size?: AlertSizeType = sm</code></pre>
1073
1183
  <span class="badge ok">story ok</span>
1074
1184
  </div>
1075
1185
  <div>Alert with a dismiss button</div>
1076
- <div class="hint">Dismissible alert. Providing `onDismiss` shows an icon-only close button with `aria-label=&quot;Dismiss&quot;` that inherits the alert&#39;s color.</div>
1186
+ <div class="hint">Dismissible alert. Providing `onDismiss` shows an icon-only close button
1187
+ with `aria-label=&quot;Dismiss&quot;` that inherits the alert&#39;s color.</div>
1077
1188
  <pre><code>const WithDismiss = () =&gt; &lt;Alert color=&quot;warning&quot; size=&quot;sm&quot; ghost={false} hasIcon onDismiss={fn()}&gt;
1078
1189
  &lt;Alert.Content&gt;
1079
1190
  &lt;Alert.Title&gt;Title&lt;/Alert.Title&gt;
@@ -1087,7 +1198,8 @@ size?: AlertSizeType = sm</code></pre>
1087
1198
  <span class="badge ok">story ok</span>
1088
1199
  </div>
1089
1200
  <div>Alert with a trailing action button</div>
1090
- <div class="hint">Alert with a trailing action pinned to the right edge. Use `Alert.Actions` + `Alert.Button` for the common &quot;message + action&quot; pattern.</div>
1201
+ <div class="hint">Alert with a trailing action pinned to the right edge. Use `Alert.Actions`
1202
+ + `Alert.Button` for the common &quot;message + action&quot; pattern.</div>
1091
1203
  <pre><code>const WithActions = () =&gt; &lt;Alert
1092
1204
  color=&quot;info&quot;
1093
1205
  size=&quot;sm&quot;
@@ -1109,7 +1221,8 @@ size?: AlertSizeType = sm</code></pre>
1109
1221
  <span class="badge ok">story ok</span>
1110
1222
  </div>
1111
1223
  <div>Alert with both dismiss and action</div>
1112
- <div class="hint">Alert combining a dismiss button with a trailing action. Dismiss is pinned to the right edge after the actions.</div>
1224
+ <div class="hint">Alert combining a dismiss button with a trailing action. Dismiss is pinned
1225
+ to the right edge after the actions.</div>
1113
1226
  <pre><code>const WithDismissAndAction = () =&gt; &lt;Alert
1114
1227
  color=&quot;warning&quot;
1115
1228
  size=&quot;md&quot;
@@ -1131,7 +1244,8 @@ size?: AlertSizeType = sm</code></pre>
1131
1244
  <span class="badge ok">story ok</span>
1132
1245
  </div>
1133
1246
  <div>Alert without the default icon</div>
1134
- <div class="hint">Alert rendered without the built-in color icon. Use `hasIcon={false}` when the surrounding context already conveys the semantic intent.</div>
1247
+ <div class="hint">Alert rendered without the built-in color icon. Use `hasIcon={false}` when
1248
+ the surrounding context already conveys the semantic intent.</div>
1135
1249
  <pre><code>const WithoutIcon = () =&gt; &lt;Alert
1136
1250
  color=&quot;info&quot;
1137
1251
  size=&quot;sm&quot;
@@ -1150,7 +1264,9 @@ size?: AlertSizeType = sm</code></pre>
1150
1264
  <span class="badge ok">story ok</span>
1151
1265
  </div>
1152
1266
  <div>Alert with a custom icon override</div>
1153
- <div class="hint">Alert with a caller-supplied icon that replaces the default color icon. The custom icon receives the slot-computed className so color tokens still apply.</div>
1267
+ <div class="hint">Alert with a caller-supplied icon that replaces the default color icon. The
1268
+ custom icon receives the slot-computed className so color tokens still
1269
+ apply.</div>
1154
1270
  <pre><code>const WithCustomIcon = () =&gt; &lt;Alert
1155
1271
  color=&quot;creative&quot;
1156
1272
  size=&quot;sm&quot;
@@ -1170,7 +1286,9 @@ size?: AlertSizeType = sm</code></pre>
1170
1286
  <span class="badge ok">story ok</span>
1171
1287
  </div>
1172
1288
  <div>Alert paragraph rendered from HTML</div>
1173
- <div class="hint">Alert rendering a paragraph from pre-sanitized HTML via `Alert.ParagraphHtml`. The caller is responsible for sanitizing the HTML string before passing it in.</div>
1289
+ <div class="hint">Alert rendering a paragraph from pre-sanitized HTML via
1290
+ `Alert.ParagraphHtml`. The caller is responsible for sanitizing the HTML
1291
+ string before passing it in.</div>
1174
1292
  <pre><code>const WithParagraphHtml = () =&gt; &lt;Alert
1175
1293
  color=&quot;success&quot;
1176
1294
  size=&quot;sm&quot;
@@ -1190,7 +1308,8 @@ size?: AlertSizeType = sm</code></pre>
1190
1308
  <span class="badge ok">story ok</span>
1191
1309
  </div>
1192
1310
  <div>Alert with a pictogram illustration</div>
1193
- <div class="hint">Alert with a 64×64 pictogram in place of the inline icon. Use `Alert.Pictograms` when the message benefits from a richer illustration.</div>
1311
+ <div class="hint">Alert with a 64×64 pictogram in place of the inline icon. Use
1312
+ `Alert.Pictograms` when the message benefits from a richer illustration.</div>
1194
1313
  <pre><code>const WithPictograms = () =&gt; &lt;Alert
1195
1314
  color=&quot;info&quot;
1196
1315
  size=&quot;md&quot;
@@ -1216,7 +1335,8 @@ size?: AlertSizeType = sm</code></pre>
1216
1335
  <span class="badge ok">story ok</span>
1217
1336
  </div>
1218
1337
  <div>Alert with only a paragraph body</div>
1219
- <div class="hint">Alert rendered with only a paragraph — no title. The root omits `aria-labelledby` since there is no title to reference.</div>
1338
+ <div class="hint">Alert rendered with only a paragraph — no title. The root omits
1339
+ `aria-labelledby` since there is no title to reference.</div>
1220
1340
  <pre><code>const OnlyParagraph = () =&gt; &lt;Alert
1221
1341
  color=&quot;neutral&quot;
1222
1342
  size=&quot;sm&quot;
@@ -1232,7 +1352,8 @@ size?: AlertSizeType = sm</code></pre>
1232
1352
  <span class="badge ok">story ok</span>
1233
1353
  </div>
1234
1354
  <div>Alert with actions placed below the content</div>
1235
- <div class="hint">Action button rendered inline below the paragraphs, inside `Alert.Content`, rather than pinned to the right via `Alert.Actions`.</div>
1355
+ <div class="hint">Action button rendered inline below the paragraphs, inside
1356
+ `Alert.Content`, rather than pinned to the right via `Alert.Actions`.</div>
1236
1357
  <pre><code>const WithActionsBelow = () =&gt; &lt;Alert
1237
1358
  color=&quot;success&quot;
1238
1359
  size=&quot;sm&quot;
@@ -1254,7 +1375,8 @@ size?: AlertSizeType = sm</code></pre>
1254
1375
  <span class="badge ok">story ok</span>
1255
1376
  </div>
1256
1377
  <div>Visual comparison of all Alert colors</div>
1257
- <div class="hint">All eight colors in their primary (non-ghost) treatment, stacked for comparison. Each alert uses the built-in icon mapping for its color.</div>
1378
+ <div class="hint">All eight colors in their primary (non-ghost) treatment, stacked for
1379
+ comparison. Each alert uses the built-in icon mapping for its color.</div>
1258
1380
  <pre><code>const AllColors = () =&gt; (
1259
1381
  &lt;Stack&gt;
1260
1382
  {COLORS.map(color =&gt; (
@@ -1276,7 +1398,8 @@ size?: AlertSizeType = sm</code></pre>
1276
1398
  <span class="badge ok">story ok</span>
1277
1399
  </div>
1278
1400
  <div>Visual comparison of all Alert colors in ghost mode</div>
1279
- <div class="hint">All eight colors in ghost mode, stacked for comparison. Ghost alerts use a lower-weight token ramp and omit background + padding.</div>
1401
+ <div class="hint">All eight colors in ghost mode, stacked for comparison. Ghost alerts use a
1402
+ lower-weight token ramp and omit background + padding.</div>
1280
1403
  <pre><code>const AllGhostColors = () =&gt; (
1281
1404
  &lt;Stack&gt;
1282
1405
  {COLORS.map(color =&gt; (
@@ -1294,6 +1417,7 @@ size?: AlertSizeType = sm</code></pre>
1294
1417
  </div>
1295
1418
  </div>
1296
1419
 
1420
+
1297
1421
  </div>
1298
1422
  </article>
1299
1423
  <article
@@ -1312,12 +1436,17 @@ size?: AlertSizeType = sm</code></pre>
1312
1436
 
1313
1437
  <label for="c-2-components-avatar-stories" class="badge ok as-toggle">22 stories</label>
1314
1438
 
1439
+
1315
1440
  </div>
1316
1441
  </div>
1317
1442
  <div class="meta" title="./src/avatar/avatar.stories.tsx">components-avatar · ./src/avatar/avatar.stories.tsx</div>
1318
-
1319
- <div class="hint">Avatar displays a user&#39;s profile image, initials, or a fallback icon. Use for user identification in lists, headers, cards, and comment threads. Supports multiple shapes (`circle`, `square`, `pillow`, `pentagon`), content types (`photo`, `initials`, `isotype`), and sizes from `xs` (24px) to `4xl` (128px).</div>
1320
-
1443
+ <div>Displays a user&#39;s profile image, initials, or fallback icon</div>
1444
+ <div class="hint">Avatar displays a user&#39;s profile image, initials, or a fallback icon.
1445
+ Use for user identification in lists, headers, cards, and comment threads.
1446
+ Supports multiple shapes (`circle`, `square`, `pillow`, `pentagon`),
1447
+ content types (`photo`, `initials`, `isotype`), and sizes from `xs` (24px)
1448
+ to `4xl` (128px).</div>
1449
+ <div class="kv"><span class="chip">summary: Displays a user&#39;s profile image, initials, or fallback icon</span><span class="chip">example: &lt;Avatar src=&quot;/photos/jane.jpg&quot; alt=&quot;Jane Doe&quot; size=&quot;md&quot; variant=&quot;circle&quot; /&gt;</span><span class="chip">example: &lt;Avatar fallback=&quot;JD&quot; size=&quot;lg&quot; variant=&quot;square&quot; /&gt;</span></div>
1321
1450
  </div>
1322
1451
 
1323
1452
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -1325,6 +1454,7 @@ size?: AlertSizeType = sm</code></pre>
1325
1454
 
1326
1455
  <input id="c-2-components-avatar-stories" class="tg tg-stories" type="checkbox" hidden />
1327
1456
 
1457
+
1328
1458
  <input id="c-2-components-avatar-props" class="tg tg-props" type="checkbox" hidden />
1329
1459
 
1330
1460
  <div class="panels">
@@ -1334,7 +1464,7 @@ size?: AlertSizeType = sm</code></pre>
1334
1464
  <div class="panel panel-props">
1335
1465
  <div class="note ok">
1336
1466
  <div class="row">
1337
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
1467
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
1338
1468
  <span class="badge ok">8 prop types</span>
1339
1469
  </div>
1340
1470
  <pre><code>Component: src/avatar/avatar.tsx::Avatar</code></pre>
@@ -1412,7 +1542,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1412
1542
  <span class="badge ok">story ok</span>
1413
1543
  </div>
1414
1544
  <div>Default avatar with fallback initials</div>
1415
- <div class="hint">The default avatar with fallback initials. Renders as a medium circle when no image source is provided.</div>
1545
+ <div class="hint">The default avatar with fallback initials. Renders as a medium circle
1546
+ when no image source is provided.</div>
1416
1547
  <pre><code>const Default = () =&gt; &lt;Avatar fallback=&quot;JD&quot; size=&quot;md&quot; variant=&quot;circle&quot; type=&quot;photo&quot; /&gt;;</code></pre>
1417
1548
  </div>
1418
1549
  <div class="note ok">
@@ -1421,7 +1552,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1421
1552
  <span class="badge ok">story ok</span>
1422
1553
  </div>
1423
1554
  <div>Avatar with a profile image</div>
1424
- <div class="hint">Avatar displaying a user profile photo. The image fills the avatar shape and the fallback is hidden while the image loads successfully.</div>
1555
+ <div class="hint">Avatar displaying a user profile photo. The image fills the avatar shape
1556
+ and the fallback is hidden while the image loads successfully.</div>
1425
1557
  <pre><code>const WithImage = () =&gt; &lt;Avatar
1426
1558
  fallback=&quot;JD&quot;
1427
1559
  size=&quot;md&quot;
@@ -1436,7 +1568,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1436
1568
  <span class="badge ok">story ok</span>
1437
1569
  </div>
1438
1570
  <div>Fallback content shown when image is unavailable</div>
1439
- <div class="hint">When the image fails to load, the fallback content is displayed. Pass initials, an icon, or any ReactNode as the `fallback` prop.</div>
1571
+ <div class="hint">When the image fails to load, the fallback content is displayed.
1572
+ Pass initials, an icon, or any ReactNode as the `fallback` prop.</div>
1440
1573
  <pre><code>const WithFallbackInitials = () =&gt; &lt;Avatar
1441
1574
  fallback=&quot;AM&quot;
1442
1575
  size=&quot;md&quot;
@@ -1459,7 +1592,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1459
1592
  <span class="badge ok">story ok</span>
1460
1593
  </div>
1461
1594
  <div>Square-shaped avatar for workspaces</div>
1462
- <div class="hint">The square variant uses a rounded rectangle, suitable for workspace, team, or organization icons.</div>
1595
+ <div class="hint">The square variant uses a rounded rectangle, suitable for workspace,
1596
+ team, or organization icons.</div>
1463
1597
  <pre><code>const Square = () =&gt; &lt;Avatar fallback=&quot;WS&quot; size=&quot;md&quot; variant=&quot;square&quot; type=&quot;photo&quot; /&gt;;</code></pre>
1464
1598
  </div>
1465
1599
  <div class="note ok">
@@ -1468,7 +1602,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1468
1602
  <span class="badge ok">story ok</span>
1469
1603
  </div>
1470
1604
  <div>Pillow-shaped avatar with organic squircle</div>
1471
- <div class="hint">The pillow variant uses a soft, organic squircle shape for a friendly and distinctive appearance.</div>
1605
+ <div class="hint">The pillow variant uses a soft, organic squircle shape for a
1606
+ friendly and distinctive appearance.</div>
1472
1607
  <pre><code>const Pillow = () =&gt; &lt;Avatar fallback=&quot;PL&quot; size=&quot;md&quot; variant=&quot;pillow&quot; type=&quot;photo&quot; /&gt;;</code></pre>
1473
1608
  </div>
1474
1609
  <div class="note ok">
@@ -1477,7 +1612,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1477
1612
  <span class="badge ok">story ok</span>
1478
1613
  </div>
1479
1614
  <div>Pentagon-shaped avatar for unique identity</div>
1480
- <div class="hint">The pentagon variant uses a five-sided mask for a unique visual identity. Note: the border is hidden in this variant due to the mask shape.</div>
1615
+ <div class="hint">The pentagon variant uses a five-sided mask for a unique visual identity.
1616
+ Note: the border is hidden in this variant due to the mask shape.</div>
1481
1617
  <pre><code>const Pentagon = () =&gt; &lt;Avatar fallback=&quot;PT&quot; size=&quot;md&quot; variant=&quot;pentagon&quot; type=&quot;photo&quot; /&gt;;</code></pre>
1482
1618
  </div>
1483
1619
  <div class="note ok">
@@ -1486,7 +1622,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1486
1622
  <span class="badge ok">story ok</span>
1487
1623
  </div>
1488
1624
  <div>Photo type fills the avatar shape edge-to-edge</div>
1489
- <div class="hint">The `photo` type is the default. The image fills the avatar shape edge-to-edge, which is ideal for user profile photographs.</div>
1625
+ <div class="hint">The `photo` type is the default. The image fills the avatar shape edge-to-edge,
1626
+ which is ideal for user profile photographs.</div>
1490
1627
  <pre><code>const TypePhoto = () =&gt; &lt;Avatar
1491
1628
  fallback=&quot;AM&quot;
1492
1629
  size=&quot;md&quot;
@@ -1501,7 +1638,9 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1501
1638
  <span class="badge ok">story ok</span>
1502
1639
  </div>
1503
1640
  <div>Initials type for users without a profile photo</div>
1504
- <div class="hint">The `initials` type is intended when no image is available and the avatar stands in for a user with their initials. The fallback text is centered within the avatar shape.</div>
1641
+ <div class="hint">The `initials` type is intended when no image is available and the avatar
1642
+ stands in for a user with their initials. The fallback text is centered
1643
+ within the avatar shape.</div>
1505
1644
  <pre><code>const TypeInitials = () =&gt; &lt;Avatar fallback=&quot;JD&quot; size=&quot;md&quot; variant=&quot;circle&quot; type=&quot;initials&quot; /&gt;;</code></pre>
1506
1645
  </div>
1507
1646
  <div class="note ok">
@@ -1510,7 +1649,10 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1510
1649
  <span class="badge ok">story ok</span>
1511
1650
  </div>
1512
1651
  <div>Isotype type centers a brand icon inside the shape</div>
1513
- <div class="hint">The `isotype` type renders the image smaller than the avatar shape so a brand or organization icon sits centered inside the container rather than filling it. Use for workspace, team, or company avatars where a logo should remain legible inside the bounding shape.</div>
1652
+ <div class="hint">The `isotype` type renders the image smaller than the avatar shape so a
1653
+ brand or organization icon sits centered inside the container rather than
1654
+ filling it. Use for workspace, team, or company avatars where a logo
1655
+ should remain legible inside the bounding shape.</div>
1514
1656
  <pre><code>const TypeIsotype = () =&gt; &lt;Avatar
1515
1657
  fallback=&quot;FG&quot;
1516
1658
  size=&quot;md&quot;
@@ -1525,7 +1667,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1525
1667
  <span class="badge ok">story ok</span>
1526
1668
  </div>
1527
1669
  <div>Visual comparison of all avatar content types</div>
1528
- <div class="hint">All content types shown side by side: `photo` fills the shape, `initials` centers text, and `isotype` shrinks a brand icon inside the bounding shape.</div>
1670
+ <div class="hint">All content types shown side by side: `photo` fills the shape, `initials`
1671
+ centers text, and `isotype` shrinks a brand icon inside the bounding shape.</div>
1529
1672
  <pre><code>const AllTypes = () =&gt; (
1530
1673
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1531
1674
  &lt;Avatar
@@ -1553,7 +1696,9 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1553
1696
  <span class="badge ok">story ok</span>
1554
1697
  </div>
1555
1698
  <div>Isotype scaling across all avatar sizes</div>
1556
- <div class="hint">The isotype icon scales proportionally smaller than the avatar shape at every size, keeping a consistent inset around the logo from `xs` (24px) to `4xl` (128px).</div>
1699
+ <div class="hint">The isotype icon scales proportionally smaller than the avatar shape at
1700
+ every size, keeping a consistent inset around the logo from `xs` (24px)
1701
+ to `4xl` (128px).</div>
1557
1702
  <pre><code>const AllSizesIsotype = () =&gt; (
1558
1703
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1559
1704
  {([&#39;xs&#39;, &#39;sm&#39;, &#39;md&#39;, &#39;lg&#39;, &#39;xl&#39;, &#39;2xl&#39;, &#39;3xl&#39;, &#39;4xl&#39;] as const).map(size =&gt; (
@@ -1612,7 +1757,9 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1612
1757
  <span class="badge ok">story ok</span>
1613
1758
  </div>
1614
1759
  <div>Colorized avatar based on user name</div>
1615
- <div class="hint">The `colorize` prop deterministically maps a string (typically a user name) to a color from the palette, applying a tinted background and matching text color. Useful for distinguishing users in lists without profile photos.</div>
1760
+ <div class="hint">The `colorize` prop deterministically maps a string (typically a user name)
1761
+ to a color from the palette, applying a tinted background and matching
1762
+ text color. Useful for distinguishing users in lists without profile photos.</div>
1616
1763
  <pre><code>const Colorized = () =&gt; &lt;Avatar fallback=&quot;JD&quot; size=&quot;md&quot; variant=&quot;circle&quot; type=&quot;photo&quot; colorize=&quot;jane doe&quot; /&gt;;</code></pre>
1617
1764
  </div>
1618
1765
  <div class="note ok">
@@ -1621,7 +1768,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1621
1768
  <span class="badge ok">story ok</span>
1622
1769
  </div>
1623
1770
  <div>Multiple colorized avatars for visual distinction</div>
1624
- <div class="hint">Multiple colorized avatars showing how different names map to different colors from the palette for visual distinction.</div>
1771
+ <div class="hint">Multiple colorized avatars showing how different names map to different
1772
+ colors from the palette for visual distinction.</div>
1625
1773
  <pre><code>const AllColorized = () =&gt; (
1626
1774
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1627
1775
  {[&#39;alice&#39;, &#39;bob&#39;, &#39;carol&#39;, &#39;dave&#39;, &#39;eve&#39;, &#39;frank&#39;, &#39;grace&#39;, &#39;henry&#39;, &#39;iris&#39;].map(name =&gt; (
@@ -1636,7 +1784,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1636
1784
  <span class="badge ok">story ok</span>
1637
1785
  </div>
1638
1786
  <div>Visual comparison of all avatar sizes</div>
1639
- <div class="hint">All available sizes displayed together for visual comparison. Sizes range from `xs` (24px) to `4xl` (128px).</div>
1787
+ <div class="hint">All available sizes displayed together for visual comparison.
1788
+ Sizes range from `xs` (24px) to `4xl` (128px).</div>
1640
1789
  <pre><code>const AllSizes = () =&gt; (
1641
1790
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1642
1791
  {([&#39;xs&#39;, &#39;sm&#39;, &#39;md&#39;, &#39;lg&#39;, &#39;xl&#39;, &#39;2xl&#39;, &#39;3xl&#39;, &#39;4xl&#39;] as const).map(size =&gt; (
@@ -1651,7 +1800,8 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1651
1800
  <span class="badge ok">story ok</span>
1652
1801
  </div>
1653
1802
  <div>All avatar sizes with a profile image</div>
1654
- <div class="hint">All sizes with a profile image to verify image scaling and quality across the full size range from `xs` (24px) to `4xl` (128px).</div>
1803
+ <div class="hint">All sizes with a profile image to verify image scaling and quality
1804
+ across the full size range from `xs` (24px) to `4xl` (128px).</div>
1655
1805
  <pre><code>const AllSizesWithImage = () =&gt; (
1656
1806
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1657
1807
  {([&#39;xs&#39;, &#39;sm&#39;, &#39;md&#39;, &#39;lg&#39;, &#39;xl&#39;, &#39;2xl&#39;, &#39;3xl&#39;, &#39;4xl&#39;] as const).map(size =&gt; (
@@ -1672,7 +1822,9 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1672
1822
  <span class="badge ok">story ok</span>
1673
1823
  </div>
1674
1824
  <div>Visual comparison of all avatar shapes</div>
1675
- <div class="hint">All available shape variants displayed together for visual comparison. Each variant serves a different use case: user photos, workspaces, friendly branding, and unique identity.</div>
1825
+ <div class="hint">All available shape variants displayed together for visual comparison.
1826
+ Each variant serves a different use case: user photos, workspaces,
1827
+ friendly branding, and unique identity.</div>
1676
1828
  <pre><code>const AllVariants = () =&gt; (
1677
1829
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1678
1830
  {([&#39;circle&#39;, &#39;square&#39;, &#39;pillow&#39;, &#39;pentagon&#39;] as const).map(variant =&gt; (
@@ -1692,7 +1844,9 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1692
1844
  <span class="badge ok">story ok</span>
1693
1845
  </div>
1694
1846
  <div>All avatar shapes with a profile image</div>
1695
- <div class="hint">All shape variants with a profile image to show how each mask clips the photo. Particularly useful for verifying the pentagon mask and pillow shape render correctly with real imagery.</div>
1847
+ <div class="hint">All shape variants with a profile image to show how each mask clips
1848
+ the photo. Particularly useful for verifying the pentagon mask and
1849
+ pillow shape render correctly with real imagery.</div>
1696
1850
  <pre><code>const AllVariantsWithImage = () =&gt; (
1697
1851
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;1rem&#39; }}&gt;
1698
1852
  {([&#39;circle&#39;, &#39;square&#39;, &#39;pillow&#39;, &#39;pentagon&#39;] as const).map(variant =&gt; (
@@ -1710,6 +1864,7 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1710
1864
  </div>
1711
1865
  </div>
1712
1866
 
1867
+
1713
1868
  </div>
1714
1869
  </article>
1715
1870
  <article
@@ -1724,16 +1879,24 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1724
1879
  <div class="title">
1725
1880
  <h2><span class="status-dot dot-ok"></span> AvatarGroup</h2>
1726
1881
  <div class="badges">
1727
- <label for="c-3-components-avatargroup-props" class="badge ok as-toggle">3 prop types</label>
1882
+ <label for="c-3-components-avatargroup-props" class="badge ok as-toggle">4 prop types</label>
1728
1883
 
1729
1884
  <label for="c-3-components-avatargroup-stories" class="badge ok as-toggle">4 stories</label>
1730
1885
 
1886
+
1731
1887
  </div>
1732
1888
  </div>
1733
1889
  <div class="meta" title="./src/avatar-group/avatar-group.stories.tsx">components-avatargroup · ./src/avatar-group/avatar-group.stories.tsx</div>
1734
-
1735
- <div class="hint">AvatarGroup stacks `&lt;Avatar&gt;` children into an overlapping row and collapses everything past `max` into a trailing `+N` bubble. The group owns the layout: it forces a uniform `size` (and `variant`, when set) and rings each avatar in the surface color so they read as separate.</div>
1736
-
1890
+ <div>Overlapping row of avatars, collapsing the rest into `+N`</div>
1891
+ <div class="hint">AvatarGroup stacks `&lt;Avatar&gt;` children into an overlapping row and collapses
1892
+ everything past `max` into a trailing `+N` bubble. The group owns the layout:
1893
+ it forces a uniform `size` (and `variant`, when set) and rings each avatar in
1894
+ the surface color so they read as separate.</div>
1895
+ <div class="kv"><span class="chip">summary: Overlapping row of avatars, collapsing the rest into `+N`</span><span class="chip">example: &lt;AvatarGroup size=&quot;sm&quot; max={3}&gt;
1896
+ &lt;Avatar fallback=&quot;AL&quot; colorize=&quot;Ada Lovelace&quot; /&gt;
1897
+ &lt;Avatar fallback=&quot;GH&quot; colorize=&quot;Grace Hopper&quot; /&gt;
1898
+ &lt;Avatar fallback=&quot;MK&quot; colorize=&quot;Mary Kom&quot; /&gt;
1899
+ &lt;/AvatarGroup&gt;</span></div>
1737
1900
  </div>
1738
1901
 
1739
1902
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -1741,6 +1904,7 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1741
1904
 
1742
1905
  <input id="c-3-components-avatargroup-stories" class="tg tg-stories" type="checkbox" hidden />
1743
1906
 
1907
+
1744
1908
  <input id="c-3-components-avatargroup-props" class="tg tg-props" type="checkbox" hidden />
1745
1909
 
1746
1910
  <div class="panels">
@@ -1750,14 +1914,16 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1750
1914
  <div class="panel panel-props">
1751
1915
  <div class="note ok">
1752
1916
  <div class="row">
1753
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
1754
- <span class="badge ok">3 prop types</span>
1917
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
1918
+ <span class="badge ok">4 prop types</span>
1755
1919
  </div>
1756
1920
  <pre><code>Component: src/avatar-group/avatar-group.tsx::AvatarGroup</code></pre>
1757
1921
  <pre><code>Props:</code></pre>
1758
- <pre><code>max?: number = 3
1922
+ <pre><code>children?: ReactNode
1923
+
1924
+ max?: number = 3
1759
1925
 
1760
- size?: &quot;sm&quot; | &quot;md&quot; | &quot;xs&quot; | &quot;lg&quot; | &quot;xl&quot; | &quot;2xl&quot; | &quot;3xl&quot; | &quot;4xl&quot; = md
1926
+ size?: &quot;sm&quot; | &quot;md&quot; | &quot;xs&quot; | &quot;lg&quot; | &quot;xl&quot; | &quot;2xl&quot; | &quot;3xl&quot; | &quot;4xl&quot; = &#39;md&#39;
1761
1927
 
1762
1928
  /**
1763
1929
  * Shape applied uniformly to every avatar and the `+N` bubble. Defaults to `circle`.
@@ -1838,6 +2004,7 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1838
2004
  </div>
1839
2005
  </div>
1840
2006
 
2007
+
1841
2008
  </div>
1842
2009
  </article>
1843
2010
  <article
@@ -1856,12 +2023,26 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1856
2023
 
1857
2024
  <label for="c-4-components-button-stories" class="badge ok as-toggle">11 stories</label>
1858
2025
 
2026
+
1859
2027
  </div>
1860
2028
  </div>
1861
2029
  <div class="meta" title="./src/button/button.stories.tsx">components-button · ./src/button/button.stories.tsx</div>
1862
-
1863
- <div class="hint">Button is the design system&#39;s primary actionable control. Pick `variant` to express hierarchy, `size` for prominence, and `status=&quot;danger&quot;` for destructive actions. Pass `asChild` to render Button&#39;s styles on any nested element — a plain `&lt;a&gt;`, a framework `&lt;Link&gt;`, or a custom component — without Button binding to any particular framework.</div>
1864
-
2030
+ <div>Primary actionable control; renders a `&lt;button&gt;` or, with `asChild`, any nested element</div>
2031
+ <div class="hint">Button is the design system&#39;s primary actionable control. Pick `variant` to
2032
+ express hierarchy, `size` for prominence, and `status=&quot;danger&quot;` for
2033
+ destructive actions. Pass `asChild` to render Button&#39;s styles on any nested
2034
+ element — a plain `&lt;a&gt;`, a framework `&lt;Link&gt;`, or a custom component —
2035
+ without Button binding to any particular framework.</div>
2036
+ <div class="kv"><span class="chip">summary: Primary actionable control; renders a `&lt;button&gt;` or, with `asChild`, any nested element</span><span class="chip">example: &lt;Button variant=&quot;primary&quot; size=&quot;sm&quot; onClick={handleSave}&gt;
2037
+ Save changes
2038
+ &lt;/Button&gt;</span><span class="chip">example: &lt;Button asChild variant=&quot;secondary&quot;&gt;
2039
+ &lt;a href=&quot;https://agentero.com&quot; target=&quot;_blank&quot; rel=&quot;noreferrer&quot;&gt;Visit Agentero&lt;/a&gt;
2040
+ &lt;/Button&gt;</span><span class="chip">example: // Framework-agnostic: wrap any Link implementation
2041
+ &lt;Button asChild variant=&quot;primary&quot;&gt;
2042
+ &lt;Link href=&quot;/dashboard&quot;&gt;Go to dashboard&lt;/Link&gt;
2043
+ &lt;/Button&gt;</span><span class="chip">example: &lt;Button variant=&quot;primary&quot; status=&quot;danger&quot; loading={isDeleting} onClick={handleDelete}&gt;
2044
+ Delete account
2045
+ &lt;/Button&gt;</span></div>
1865
2046
  </div>
1866
2047
 
1867
2048
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -1869,6 +2050,7 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1869
2050
 
1870
2051
  <input id="c-4-components-button-stories" class="tg tg-stories" type="checkbox" hidden />
1871
2052
 
2053
+
1872
2054
  <input id="c-4-components-button-props" class="tg tg-props" type="checkbox" hidden />
1873
2055
 
1874
2056
  <div class="panels">
@@ -1878,7 +2060,7 @@ variant?: &quot;circle&quot; | &quot;square&quot; | &quot;pillow&quot; | &quot;p
1878
2060
  <div class="panel panel-props">
1879
2061
  <div class="note ok">
1880
2062
  <div class="row">
1881
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
2063
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
1882
2064
  <span class="badge ok">12 prop types</span>
1883
2065
  </div>
1884
2066
  <pre><code>Component: src/button/button.tsx::Button</code></pre>
@@ -1949,7 +2131,7 @@ loading?: boolean
1949
2131
  * `&lt;button&gt;` and `&lt;a&gt;` because `asChild` lets consumers render either tag
1950
2132
  * (or any forwardRef component) through Radix&#39;s `Slot`.
1951
2133
  */
1952
- ref?: Ref&lt;HTMLButtonElement | HTMLAnchorElement&gt;
2134
+ ref?: Ref&lt;HTMLButtonElement | HTMLAnchorElement&gt; | undefined
1953
2135
 
1954
2136
  /**
1955
2137
  * When `true`, renders a fully pill-shaped button (rounded-full). Otherwise
@@ -1964,7 +2146,7 @@ rounded?: boolean
1964
2146
  * - `md` (40px) — prominent actions in modals or feature rows.
1965
2147
  * - `lg` (48px) — hero CTAs and full-width mobile actions.
1966
2148
  */
1967
- size?: ButtonSizeType
2149
+ size?: &quot;sm&quot; | &quot;md&quot; | &quot;xs&quot; | &quot;lg&quot;
1968
2150
 
1969
2151
  /**
1970
2152
  * Semantic status override. Set to `&#39;danger&#39;` for destructive actions
@@ -1981,7 +2163,7 @@ status?: &quot;danger&quot;
1981
2163
  * - `ghost` — minimal background; low-emphasis action in dense layouts.
1982
2164
  * - `link` — inline text-style action; no padding or background.
1983
2165
  */
1984
- variant?: ButtonVariantType</code></pre>
2166
+ variant?: &quot;link&quot; | &quot;ghost&quot; | &quot;primary&quot; | &quot;secondary&quot; | &quot;tertiary&quot;</code></pre>
1985
2167
  </div>
1986
2168
  </div>
1987
2169
 
@@ -2003,7 +2185,9 @@ variant?: ButtonVariantType</code></pre>
2003
2185
  <span class="badge ok">story ok</span>
2004
2186
  </div>
2005
2187
  <div>Default args playground for Button</div>
2006
- <div class="hint">Args-controlled playground. Toggle `variant`, `size`, `status`, `loading`, `disabled`, and `rounded` from the Controls panel to explore every visual combination of the Button.</div>
2188
+ <div class="hint">Args-controlled playground. Toggle `variant`, `size`, `status`, `loading`,
2189
+ `disabled`, and `rounded` from the Controls panel to explore every visual
2190
+ combination of the Button.</div>
2007
2191
  <pre><code>const Default = () =&gt; &lt;Button variant=&quot;primary&quot; size=&quot;sm&quot;&gt;{TEXT}&lt;/Button&gt;;</code></pre>
2008
2192
  </div>
2009
2193
  <div class="note ok">
@@ -2012,7 +2196,10 @@ variant?: ButtonVariantType</code></pre>
2012
2196
  <span class="badge ok">story ok</span>
2013
2197
  </div>
2014
2198
  <div>All Button variants at default size</div>
2015
- <div class="hint">All five variants at the default `sm` size. Variants express visual hierarchy: `primary` for the main CTA, `secondary` / `tertiary` for supporting actions, `ghost` for low-emphasis inline actions, and `link` for text-only actions.</div>
2199
+ <div class="hint">All five variants at the default `sm` size. Variants express visual
2200
+ hierarchy: `primary` for the main CTA, `secondary` / `tertiary` for
2201
+ supporting actions, `ghost` for low-emphasis inline actions, and `link`
2202
+ for text-only actions.</div>
2016
2203
  <pre><code>const Variants = () =&gt; (
2017
2204
  &lt;Row&gt;
2018
2205
  {VARIANTS.map(variant =&gt; (
@@ -2029,7 +2216,8 @@ variant?: ButtonVariantType</code></pre>
2029
2216
  <span class="badge ok">story ok</span>
2030
2217
  </div>
2031
2218
  <div>All Button sizes at default variant</div>
2032
- <div class="hint">All four sizes at the default `primary` variant. Sizes scale from `xs` (24px) for dense toolbars up to `lg` (48px) for hero CTAs.</div>
2219
+ <div class="hint">All four sizes at the default `primary` variant. Sizes scale from `xs`
2220
+ (24px) for dense toolbars up to `lg` (48px) for hero CTAs.</div>
2033
2221
  <pre><code>const Sizes = () =&gt; (
2034
2222
  &lt;Row&gt;
2035
2223
  {SIZES.map(size =&gt; (
@@ -2046,7 +2234,10 @@ variant?: ButtonVariantType</code></pre>
2046
2234
  <span class="badge ok">story ok</span>
2047
2235
  </div>
2048
2236
  <div>Disabled treatment for every variant</div>
2049
- <div class="hint">Disabled state across all variants. Rendered via `asChild` with `&lt;a&gt;` children to show the disabled treatment applied via className — native anchors ignore the `disabled` attribute, so Button emits `aria-disabled` and `data-disabled` on the child instead.</div>
2237
+ <div class="hint">Disabled state across all variants. Rendered via `asChild` with `&lt;a&gt;`
2238
+ children to show the disabled treatment applied via className — native
2239
+ anchors ignore the `disabled` attribute, so Button emits `aria-disabled`
2240
+ and `data-disabled` on the child instead.</div>
2050
2241
  <pre><code>const Disabled = () =&gt; (
2051
2242
  &lt;Row&gt;
2052
2243
  {VARIANTS.map(variant =&gt; (
@@ -2086,7 +2277,9 @@ variant?: ButtonVariantType</code></pre>
2086
2277
  <span class="badge ok">story ok</span>
2087
2278
  </div>
2088
2279
  <div>Icon-only Button across variant × size (excluding `link`)</div>
2089
- <div class="hint">Icon-only buttons across the variant × size grid. Excludes `variant=&quot;link&quot;` — combining `link` with icon-only children logs a dev-only warning because the link treatment has no padding to accommodate an icon alone.</div>
2280
+ <div class="hint">Icon-only buttons across the variant × size grid. Excludes `variant=&quot;link&quot;`
2281
+ — combining `link` with icon-only children logs a dev-only warning because
2282
+ the link treatment has no padding to accommodate an icon alone.</div>
2090
2283
  <pre><code>const OnlyIcon = () =&gt; (
2091
2284
  &lt;Stack&gt;
2092
2285
  {NON_LINK_VARIANTS.map(variant =&gt; (
@@ -2107,7 +2300,10 @@ variant?: ButtonVariantType</code></pre>
2107
2300
  <span class="badge ok">story ok</span>
2108
2301
  </div>
2109
2302
  <div>Loading state across variant × size (excluding `link`)</div>
2110
- <div class="hint">Loading state across the variant × size grid. Each row shows two buttons per size: one icon-only, one with text. Loading forces `disabled` and overlays a spinner that inherits the variant&#39;s text color. Excludes `variant=&quot;link&quot;` — combining `link` with `loading` logs a dev-only warning.</div>
2303
+ <div class="hint">Loading state across the variant × size grid. Each row shows two buttons
2304
+ per size: one icon-only, one with text. Loading forces `disabled` and
2305
+ overlays a spinner that inherits the variant&#39;s text color. Excludes
2306
+ `variant=&quot;link&quot;` — combining `link` with `loading` logs a dev-only warning.</div>
2111
2307
  <pre><code>const Loading = () =&gt; (
2112
2308
  &lt;Stack&gt;
2113
2309
  {NON_LINK_VARIANTS.map(variant =&gt; (
@@ -2133,7 +2329,10 @@ variant?: ButtonVariantType</code></pre>
2133
2329
  <span class="badge ok">story ok</span>
2134
2330
  </div>
2135
2331
  <div>`status=&quot;danger&quot;` across every variant, enabled + disabled</div>
2136
- <div class="hint">Destructive treatment via `status=&quot;danger&quot;`. The top row shows every variant enabled; the bottom row shows every variant disabled. Use `status=&quot;danger&quot;` for delete, remove, or disconnect actions regardless of variant.</div>
2332
+ <div class="hint">Destructive treatment via `status=&quot;danger&quot;`. The top row shows every
2333
+ variant enabled; the bottom row shows every variant disabled. Use
2334
+ `status=&quot;danger&quot;` for delete, remove, or disconnect actions regardless of
2335
+ variant.</div>
2137
2336
  <pre><code>const Status = () =&gt; (
2138
2337
  &lt;Stack&gt;
2139
2338
  &lt;Row&gt;
@@ -2165,7 +2364,8 @@ variant?: ButtonVariantType</code></pre>
2165
2364
  <span class="badge ok">story ok</span>
2166
2365
  </div>
2167
2366
  <div>`rounded` pill shape across variant × size (excluding `link`)</div>
2168
- <div class="hint">Fully pill-shaped buttons across the variant × size grid. Excludes `variant=&quot;link&quot;` since the link treatment has no background to round.</div>
2367
+ <div class="hint">Fully pill-shaped buttons across the variant × size grid. Excludes
2368
+ `variant=&quot;link&quot;` since the link treatment has no background to round.</div>
2169
2369
  <pre><code>const Rounded = () =&gt; (
2170
2370
  &lt;Stack&gt;
2171
2371
  {NON_LINK_VARIANTS.map(variant =&gt; (
@@ -2188,7 +2388,12 @@ variant?: ButtonVariantType</code></pre>
2188
2388
  <span class="badge ok">story ok</span>
2189
2389
  </div>
2190
2390
  <div>`asChild` composes Button&#39;s styles onto any element</div>
2191
- <div class="hint">`asChild` renders Button&#39;s styles on the nested child element rather than on a `&lt;button&gt;` — the child receives Button&#39;s `className`, `ref`, and merged props via Radix&#39;s `Slot` primitive. Use it to turn any anchor or framework `Link` into a Button without coupling the design system to a router. In app code, swap the plain `&lt;a&gt;` below for your framework&#39;s Link (`next/link`, `react-router`, `@tanstack/react-router`, etc.).</div>
2391
+ <div class="hint">`asChild` renders Button&#39;s styles on the nested child element rather than
2392
+ on a `&lt;button&gt;` — the child receives Button&#39;s `className`, `ref`, and
2393
+ merged props via Radix&#39;s `Slot` primitive. Use it to turn any anchor or
2394
+ framework `Link` into a Button without coupling the design system to a
2395
+ router. In app code, swap the plain `&lt;a&gt;` below for your framework&#39;s Link
2396
+ (`next/link`, `react-router`, `@tanstack/react-router`, etc.).</div>
2192
2397
  <pre><code>const AsChild = () =&gt; (
2193
2398
  &lt;Row&gt;
2194
2399
  &lt;Button asChild variant=&quot;primary&quot;&gt;
@@ -2208,7 +2413,15 @@ variant?: ButtonVariantType</code></pre>
2208
2413
  <span class="badge ok">story ok</span>
2209
2414
  </div>
2210
2415
  <div>Press feedback dips the button, excluding `link` and disabled</div>
2211
- <div class="hint">Buttons dip to 97% while held so the control answers the pointer rather than only changing color. Press and hold one below to feel it — the effect is deliberately small, and if a quick click draws the eye it is too strong. `variant=&quot;link&quot;` is excluded: it has no padding or background, so scaling bare text reads as a wobble rather than a button being pushed. Disabled buttons are excluded too, including the `asChild` anchor form, which stays keyboard-focusable and would otherwise dip on Enter. The whole effect is gated behind `motion-safe`, so it disappears under `prefers-reduced-motion`.</div>
2416
+ <div class="hint">Buttons dip to 97% while held so the control answers the pointer rather than
2417
+ only changing color. Press and hold one below to feel it — the effect is
2418
+ deliberately small, and if a quick click draws the eye it is too strong.
2419
+
2420
+ `variant=&quot;link&quot;` is excluded: it has no padding or background, so scaling
2421
+ bare text reads as a wobble rather than a button being pushed. Disabled
2422
+ buttons are excluded too, including the `asChild` anchor form, which stays
2423
+ keyboard-focusable and would otherwise dip on Enter. The whole effect is
2424
+ gated behind `motion-safe`, so it disappears under `prefers-reduced-motion`.</div>
2212
2425
  <pre><code>const Pressed = () =&gt; (
2213
2426
  &lt;Stack&gt;
2214
2427
  &lt;Row&gt;
@@ -2232,6 +2445,7 @@ variant?: ButtonVariantType</code></pre>
2232
2445
  </div>
2233
2446
  </div>
2234
2447
 
2448
+
2235
2449
  </div>
2236
2450
  </article>
2237
2451
  <article
@@ -2250,12 +2464,20 @@ variant?: ButtonVariantType</code></pre>
2250
2464
 
2251
2465
  <label for="c-5-components-checklist-stories" class="badge ok as-toggle">2 stories</label>
2252
2466
 
2467
+
2253
2468
  </div>
2254
2469
  </div>
2255
2470
  <div class="meta" title="./src/check-list/check-list.stories.tsx">components-checklist · ./src/check-list/check-list.stories.tsx</div>
2256
-
2257
- <div class="hint">CheckList renders a vertical list where every row is marked with a check icon. Purely presentational — for interactive selection use a checkbox group.</div>
2258
-
2471
+ <div>List container for check-marked items</div>
2472
+ <div class="hint">CheckList renders a vertical list where every row is marked with a check
2473
+ icon. Purely presentational — for interactive selection use a checkbox group.</div>
2474
+ <div class="kv"><span class="chip">summary: List container for check-marked items</span><span class="chip">example: ```tsx
2475
+ import { CheckList } from &#39;@agentero/design-system/check-list&#39;;
2476
+
2477
+ &lt;CheckList.Root&gt;
2478
+ &lt;CheckList.Item&gt;Instant appointment&lt;/CheckList.Item&gt;
2479
+ &lt;/CheckList.Root&gt;
2480
+ ```</span></div>
2259
2481
  </div>
2260
2482
 
2261
2483
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -2264,6 +2486,7 @@ variant?: ButtonVariantType</code></pre>
2264
2486
  <input id="c-5-components-checklist-stories" class="tg tg-stories" type="checkbox" hidden />
2265
2487
 
2266
2488
 
2489
+
2267
2490
 
2268
2491
  <div class="panels">
2269
2492
 
@@ -2322,6 +2545,7 @@ variant?: ButtonVariantType</code></pre>
2322
2545
  </div>
2323
2546
  </div>
2324
2547
 
2548
+
2325
2549
  </div>
2326
2550
  </article>
2327
2551
  <article
@@ -2336,16 +2560,36 @@ variant?: ButtonVariantType</code></pre>
2336
2560
  <div class="title">
2337
2561
  <h2><span class="status-dot dot-ok"></span> Command.Root</h2>
2338
2562
  <div class="badges">
2339
-
2563
+ <label for="c-6-components-command-props" class="badge ok as-toggle">10 prop types</label>
2340
2564
 
2341
2565
  <label for="c-6-components-command-stories" class="badge ok as-toggle">5 stories</label>
2342
2566
 
2567
+
2343
2568
  </div>
2344
2569
  </div>
2345
2570
  <div class="meta" title="./src/command/command.stories.tsx">components-command · ./src/command/command.stories.tsx</div>
2346
-
2347
- <div class="hint">Command is a filterable list built on `cmdk`. Type to narrow the options, navigate with the arrow keys, select with Enter. It carries its own panel chrome, so dropping it inside a `Popover.Content` yields a combobox.</div>
2348
-
2571
+ <div>Filterable command palette container</div>
2572
+ <div class="hint">Command is a filterable list built on `cmdk`. Type to narrow the options,
2573
+ navigate with the arrow keys, select with Enter. It carries its own panel
2574
+ chrome, so dropping it inside a `Popover.Content` yields a combobox.</div>
2575
+ <div class="kv"><span class="chip">summary: Filterable command palette container</span><span class="chip">see: {@link https://github.com/pacocoursey/cmdk cmdk}</span><span class="chip">example: ```tsx
2576
+ import { Command } from &#39;@agentero/design-system/command&#39;;
2577
+
2578
+ &lt;Command.Root label=&quot;Search lines of business&quot;&gt;
2579
+ &lt;Command.Input placeholder=&quot;Search lines of business...&quot; /&gt;
2580
+ &lt;Command.List&gt;
2581
+ &lt;Command.Item onSelect={() =&gt; select(&#39;home&#39;)}&gt;Homeowners&lt;/Command.Item&gt;
2582
+ &lt;Command.Item onSelect={() =&gt; select(&#39;auto&#39;)}&gt;Auto&lt;/Command.Item&gt;
2583
+ &lt;/Command.List&gt;
2584
+ &lt;Command.Empty&gt;No options found&lt;/Command.Empty&gt;
2585
+ &lt;/Command.Root&gt;
2586
+ ```</span><span class="chip">example: ```tsx
2587
+ // Filtering handled upstream (async search): let every item through.
2588
+ &lt;Command.Root label=&quot;Search options&quot; shouldFilter={false}&gt;
2589
+ &lt;Command.Input placeholder=&quot;Search...&quot; /&gt;
2590
+ &lt;Command.List&gt;...&lt;/Command.List&gt;
2591
+ &lt;/Command.Root&gt;
2592
+ ```</span></div>
2349
2593
  </div>
2350
2594
 
2351
2595
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -2354,11 +2598,68 @@ variant?: ButtonVariantType</code></pre>
2354
2598
  <input id="c-6-components-command-stories" class="tg tg-stories" type="checkbox" hidden />
2355
2599
 
2356
2600
 
2601
+ <input id="c-6-components-command-props" class="tg tg-props" type="checkbox" hidden />
2357
2602
 
2358
2603
  <div class="panels">
2359
2604
 
2360
2605
 
2361
2606
 
2607
+ <div class="panel panel-props">
2608
+ <div class="note ok">
2609
+ <div class="row">
2610
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
2611
+ <span class="badge ok">10 prop types</span>
2612
+ </div>
2613
+ <pre><code>Component: src/command/index.ts::Command</code></pre>
2614
+ <pre><code>Props:</code></pre>
2615
+ <pre><code>asChild?: boolean
2616
+
2617
+ children?: ReactNode
2618
+
2619
+ /**
2620
+ * Optionally set to `true` to disable selection via pointer events.
2621
+ */
2622
+ disablePointerSelection?: boolean
2623
+
2624
+ /**
2625
+ * Custom filter function for whether each command menu item should matches the given search query.
2626
+ * It should return a number between 0 and 1, with 1 being the best match and 0 being hidden entirely.
2627
+ * By default, uses the `command-score` library.
2628
+ */
2629
+ filter?: CommandFilter
2630
+
2631
+ /**
2632
+ * Accessible label for this command menu. Not shown visibly.
2633
+ */
2634
+ label?: string
2635
+
2636
+ /**
2637
+ * Optionally set to `true` to turn on looping around when using the arrow keys.
2638
+ */
2639
+ loop?: boolean
2640
+
2641
+ /**
2642
+ * Event handler called when the selected item of the menu changes.
2643
+ */
2644
+ onValueChange?: (value: string) =&gt; void
2645
+
2646
+ /**
2647
+ * Optionally set to `false` to turn off the automatic filtering and sorting.
2648
+ * If `false`, you must conditionally render valid items based on the search query yourself.
2649
+ */
2650
+ shouldFilter?: boolean
2651
+
2652
+ /**
2653
+ * Optional controlled state of the selected command menu item.
2654
+ */
2655
+ value?: string
2656
+
2657
+ /**
2658
+ * Set to `false` to disable ctrl+n/j/p/k shortcuts. Defaults to `true`.
2659
+ */
2660
+ vimBindings?: boolean</code></pre>
2661
+ </div>
2662
+ </div>
2362
2663
 
2363
2664
  <div class="panel panel-stories">
2364
2665
 
@@ -2416,7 +2717,8 @@ variant?: ButtonVariantType</code></pre>
2416
2717
  <span class="badge ok">story ok</span>
2417
2718
  </div>
2418
2719
 
2419
- <div class="hint">`Group` sections related options. It ships unstyled, so the heading is styled per usage through the `[cmdk-group-heading]` hook.</div>
2720
+ <div class="hint">`Group` sections related options. It ships unstyled, so the heading is styled
2721
+ per usage through the `[cmdk-group-heading]` hook.</div>
2420
2722
  <pre><code>const Grouped = () =&gt; (
2421
2723
  &lt;Command.Root label=&quot;Search commands&quot;&gt;
2422
2724
  &lt;Command.Input placeholder=&quot;Search...&quot; /&gt;
@@ -2440,7 +2742,9 @@ variant?: ButtonVariantType</code></pre>
2440
2742
  <span class="badge ok">story ok</span>
2441
2743
  </div>
2442
2744
 
2443
- <div class="hint">With more rows than the list cap fits, the list scrolls — by wheel, or by keyboard: cmdk scrolls the active row into view as the arrow keys move it, and `scroll-py-2` keeps that row off the container edges.</div>
2745
+ <div class="hint">With more rows than the list cap fits, the list scrolls — by wheel, or by
2746
+ keyboard: cmdk scrolls the active row into view as the arrow keys move it,
2747
+ and `scroll-py-2` keeps that row off the container edges.</div>
2444
2748
  <pre><code>const ScrollingList = () =&gt; (
2445
2749
  &lt;Command.Root label=&quot;Search states&quot;&gt;
2446
2750
  &lt;Command.Input placeholder=&quot;Search states...&quot; /&gt;
@@ -2473,6 +2777,7 @@ variant?: ButtonVariantType</code></pre>
2473
2777
  </div>
2474
2778
  </div>
2475
2779
 
2780
+
2476
2781
  </div>
2477
2782
  </article>
2478
2783
  <article
@@ -2487,16 +2792,46 @@ variant?: ButtonVariantType</code></pre>
2487
2792
  <div class="title">
2488
2793
  <h2><span class="status-dot dot-ok"></span> DataTable.Root</h2>
2489
2794
  <div class="badges">
2490
-
2795
+ <label for="c-7-components-datatable-props" class="badge ok as-toggle">88 prop types</label>
2491
2796
 
2492
2797
  <label for="c-7-components-datatable-stories" class="badge ok as-toggle">4 stories</label>
2493
2798
 
2799
+
2494
2800
  </div>
2495
2801
  </div>
2496
2802
  <div class="meta" title="./src/data-table/data-table.stories.tsx">components-datatable · ./src/data-table/data-table.stories.tsx</div>
2497
-
2498
- <div class="hint">DataTable is the data-driven table compound built on TanStack Table. This story shows a representative leads table: an `Applicant` column with a name + address, contact info, insurance type with an icon, a sortable `Created` column, a status badge, and hover-revealed row actions (open + a kebab menu). The toolbar (search + filters) and the footer pagination are **separate components** composed inside `ToolBar` / `Footer`.</div>
2499
-
2803
+ <div>DataTable root that builds the table instance and shares context</div>
2804
+ <div class="hint">DataTable is the data-driven table compound built on TanStack Table. This
2805
+ story shows a representative leads table: an `Applicant` column with a name +
2806
+ address, contact info, insurance type with an icon, a sortable `Created`
2807
+ column, a status badge, and hover-revealed row actions (open + a kebab menu).
2808
+ The toolbar (search + filters) and the footer pagination are **separate
2809
+ components** composed inside `ToolBar` / `Footer`.</div>
2810
+ <div class="kv"><span class="chip">summary: DataTable root that builds the table instance and shares context</span><span class="chip">see: {@link https://tanstack.com/table/latest TanStack Table}</span><span class="chip">example: ```tsx
2811
+ import { DataTable } from &#39;@agentero/design-system/data-table&#39;;
2812
+ import { createColumnHelper } from &#39;@tanstack/react-table&#39;;
2813
+
2814
+ const columnHelper = createColumnHelper&lt;User&gt;();
2815
+ const columns = [
2816
+ columnHelper.accessor(&#39;name&#39;, { header: &#39;Name&#39;, enableSorting: true }),
2817
+ columnHelper.accessor(&#39;email&#39;, { header: &#39;Email&#39; })
2818
+ ];
2819
+
2820
+ &lt;DataTable.Root data={users} columns={columns}&gt;
2821
+ &lt;DataTable.ToolBar&gt;
2822
+ &lt;SearchInput /&gt;
2823
+ &lt;/DataTable.ToolBar&gt;
2824
+ &lt;DataTable.Table /&gt;
2825
+ &lt;DataTable.Footer&gt;
2826
+ &lt;DataTable.Pagination
2827
+ currentPage={page}
2828
+ pageSize={10}
2829
+ totalCount={total}
2830
+ onPageChange={setPage}
2831
+ /&gt;
2832
+ &lt;/DataTable.Footer&gt;
2833
+ &lt;/DataTable.Root&gt;
2834
+ ```</span></div>
2500
2835
  </div>
2501
2836
 
2502
2837
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -2505,172 +2840,645 @@ variant?: ButtonVariantType</code></pre>
2505
2840
  <input id="c-7-components-datatable-stories" class="tg tg-stories" type="checkbox" hidden />
2506
2841
 
2507
2842
 
2843
+ <input id="c-7-components-datatable-props" class="tg tg-props" type="checkbox" hidden />
2508
2844
 
2509
2845
  <div class="panels">
2510
2846
 
2511
2847
 
2512
2848
 
2513
-
2514
- <div class="panel panel-stories">
2515
-
2516
-
2517
-
2849
+ <div class="panel panel-props">
2518
2850
  <div class="note ok">
2519
- <div class="row">
2520
- <span class="ex-name">Imports</span>
2521
- </div>
2522
- <pre><code>import { Button, DataTable, DropdownMenu, Pagination, Table } from "@agentero/design-system";</code></pre>
2523
- </div>
2524
-
2525
-
2526
- <div class="note ok">
2527
- <div class="row">
2528
- <span class="ex-name">Playground</span>
2529
- <span class="badge ok">story ok</span>
2530
- </div>
2531
- <div>Display props playground (size / embed / enclosed / sticky)</div>
2532
- <div class="hint">Playground for `DataTable.Table` display props — toggle `size`, `embed`, `enclosed`, and `sticky` from the controls panel.</div>
2533
- <pre><code>const Playground = () =&gt; &lt;div
2534
- className={args.enclosed ? &#39;flex min-h-0 flex-1 flex-col p-4&#39; : &#39;contents&#39;}&gt;
2535
- &lt;DataTable.Root data={LEADS} columns={columns}&gt;
2536
- &lt;DataTable.Table size=&quot;md&quot; embed enclosed={false} sticky=&quot;header&quot; /&gt;
2537
- &lt;/DataTable.Root&gt;
2538
- &lt;/div&gt;;</code></pre>
2851
+ <div class="row">
2852
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
2853
+ <span class="badge ok">88 prop types</span>
2539
2854
  </div>
2540
- <div class="note ok">
2541
- <div class="row">
2542
- <span class="ex-name">Leads</span>
2543
- <span class="badge ok">story ok</span>
2544
- </div>
2545
- <div>Representative leads table composition</div>
2546
- <div class="hint">A leads-table composition: sortable `Created` column, a status badge, row navigation via `rowHref`, hover-revealed actions, a search input + filters in the toolbar, and pagination in the footer.</div>
2547
- <pre><code>const Leads = () =&gt; {
2548
- const [sorting, setSorting] = useState&lt;SortingState&gt;([]);
2549
- const [page, setPage] = useState(1);
2550
- const [search, setSearch] = useState(&#39;&#39;);
2855
+ <pre><code>Component: src/data-table/index.ts::DataTable</code></pre>
2856
+ <pre><code>Props:</code></pre>
2857
+ <pre><code>/**
2858
+ * An array of extra features that you can add to the table instance.
2859
+ */
2860
+ _features?: TableFeature&lt;any&gt;[]
2551
2861
 
2552
- const data = useMemo(
2553
- () =&gt; LEADS.filter(l =&gt; l.contact.toLowerCase().includes(search.toLowerCase())),
2554
- [search]
2555
- );
2862
+ aggregationFns?: Record&lt;string, AggregationFn&lt;any&gt;&gt;
2556
2863
 
2557
- return (
2558
- &lt;DataTable.Root
2559
- data={data}
2560
- columns={columns}
2561
- state={{ sorting }}
2562
- onSortingChange={setSorting}
2563
- getSortedRowModel={getSortedRowModel()}
2564
- enableSortingRemoval={false}
2565
- rowHref={lead =&gt; `/leads/${lead.leadId}`}&gt;
2566
- &lt;DataTable.ToolBar&gt;
2567
- &lt;input
2568
- value={search}
2569
- onChange={e =&gt; setSearch(e.target.value)}
2570
- placeholder=&quot;Search...&quot;
2571
- aria-label=&quot;Search leads&quot;
2572
- className=&quot;h-8 w-60 rounded-md border border-border-default-base-primary px-3 text-sm outline-none&quot;
2573
- /&gt;
2574
- &lt;Button variant=&quot;secondary&quot; size=&quot;sm&quot;&gt;
2575
- Filters
2576
- &lt;/Button&gt;
2577
- &lt;/DataTable.ToolBar&gt;
2864
+ /**
2865
+ * Set this option to override any of the `autoReset...` feature options.
2866
+ */
2867
+ autoResetAll?: boolean
2578
2868
 
2579
- &lt;DataTable.Table /&gt;
2869
+ /**
2870
+ * Enable this setting to automatically reset the expanded state of the table when expanding state changes.
2871
+ */
2872
+ autoResetExpanded?: boolean
2580
2873
 
2581
- &lt;DataTable.Footer&gt;
2582
- &lt;Pagination
2583
- totalCount={LEADS.length}
2584
- currentPage={page}
2585
- pageSize={10}
2586
- onPageChange={setPage}
2587
- /&gt;
2588
- &lt;/DataTable.Footer&gt;
2589
- &lt;/DataTable.Root&gt;
2590
- );
2591
- };</code></pre>
2592
- </div>
2593
- <div class="note ok">
2594
- <div class="row">
2595
- <span class="ex-name">Empty</span>
2596
- <span class="badge ok">story ok</span>
2597
- </div>
2598
- <div>Empty state when there are no rows</div>
2599
- <div class="hint">No rows: the table renders its default empty state instead of body rows.</div>
2600
- <pre><code>const Empty = () =&gt; (
2601
- &lt;DataTable.Root data={[] as Lead[]} columns={columns}&gt;
2602
- &lt;DataTable.Table /&gt;
2603
- &lt;/DataTable.Root&gt;
2604
- );</code></pre>
2605
- </div>
2606
- <div class="note ok">
2607
- <div class="row">
2608
- <span class="ex-name">Loading</span>
2609
- <span class="badge ok">story ok</span>
2610
- </div>
2611
- <div>Loading state dims the table and hides the empty state</div>
2612
- <div class="hint">Loading: the body is dimmed and the empty state is suppressed while data is in flight.</div>
2613
- <pre><code>const Loading = () =&gt; (
2614
- &lt;DataTable.Root data={[] as Lead[]} columns={columns} isLoading&gt;
2615
- &lt;DataTable.Table /&gt;
2616
- &lt;/DataTable.Root&gt;
2617
- );</code></pre>
2618
- </div>
2619
- </div>
2620
-
2621
- </div>
2622
- </article>
2623
- <article
2624
- class="card
2625
- no-error
2626
- no-info
2627
- no-story-error
2628
- no-doc-error"
2629
- role="listitem"
2630
- aria-label="Divider">
2631
- <div class="head">
2632
- <div class="title">
2633
- <h2><span class="status-dot dot-ok"></span> Divider</h2>
2634
- <div class="badges">
2635
- <label for="c-8-components-divider-props" class="badge ok as-toggle">2 prop types</label>
2636
-
2637
- <label for="c-8-components-divider-stories" class="badge ok as-toggle">10 stories</label>
2638
-
2639
- </div>
2640
- </div>
2641
- <div class="meta" title="./src/divider/divider.stories.tsx">components-divider · ./src/divider/divider.stories.tsx</div>
2642
-
2643
- <div class="hint">Divider separates content visually along either a horizontal or vertical axis. Use between page or card sections, between inline items in a toolbar or list, or — with the `label` prop — to render an &quot;or&quot;-style break between options. Set `decorative={false}` when the separator carries semantic meaning so it&#39;s announced to assistive technologies.</div>
2644
-
2645
- </div>
2874
+ /**
2875
+ * If set to `true`, pagination will be reset to the first page when page-altering state changes eg. `data` is updated, filters change, grouping changes, etc.
2876
+ */
2877
+ autoResetPageIndex?: boolean
2646
2878
 
2647
- <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
2648
-
2649
-
2650
- <input id="c-8-components-divider-stories" class="tg tg-stories" type="checkbox" hidden />
2651
-
2652
- <input id="c-8-components-divider-props" class="tg tg-props" type="checkbox" hidden />
2879
+ children?: ReactNode
2653
2880
 
2654
- <div class="panels">
2881
+ /**
2882
+ * Enables or disables right-to-left support for resizing the column. defaults to &#39;ltr&#39;.
2883
+ */
2884
+ columnResizeDirection?: &quot;ltr&quot; | &quot;rtl&quot;
2885
+
2886
+ /**
2887
+ * Determines when the columnSizing state is updated. `onChange` updates the state when the user is dragging the resize handle. `onEnd` updates the state when the user releases the resize handle.
2888
+ */
2889
+ columnResizeMode?: &quot;onChange&quot; | &quot;onEnd&quot;
2890
+
2891
+ /**
2892
+ * The array of column defs to use for the table.
2893
+ */
2894
+ columns: ColumnDef&lt;Lead, any&gt;[]
2895
+
2896
+ /**
2897
+ * The data for the table to display. This array should match the type you provided to `table.setRowType&lt;...&gt;`. Columns can access this data via string/index or a functional accessor. When the `data` option changes reference, the table will reprocess the data.
2898
+ */
2899
+ data: Lead[]
2900
+
2901
+ /**
2902
+ * Set this option to `true` to output all debugging information to the console.
2903
+ */
2904
+ debugAll?: boolean
2905
+
2906
+ /**
2907
+ * Set this option to `true` to output cell debugging information to the console.
2908
+ */
2909
+ debugCells?: boolean
2910
+
2911
+ /**
2912
+ * Set this option to `true` to output column debugging information to the console.
2913
+ */
2914
+ debugColumns?: boolean
2915
+
2916
+ /**
2917
+ * Set this option to `true` to output header debugging information to the console.
2918
+ */
2919
+ debugHeaders?: boolean
2920
+
2921
+ /**
2922
+ * Set this option to `true` to output row debugging information to the console.
2923
+ */
2924
+ debugRows?: boolean
2925
+
2926
+ /**
2927
+ * Set this option to `true` to output table debugging information to the console.
2928
+ */
2929
+ debugTable?: boolean
2930
+
2931
+ /**
2932
+ * Default column options to use for all column defs supplied to the table.
2933
+ */
2934
+ defaultColumn?: Partial&lt;ColumnDef&lt;Lead, unknown&gt;&gt; | undefined
2935
+
2936
+ /**
2937
+ * Enables/disables **column** filtering for all columns.
2938
+ */
2939
+ enableColumnFilters?: boolean
2940
+
2941
+ /**
2942
+ * Enables/disables column pinning for the table. Defaults to `true`.
2943
+ */
2944
+ enableColumnPinning?: boolean
2945
+
2946
+ /**
2947
+ * Enables or disables column resizing for the column.
2948
+ */
2949
+ enableColumnResizing?: boolean
2950
+
2951
+ /**
2952
+ * Enable/disable expanding for all rows.
2953
+ */
2954
+ enableExpanding?: boolean
2955
+
2956
+ /**
2957
+ * Enables/disables all filtering for the table.
2958
+ */
2959
+ enableFilters?: boolean
2960
+
2961
+ /**
2962
+ * Enables/disables **global** filtering for all columns.
2963
+ */
2964
+ enableGlobalFilter?: boolean
2965
+
2966
+ /**
2967
+ * Enables/disables grouping for the table.
2968
+ */
2969
+ enableGrouping?: boolean
2970
+
2971
+ /**
2972
+ * Whether to enable column hiding. Defaults to `true`.
2973
+ */
2974
+ enableHiding?: boolean
2975
+
2976
+ /**
2977
+ * Enables/disables the ability to remove multi-sorts
2978
+ */
2979
+ enableMultiRemove?: boolean
2980
+
2981
+ /**
2982
+ * - Enables/disables multiple row selection for all rows in the table OR
2983
+ * - A function that given a row, returns whether to enable/disable multiple row selection for that row&#39;s children/grandchildren
2984
+ */
2985
+ enableMultiRowSelection?: boolean | ((row: Row&lt;Lead&gt;) =&gt; boolean) | undefined
2986
+
2987
+ /**
2988
+ * Enables/Disables multi-sorting for the table.
2989
+ */
2990
+ enableMultiSort?: boolean
2991
+
2992
+ enablePinning?: boolean
2993
+
2994
+ /**
2995
+ * Enables/disables row pinning for the table. Defaults to `true`.
2996
+ */
2997
+ enableRowPinning?: boolean | ((row: Row&lt;Lead&gt;) =&gt; boolean) | undefined
2998
+
2999
+ /**
3000
+ * - Enables/disables row selection for all rows in the table OR
3001
+ * - A function that given a row, returns whether to enable/disable row selection for that row
3002
+ */
3003
+ enableRowSelection?: boolean | ((row: Row&lt;Lead&gt;) =&gt; boolean) | undefined
3004
+
3005
+ /**
3006
+ * Enables/Disables sorting for the table.
3007
+ */
3008
+ enableSorting?: boolean
3009
+
3010
+ /**
3011
+ * Enables/Disables the ability to remove sorting for the table.
3012
+ * - If `true` then changing sort order will circle like: &#39;none&#39; -&gt; &#39;desc&#39; -&gt; &#39;asc&#39; -&gt; &#39;none&#39; -&gt; ...
3013
+ * - If `false` then changing sort order will circle like: &#39;none&#39; -&gt; &#39;desc&#39; -&gt; &#39;asc&#39; -&gt; &#39;desc&#39; -&gt; &#39;asc&#39; -&gt; ...
3014
+ */
3015
+ enableSortingRemoval?: boolean
3016
+
3017
+ /**
3018
+ * Enables/disables automatic sub-row selection when a parent row is selected, or a function that enables/disables automatic sub-row selection for each row.
3019
+ * (Use in combination with expanding or grouping features)
3020
+ */
3021
+ enableSubRowSelection?: boolean | ((row: Row&lt;Lead&gt;) =&gt; boolean) | undefined
3022
+
3023
+ filterFns?: Record&lt;string, FilterFn&lt;any&gt;&gt;
3024
+
3025
+ /**
3026
+ * By default, filtering is done from parent rows down (so if a parent row is filtered out, all of its children will be filtered out as well). Setting this option to `true` will cause filtering to be done from leaf rows up (which means parent rows will be included so long as one of their child or grand-child rows is also included).
3027
+ */
3028
+ filterFromLeafRows?: boolean
3029
+
3030
+ /**
3031
+ * If provided, this function will be called with the column and should return `true` or `false` to indicate whether this column should be used for global filtering.
3032
+ *
3033
+ * This is useful if the column can contain data that is not `string` or `number` (i.e. `undefined`).
3034
+ */
3035
+ getColumnCanGlobalFilter?: (column: Column&lt;Lead, unknown&gt;) =&gt; boolean
3036
+
3037
+ /**
3038
+ * This function is responsible for returning the expanded row model. If this function is not provided, the table will not expand rows. You can use the default exported `getExpandedRowModel` function to get the expanded row model or implement your own.
3039
+ */
3040
+ getExpandedRowModel?: (table: Table&lt;any&gt;) =&gt; () =&gt; RowModel&lt;any&gt;
3041
+
3042
+ getFacetedMinMaxValues?: (table: Table&lt;Lead&gt;, columnId: string) =&gt; () =&gt; [number, number] | undefined
3043
+
3044
+ getFacetedRowModel?: (table: Table&lt;Lead&gt;, columnId: string) =&gt; () =&gt; RowModel&lt;Lead&gt;
3045
+
3046
+ getFacetedUniqueValues?: (table: Table&lt;Lead&gt;, columnId: string) =&gt; () =&gt; Map&lt;any, number&gt;
3047
+
3048
+ /**
3049
+ * If provided, this function is called **once** per table and should return a **new function** which will calculate and return the row model for the table when it&#39;s filtered.
3050
+ * - For server-side filtering, this function is unnecessary and can be ignored since the server should already return the filtered row model.
3051
+ * - For client-side filtering, this function is required. A default implementation is provided via any table adapter&#39;s `{ getFilteredRowModel }` export.
3052
+ */
3053
+ getFilteredRowModel?: (table: Table&lt;any&gt;) =&gt; () =&gt; RowModel&lt;any&gt;
3054
+
3055
+ /**
3056
+ * Returns the row model after grouping has taken place, but no further.
3057
+ */
3058
+ getGroupedRowModel?: (table: Table&lt;any&gt;) =&gt; () =&gt; RowModel&lt;any&gt;
3059
+
3060
+ /**
3061
+ * If provided, allows you to override the default behavior of determining whether a row is currently expanded.
3062
+ */
3063
+ getIsRowExpanded?: (row: Row&lt;Lead&gt;) =&gt; boolean
3064
+
3065
+ /**
3066
+ * Returns the row model after pagination has taken place, but no further.
3067
+ *
3068
+ * Pagination columns are automatically reordered by default to the start of the columns list. If you would rather remove them or leave them as-is, set the appropriate mode here.
3069
+ */
3070
+ getPaginationRowModel?: (table: Table&lt;any&gt;) =&gt; () =&gt; RowModel&lt;any&gt;
3071
+
3072
+ /**
3073
+ * If provided, allows you to override the default behavior of determining whether a row can be expanded.
3074
+ */
3075
+ getRowCanExpand?: (row: Row&lt;Lead&gt;) =&gt; boolean
3076
+
3077
+ /**
3078
+ * This optional function is used to derive a unique ID for any given row. If not provided the rows index is used (nested rows join together with `.` using their grandparents&#39; index eg. `index.index.index`). If you need to identify individual rows that are originating from any server-side operations, it&#39;s suggested you use this function to return an ID that makes sense regardless of network IO/ambiguity eg. a userId, taskId, database ID field, etc.
3079
+ */
3080
+ getRowId?: (originalRow: Lead, index: number, parent?: Row&lt;Lead&gt; | undefined) =&gt; string
3081
+
3082
+ /**
3083
+ * This function is used to retrieve the sorted row model. If using server-side sorting, this function is not required. To use client-side sorting, pass the exported `getSortedRowModel()` from your adapter to your table or implement your own.
3084
+ */
3085
+ getSortedRowModel?: (table: Table&lt;any&gt;) =&gt; () =&gt; RowModel&lt;any&gt;
3086
+
3087
+ /**
3088
+ * This optional function is used to access the sub rows for any given row. If you are using nested rows, you will need to use this function to return the sub rows object (or undefined) from the row.
3089
+ */
3090
+ getSubRows?: (originalRow: Lead, index: number) =&gt; Lead[] | undefined
3091
+
3092
+ /**
3093
+ * The filter function to use for global filtering.
3094
+ * - A `string` referencing a built-in filter function
3095
+ * - A `string` that references a custom filter functions provided via the `tableOptions.filterFns` option
3096
+ * - A custom filter function
3097
+ */
3098
+ globalFilterFn?: FilterFnOption&lt;Lead&gt; | undefined
3099
+
3100
+ /**
3101
+ * Grouping columns are automatically reordered by default to the start of the columns list. If you would rather remove them or leave them as-is, set the appropriate mode here.
3102
+ */
3103
+ groupedColumnMode?: false | &quot;reorder&quot; | &quot;remove&quot; | undefined
3104
+
3105
+ /**
3106
+ * Use this option to optionally pass initial state to the table. This state will be used when resetting various table states either automatically by the table (eg. `options.autoResetPageIndex`) or via functions like `table.resetRowSelection()`. Most reset function allow you optionally pass a flag to reset to a blank/default state instead of the initial state.
3107
+ *
3108
+ * Table state will not be reset when this object changes, which also means that the initial state object does not need to be stable.
3109
+ */
3110
+ initialState?: InitialTableState
3111
+
3112
+ /**
3113
+ * Dims the table while data is loading and suppresses the empty state.
3114
+ */
3115
+ isLoading?: boolean = false
3116
+
3117
+ /**
3118
+ * Pass a custom function that will be used to determine if a multi-sort event should be triggered. It is passed the event from the sort toggle handler and should return `true` if the event should trigger a multi-sort.
3119
+ */
3120
+ isMultiSortEvent?: (e: unknown) =&gt; boolean
3121
+
3122
+ /**
3123
+ * When `false`, pinned rows will not be visible if they are filtered or paginated out of the table. When `true`, pinned rows will always be visible regardless of filtering or pagination. Defaults to `true`.
3124
+ */
3125
+ keepPinnedRows?: boolean
3126
+
3127
+ /**
3128
+ * Renders the per-row link when `rowHref` is set. Defaults to `&#39;a&#39;`; pass a
3129
+ * framework link (e.g. Next.js `Link`) for client-side navigation.
3130
+ */
3131
+ linkComponent?: ElementType | undefined = &#39;a&#39;
3132
+
3133
+ /**
3134
+ * Enables manual row expansion. If this is set to `true`, `getExpandedRowModel` will not be used to expand rows and you would be expected to perform the expansion in your own data model. This is useful if you are doing server-side expansion.
3135
+ */
3136
+ manualExpanding?: boolean
3137
+
3138
+ /**
3139
+ * Disables the `getFilteredRowModel` from being used to filter data. This may be useful if your table needs to dynamically support both client-side and server-side filtering.
3140
+ */
3141
+ manualFiltering?: boolean
3142
+
3143
+ /**
3144
+ * Enables manual grouping. If this option is set to `true`, the table will not automatically group rows using `getGroupedRowModel()` and instead will expect you to manually group the rows before passing them to the table. This is useful if you are doing server-side grouping and aggregation.
3145
+ */
3146
+ manualGrouping?: boolean
3147
+
3148
+ /**
3149
+ * Enables manual pagination. If this option is set to `true`, the table will not automatically paginate rows using `getPaginationRowModel()` and instead will expect you to manually paginate the rows before passing them to the table. This is useful if you are doing server-side pagination and aggregation.
3150
+ */
3151
+ manualPagination?: boolean
3152
+
3153
+ /**
3154
+ * Enables manual sorting for the table. If this is `true`, you will be expected to sort your data before it is passed to the table. This is useful if you are doing server-side sorting.
3155
+ */
3156
+ manualSorting?: boolean
3157
+
3158
+ /**
3159
+ * By default, filtering is done for all rows (max depth of 100), no matter if they are root level parent rows or the child leaf rows of a parent row. Setting this option to `0` will cause filtering to only be applied to the root level parent rows, with all sub-rows remaining unfiltered. Similarly, setting this option to `1` will cause filtering to only be applied to child leaf rows 1 level deep, and so on.
3160
+ *
3161
+ * This is useful for situations where you want a row&#39;s entire child hierarchy to be visible regardless of the applied filter.
3162
+ */
3163
+ maxLeafRowFilterDepth?: number
3164
+
3165
+ /**
3166
+ * Set a maximum number of columns that can be multi-sorted.
3167
+ */
3168
+ maxMultiSortColCount?: number
3169
+
3170
+ /**
3171
+ * This option is used to optionally implement the merging of table options.
3172
+ */
3173
+ mergeOptions?: (defaultOptions: TableOptions&lt;Lead&gt;, options: Partial&lt;TableOptions&lt;Lead&gt;&gt;) =&gt; TableOptions&lt;Lead&gt;
3174
+
3175
+ /**
3176
+ * You can pass any object to `options.meta` and access it anywhere the `table` is available via `table.options.meta`.
3177
+ */
3178
+ meta?: TableMeta&lt;Lead&gt;
3179
+
3180
+ /**
3181
+ * If provided, this function will be called with an `updaterFn` when `state.columnFilters` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3182
+ */
3183
+ onColumnFiltersChange?: OnChangeFn&lt;ColumnFiltersState&gt;
3184
+
3185
+ /**
3186
+ * If provided, this function will be called with an `updaterFn` when `state.columnOrder` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3187
+ */
3188
+ onColumnOrderChange?: OnChangeFn&lt;ColumnOrderState&gt;
3189
+
3190
+ /**
3191
+ * If provided, this function will be called with an `updaterFn` when `state.columnPinning` changes. This overrides the default internal state management, so you will also need to supply `state.columnPinning` from your own managed state.
3192
+ */
3193
+ onColumnPinningChange?: OnChangeFn&lt;ColumnPinningState&gt;
3194
+
3195
+ /**
3196
+ * If provided, this function will be called with an `updaterFn` when `state.columnSizing` changes. This overrides the default internal state management, so you will also need to supply `state.columnSizing` from your own managed state.
3197
+ */
3198
+ onColumnSizingChange?: OnChangeFn&lt;ColumnSizingState&gt;
3199
+
3200
+ /**
3201
+ * If provided, this function will be called with an `updaterFn` when `state.columnSizingInfo` changes. This overrides the default internal state management, so you will also need to supply `state.columnSizingInfo` from your own managed state.
3202
+ */
3203
+ onColumnSizingInfoChange?: OnChangeFn&lt;ColumnSizingInfoState&gt;
3204
+
3205
+ /**
3206
+ * If provided, this function will be called with an `updaterFn` when `state.columnVisibility` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3207
+ */
3208
+ onColumnVisibilityChange?: OnChangeFn&lt;VisibilityState&gt;
3209
+
3210
+ /**
3211
+ * This function is called when the `expanded` table state changes. If a function is provided, you will be responsible for managing this state on your own. To pass the managed state back to the table, use the `tableOptions.state.expanded` option.
3212
+ */
3213
+ onExpandedChange?: OnChangeFn&lt;ExpandedState&gt;
3214
+
3215
+ /**
3216
+ * If provided, this function will be called with an `updaterFn` when `state.globalFilter` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3217
+ */
3218
+ onGlobalFilterChange?: OnChangeFn&lt;any&gt;
3219
+
3220
+ /**
3221
+ * If this function is provided, it will be called when the grouping state changes and you will be expected to manage the state yourself. You can pass the managed state back to the table via the `tableOptions.state.grouping` option.
3222
+ */
3223
+ onGroupingChange?: OnChangeFn&lt;GroupingState&gt;
3224
+
3225
+ /**
3226
+ * If this function is provided, it will be called when the pagination state changes and you will be expected to manage the state yourself. You can pass the managed state back to the table via the `tableOptions.state.pagination` option.
3227
+ */
3228
+ onPaginationChange?: OnChangeFn&lt;PaginationState&gt;
3229
+
3230
+ /**
3231
+ * Called with the row&#39;s data when a non-interactive part of the row is clicked.
3232
+ */
3233
+ onRowClick?: (row: Lead) =&gt; void
3234
+
3235
+ /**
3236
+ * If provided, this function will be called with an `updaterFn` when `state.rowPinning` changes. This overrides the default internal state management, so you will also need to supply `state.rowPinning` from your own managed state.
3237
+ */
3238
+ onRowPinningChange?: OnChangeFn&lt;RowPinningState&gt;
3239
+
3240
+ /**
3241
+ * If provided, this function will be called with an `updaterFn` when `state.rowSelection` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3242
+ */
3243
+ onRowSelectionChange?: OnChangeFn&lt;RowSelectionState&gt;
3244
+
3245
+ /**
3246
+ * If provided, this function will be called with an `updaterFn` when `state.sorting` changes. This overrides the default internal state management, so you will need to persist the state change either fully or partially outside of the table.
3247
+ */
3248
+ onSortingChange?: OnChangeFn&lt;SortingState&gt;
3249
+
3250
+ /**
3251
+ * The `onStateChange` option can be used to optionally listen to state changes within the table.
3252
+ */
3253
+ onStateChange?: (updater: Updater&lt;TableState&gt;) =&gt; void
3254
+
3255
+ /**
3256
+ * When manually controlling pagination, you can supply a total `pageCount` value to the table if you know it (Or supply a `rowCount` and `pageCount` will be calculated). If you do not know how many pages there are, you can set this to `-1`.
3257
+ */
3258
+ pageCount?: number
3259
+
3260
+ /**
3261
+ * If `true` expanded rows will be paginated along with the rest of the table (which means expanded rows may span multiple pages). If `false` expanded rows will not be considered for pagination (which means expanded rows will always render on their parents page. This also means more rows will be rendered than the set page size)
3262
+ */
3263
+ paginateExpandedRows?: boolean
3264
+
3265
+ /**
3266
+ * Value used when the desired value is not found in the data.
3267
+ */
3268
+ renderFallbackValue?: any
3269
+
3270
+ /**
3271
+ * When manually controlling pagination, you can supply a total `rowCount` value to the table if you know it. The `pageCount` can be calculated from this value and the `pageSize`.
3272
+ */
3273
+ rowCount?: number
3274
+
3275
+ /**
3276
+ * Returns an href for a row; the row becomes a link (see `linkComponent`).
3277
+ */
3278
+ rowHref?: (row: Lead) =&gt; string
3279
+
3280
+ /**
3281
+ * If `true`, all sorts will default to descending as their first toggle state.
3282
+ */
3283
+ sortDescFirst?: boolean
3284
+
3285
+ sortingFns?: Record&lt;string, SortingFn&lt;any&gt;&gt;
3286
+
3287
+ /**
3288
+ * The `state` option can be used to optionally _control_ part or all of the table state. The state you pass here will merge with and overwrite the internal automatically-managed state to produce the final state for the table. You can also listen to state changes via the `onStateChange` option.
3289
+ * &gt; Note: Any state passed in here will override both the internal state and any other `initialState` you provide.
3290
+ */
3291
+ state?: Partial&lt;TableState&gt;</code></pre>
3292
+ </div>
3293
+ </div>
3294
+
3295
+ <div class="panel panel-stories">
3296
+
3297
+
3298
+
3299
+ <div class="note ok">
3300
+ <div class="row">
3301
+ <span class="ex-name">Imports</span>
3302
+ </div>
3303
+ <pre><code>import { Button, DataTable, DropdownMenu, Pagination, Table } from "@agentero/design-system";</code></pre>
3304
+ </div>
3305
+
3306
+
3307
+ <div class="note ok">
3308
+ <div class="row">
3309
+ <span class="ex-name">Playground</span>
3310
+ <span class="badge ok">story ok</span>
3311
+ </div>
3312
+ <div>Display props playground (size / embed / enclosed / sticky)</div>
3313
+ <div class="hint">Playground for `DataTable.Table` display props — toggle `size`, `embed`,
3314
+ `enclosed`, and `sticky` from the controls panel.</div>
3315
+ <pre><code>const Playground = () =&gt; &lt;div
3316
+ className={args.enclosed ? &#39;flex min-h-0 flex-1 flex-col p-4&#39; : &#39;contents&#39;}&gt;
3317
+ &lt;DataTable.Root data={LEADS} columns={columns}&gt;
3318
+ &lt;DataTable.Table size=&quot;md&quot; embed enclosed={false} sticky=&quot;header&quot; /&gt;
3319
+ &lt;/DataTable.Root&gt;
3320
+ &lt;/div&gt;;</code></pre>
3321
+ </div>
3322
+ <div class="note ok">
3323
+ <div class="row">
3324
+ <span class="ex-name">Leads</span>
3325
+ <span class="badge ok">story ok</span>
3326
+ </div>
3327
+ <div>Representative leads table composition</div>
3328
+ <div class="hint">A leads-table composition: sortable `Created` column, a status badge, row
3329
+ navigation via `rowHref`, hover-revealed actions, a search input + filters in
3330
+ the toolbar, and pagination in the footer.</div>
3331
+ <pre><code>const Leads = () =&gt; {
3332
+ const [sorting, setSorting] = useState&lt;SortingState&gt;([]);
3333
+ const [page, setPage] = useState(1);
3334
+ const [search, setSearch] = useState(&#39;&#39;);
3335
+
3336
+ const data = useMemo(
3337
+ () =&gt; LEADS.filter(l =&gt; l.contact.toLowerCase().includes(search.toLowerCase())),
3338
+ [search]
3339
+ );
3340
+
3341
+ return (
3342
+ &lt;DataTable.Root
3343
+ data={data}
3344
+ columns={columns}
3345
+ state={{ sorting }}
3346
+ onSortingChange={setSorting}
3347
+ getSortedRowModel={getSortedRowModel()}
3348
+ enableSortingRemoval={false}
3349
+ rowHref={lead =&gt; `/leads/${lead.leadId}`}&gt;
3350
+ &lt;DataTable.ToolBar&gt;
3351
+ &lt;input
3352
+ value={search}
3353
+ onChange={e =&gt; setSearch(e.target.value)}
3354
+ placeholder=&quot;Search...&quot;
3355
+ aria-label=&quot;Search leads&quot;
3356
+ className=&quot;h-8 w-60 rounded-md border border-border-default-base-primary px-3 text-sm outline-none&quot;
3357
+ /&gt;
3358
+ &lt;Button variant=&quot;secondary&quot; size=&quot;sm&quot;&gt;
3359
+ Filters
3360
+ &lt;/Button&gt;
3361
+ &lt;/DataTable.ToolBar&gt;
3362
+
3363
+ &lt;DataTable.Table /&gt;
3364
+
3365
+ &lt;DataTable.Footer&gt;
3366
+ &lt;Pagination
3367
+ totalCount={LEADS.length}
3368
+ currentPage={page}
3369
+ pageSize={10}
3370
+ onPageChange={setPage}
3371
+ /&gt;
3372
+ &lt;/DataTable.Footer&gt;
3373
+ &lt;/DataTable.Root&gt;
3374
+ );
3375
+ };</code></pre>
3376
+ </div>
3377
+ <div class="note ok">
3378
+ <div class="row">
3379
+ <span class="ex-name">Empty</span>
3380
+ <span class="badge ok">story ok</span>
3381
+ </div>
3382
+ <div>Empty state when there are no rows</div>
3383
+ <div class="hint">No rows: the table renders its default empty state instead of body rows.</div>
3384
+ <pre><code>const Empty = () =&gt; (
3385
+ &lt;DataTable.Root data={[] as Lead[]} columns={columns}&gt;
3386
+ &lt;DataTable.Table /&gt;
3387
+ &lt;/DataTable.Root&gt;
3388
+ );</code></pre>
3389
+ </div>
3390
+ <div class="note ok">
3391
+ <div class="row">
3392
+ <span class="ex-name">Loading</span>
3393
+ <span class="badge ok">story ok</span>
3394
+ </div>
3395
+ <div>Loading state dims the table and hides the empty state</div>
3396
+ <div class="hint">Loading: the body is dimmed and the empty state is suppressed while data is
3397
+ in flight.</div>
3398
+ <pre><code>const Loading = () =&gt; (
3399
+ &lt;DataTable.Root data={[] as Lead[]} columns={columns} isLoading&gt;
3400
+ &lt;DataTable.Table /&gt;
3401
+ &lt;/DataTable.Root&gt;
3402
+ );</code></pre>
3403
+ </div>
3404
+ </div>
3405
+
3406
+
3407
+ </div>
3408
+ </article>
3409
+ <article
3410
+ class="card
3411
+ no-error
3412
+ no-info
3413
+ no-story-error
3414
+ no-doc-error"
3415
+ role="listitem"
3416
+ aria-label="Divider">
3417
+ <div class="head">
3418
+ <div class="title">
3419
+ <h2><span class="status-dot dot-ok"></span> Divider</h2>
3420
+ <div class="badges">
3421
+ <label for="c-8-components-divider-props" class="badge ok as-toggle">4 prop types</label>
3422
+
3423
+ <label for="c-8-components-divider-stories" class="badge ok as-toggle">10 stories</label>
3424
+
3425
+
3426
+ </div>
3427
+ </div>
3428
+ <div class="meta" title="./src/divider/divider.stories.tsx">components-divider · ./src/divider/divider.stories.tsx</div>
3429
+ <div>Visual or semantic separator that optionally renders a centered label</div>
3430
+ <div class="hint">Divider separates content visually along either a horizontal or vertical
3431
+ axis. Use between page or card sections, between inline items in a toolbar
3432
+ or list, or — with the `label` prop — to render an &quot;or&quot;-style break between
3433
+ options. Set `decorative={false}` when the separator carries semantic
3434
+ meaning so it&#39;s announced to assistive technologies.</div>
3435
+ <div class="kv"><span class="chip">summary: Visual or semantic separator that optionally renders a centered label</span><span class="chip">param: orientation - Axis along which the separator renders. Defaults to `&#39;horizontal&#39;`.
3436
+ - `horizontal` — 1px line spanning the parent width.
3437
+ - `vertical` — 1px line spanning the parent height; parent must establish a height.</span><span class="chip">param: decorative - When `true` (default), the separator is purely visual and hidden
3438
+ from assistive technologies. Set to `false` to expose `role=&quot;separator&quot;` plus
3439
+ `aria-orientation` for meaningful section breaks.</span><span class="chip">param: label - Optional inline content rendered between two flanking 1px lines.
3440
+ When omitted, Divider renders a single line.</span><span class="chip">example: &lt;Divider /&gt;</span><span class="chip">example: &lt;Divider orientation=&quot;vertical&quot; /&gt;</span><span class="chip">example: &lt;Divider label=&quot;or&quot; /&gt;</span><span class="chip">example: &lt;Divider decorative={false} /&gt;</span></div>
3441
+ </div>
3442
+
3443
+ <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
3444
+
3445
+
3446
+ <input id="c-8-components-divider-stories" class="tg tg-stories" type="checkbox" hidden />
3447
+
3448
+
3449
+ <input id="c-8-components-divider-props" class="tg tg-props" type="checkbox" hidden />
3450
+
3451
+ <div class="panels">
2655
3452
 
2656
3453
 
2657
3454
 
2658
3455
  <div class="panel panel-props">
2659
3456
  <div class="note ok">
2660
3457
  <div class="row">
2661
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
2662
- <span class="badge ok">2 prop types</span>
3458
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
3459
+ <span class="badge ok">4 prop types</span>
2663
3460
  </div>
2664
3461
  <pre><code>Component: src/divider/divider.tsx::Divider</code></pre>
2665
3462
  <pre><code>Props:</code></pre>
2666
3463
  <pre><code>asChild?: boolean
2667
3464
 
3465
+ /**
3466
+ * Whether or not the component is purely decorative. When true, accessibility-related attributes
3467
+ * are updated so that that the rendered element is removed from the accessibility tree.
3468
+ */
3469
+ decorative?: boolean = true
3470
+
2668
3471
  /**
2669
3472
  * Optional label rendered inline between two flanking 1px lines. When set,
2670
3473
  * Divider renders a styled `&lt;div&gt;` (rather than the underlying separator
2671
3474
  * primitive) so the label can sit centered between the two line segments.
2672
3475
  */
2673
- label?: ReactNode</code></pre>
3476
+ label?: ReactNode
3477
+
3478
+ /**
3479
+ * Either `vertical` or `horizontal`. Defaults to `horizontal`.
3480
+ */
3481
+ orientation?: &quot;horizontal&quot; | &quot;vertical&quot; = &#39;horizontal&#39;</code></pre>
2674
3482
  </div>
2675
3483
  </div>
2676
3484
 
@@ -2692,7 +3500,8 @@ label?: ReactNode</code></pre>
2692
3500
  <span class="badge ok">story ok</span>
2693
3501
  </div>
2694
3502
  <div>Default horizontal decorative divider</div>
2695
- <div class="hint">The default horizontal, decorative divider — a 1px line that spans the parent width. Use this form between stacked content blocks.</div>
3503
+ <div class="hint">The default horizontal, decorative divider — a 1px line that spans the
3504
+ parent width. Use this form between stacked content blocks.</div>
2696
3505
  <pre><code>const Default = () =&gt; &lt;div
2697
3506
  className={cn(
2698
3507
  &#39;flex gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6&#39;,
@@ -2717,7 +3526,8 @@ label?: ReactNode</code></pre>
2717
3526
  <span class="badge ok">story ok</span>
2718
3527
  </div>
2719
3528
  <div>Horizontal 1px line spanning the parent width</div>
2720
- <div class="hint">Horizontal divider — a 1px line spanning the parent&#39;s full width. The default orientation; use to separate stacked content.</div>
3529
+ <div class="hint">Horizontal divider — a 1px line spanning the parent&#39;s full width. The
3530
+ default orientation; use to separate stacked content.</div>
2721
3531
  <pre><code>const Horizontal = () =&gt; (
2722
3532
  &lt;div className=&quot;w-80&quot;&gt;
2723
3533
  &lt;Divider /&gt;
@@ -2730,7 +3540,9 @@ label?: ReactNode</code></pre>
2730
3540
  <span class="badge ok">story ok</span>
2731
3541
  </div>
2732
3542
  <div>Vertical 1px line spanning the parent height</div>
2733
- <div class="hint">Vertical divider — a 1px line spanning the parent&#39;s full height. Parent must establish a height (via `h-*` or an intrinsic flex item height) for the line to be visible.</div>
3543
+ <div class="hint">Vertical divider — a 1px line spanning the parent&#39;s full height. Parent must
3544
+ establish a height (via `h-*` or an intrinsic flex item height) for the line
3545
+ to be visible.</div>
2734
3546
  <pre><code>const Vertical = () =&gt; (
2735
3547
  &lt;div className=&quot;flex h-24 items-stretch&quot;&gt;
2736
3548
  &lt;Divider orientation=&quot;vertical&quot; /&gt;
@@ -2743,7 +3555,8 @@ label?: ReactNode</code></pre>
2743
3555
  <span class="badge ok">story ok</span>
2744
3556
  </div>
2745
3557
  <div>Horizontal divider with a centered &quot;or&quot; label</div>
2746
- <div class="hint">Labelled divider. The label sits centered between two flanking 1px lines — a common pattern for &quot;or&quot; breaks between authentication options.</div>
3558
+ <div class="hint">Labelled divider. The label sits centered between two flanking 1px lines —
3559
+ a common pattern for &quot;or&quot; breaks between authentication options.</div>
2747
3560
  <pre><code>const WithLabel = () =&gt; &lt;div className=&quot;flex w-80 flex-col gap-2&quot;&gt;
2748
3561
  &lt;Button variant=&quot;primary&quot;&gt;Continue with email&lt;/Button&gt;
2749
3562
  &lt;Divider orientation=&quot;horizontal&quot; decorative label=&quot;or&quot; /&gt;
@@ -2756,7 +3569,8 @@ label?: ReactNode</code></pre>
2756
3569
  <span class="badge ok">story ok</span>
2757
3570
  </div>
2758
3571
  <div>Vertical divider with a centered label</div>
2759
- <div class="hint">Vertical divider with a label. The label sits between two stacked 1px line segments; use sparingly — horizontal labelled dividers are more common.</div>
3572
+ <div class="hint">Vertical divider with a label. The label sits between two stacked 1px line
3573
+ segments; use sparingly — horizontal labelled dividers are more common.</div>
2760
3574
  <pre><code>const VerticalWithLabel = () =&gt; &lt;div
2761
3575
  className=&quot;flex h-40 items-stretch gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6&quot;&gt;
2762
3576
  &lt;div className=&quot;flex flex-col justify-center gap-1&quot;&gt;
@@ -2776,7 +3590,9 @@ label?: ReactNode</code></pre>
2776
3590
  <span class="badge ok">story ok</span>
2777
3591
  </div>
2778
3592
  <div>Semantic separator announced to assistive technologies</div>
2779
- <div class="hint">Semantic divider (`decorative={false}`). Exposes `role=&quot;separator&quot;` and `aria-orientation` to assistive technologies, marking a meaningful section break rather than a purely visual one.</div>
3593
+ <div class="hint">Semantic divider (`decorative={false}`). Exposes `role=&quot;separator&quot;` and
3594
+ `aria-orientation` to assistive technologies, marking a meaningful section
3595
+ break rather than a purely visual one.</div>
2780
3596
  <pre><code>const Semantic = () =&gt; &lt;div
2781
3597
  className=&quot;flex w-80 flex-col gap-4 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary p-6&quot;&gt;
2782
3598
  &lt;section className=&quot;flex flex-col gap-1&quot;&gt;
@@ -2798,7 +3614,8 @@ label?: ReactNode</code></pre>
2798
3614
  <span class="badge ok">story ok</span>
2799
3615
  </div>
2800
3616
  <div>Horizontal dividers between stacked list rows</div>
2801
- <div class="hint">Divider between list rows. Dividers delineate each item without the visual weight of a full border on every row.</div>
3617
+ <div class="hint">Divider between list rows. Dividers delineate each item without the visual
3618
+ weight of a full border on every row.</div>
2802
3619
  <pre><code>const InList = () =&gt; (
2803
3620
  &lt;div className=&quot;w-80 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary&quot;&gt;
2804
3621
  &lt;div className=&quot;flex flex-col gap-1 px-4 py-3&quot;&gt;
@@ -2830,7 +3647,9 @@ label?: ReactNode</code></pre>
2830
3647
  <span class="badge ok">story ok</span>
2831
3648
  </div>
2832
3649
  <div>Vertical dividers grouping toolbar actions</div>
2833
- <div class="hint">Vertical dividers grouping related toolbar actions. Use to separate logical clusters of buttons (editing vs. history vs. settings) without visual weight.</div>
3650
+ <div class="hint">Vertical dividers grouping related toolbar actions. Use to separate logical
3651
+ clusters of buttons (editing vs. history vs. settings) without visual
3652
+ weight.</div>
2834
3653
  <pre><code>const InToolbar = () =&gt; (
2835
3654
  &lt;div className=&quot;inline-flex h-10 items-center gap-1 rounded-lg border border-border-default-base-primary bg-bg-default-base-primary px-2 shadow-1&quot;&gt;
2836
3655
  &lt;Button variant=&quot;ghost&quot; size=&quot;xs&quot;&gt;
@@ -2862,7 +3681,8 @@ label?: ReactNode</code></pre>
2862
3681
  <span class="badge ok">story ok</span>
2863
3682
  </div>
2864
3683
  <div>Horizontal dividers between content sections</div>
2865
- <div class="hint">Horizontal dividers between content sections in a long-form layout. Helps create visual hierarchy in content-heavy pages.</div>
3684
+ <div class="hint">Horizontal dividers between content sections in a long-form layout. Helps
3685
+ create visual hierarchy in content-heavy pages.</div>
2866
3686
  <pre><code>const HorizontalInContent = () =&gt; (
2867
3687
  &lt;div className=&quot;flex w-96 flex-col gap-4 p-6&quot;&gt;
2868
3688
  &lt;div className=&quot;flex flex-col gap-1&quot;&gt;
@@ -2894,7 +3714,8 @@ label?: ReactNode</code></pre>
2894
3714
  <span class="badge ok">story ok</span>
2895
3715
  </div>
2896
3716
  <div>Vertical dividers separating inline elements</div>
2897
- <div class="hint">Vertical dividers between inline elements. Common for separating a row of related controls or inline links without visual weight.</div>
3717
+ <div class="hint">Vertical dividers between inline elements. Common for separating a row of
3718
+ related controls or inline links without visual weight.</div>
2898
3719
  <pre><code>const VerticalBetweenElements = () =&gt; (
2899
3720
  &lt;div className=&quot;flex items-stretch gap-3&quot;&gt;
2900
3721
  &lt;Button variant=&quot;primary&quot; size=&quot;sm&quot;&gt;
@@ -2913,6 +3734,7 @@ label?: ReactNode</code></pre>
2913
3734
  </div>
2914
3735
  </div>
2915
3736
 
3737
+
2916
3738
  </div>
2917
3739
  </article>
2918
3740
  <article
@@ -2927,16 +3749,62 @@ label?: ReactNode</code></pre>
2927
3749
  <div class="title">
2928
3750
  <h2><span class="status-dot dot-ok"></span> DropdownMenu.Root</h2>
2929
3751
  <div class="badges">
2930
-
3752
+ <label for="c-9-components-dropdownmenu-props" class="badge ok as-toggle">6 prop types</label>
2931
3753
 
2932
3754
  <label for="c-9-components-dropdownmenu-stories" class="badge ok as-toggle">7 stories</label>
2933
3755
 
3756
+
2934
3757
  </div>
2935
3758
  </div>
2936
3759
  <div class="meta" title="./src/dropdown-menu/dropdown-menu.stories.tsx">components-dropdownmenu · ./src/dropdown-menu/dropdown-menu.stories.tsx</div>
2937
-
2938
- <div class="hint">DropdownMenu is a compound overlay for secondary actions, bulk operations, or navigation shortcuts triggered off a button or icon. Compose it from `Root` / `Trigger` / `Portal` / `Content` and fill the menu with `Item`, `Separator`, `Label`, and — for nested flows — `Sub` / `SubTrigger` / `SubContent`. Built on Radix UI&#39;s DropdownMenu primitive, so keyboard navigation, focus trapping, typeahead, and collision detection come for free.</div>
2939
-
3760
+ <div>Root provider for a DropdownMenu&#39;s open state</div>
3761
+ <div class="hint">DropdownMenu is a compound overlay for secondary actions, bulk operations,
3762
+ or navigation shortcuts triggered off a button or icon. Compose it from
3763
+ `Root` / `Trigger` / `Portal` / `Content` and fill the menu with `Item`,
3764
+ `Separator`, `Label`, and — for nested flows — `Sub` / `SubTrigger` /
3765
+ `SubContent`. Built on Radix UI&#39;s DropdownMenu primitive, so keyboard
3766
+ navigation, focus trapping, typeahead, and collision detection come for
3767
+ free.</div>
3768
+ <div class="kv"><span class="chip">summary: Root provider for a DropdownMenu&#39;s open state</span><span class="chip">see: {@link https://www.radix-ui.com/primitives/docs/components/dropdown-menu Radix UI DropdownMenu}</span><span class="chip">example: ```tsx
3769
+ import { DropdownMenu } from &#39;@agentero/design-system/dropdown-menu&#39;;
3770
+
3771
+ &lt;DropdownMenu.Root&gt;
3772
+ &lt;DropdownMenu.Trigger&gt;
3773
+ &lt;IconMoreVert /&gt;
3774
+ &lt;/DropdownMenu.Trigger&gt;
3775
+
3776
+ &lt;DropdownMenu.Portal&gt;
3777
+ &lt;DropdownMenu.Content side=&quot;bottom&quot; align=&quot;end&quot;&gt;
3778
+ &lt;DropdownMenu.Label&gt;Actions&lt;/DropdownMenu.Label&gt;
3779
+
3780
+ &lt;DropdownMenu.Item onSelect={() =&gt; handleEdit()}&gt;
3781
+ &lt;IconEdit /&gt;
3782
+ Edit
3783
+ &lt;/DropdownMenu.Item&gt;
3784
+
3785
+ &lt;DropdownMenu.Sub&gt;
3786
+ &lt;DropdownMenu.SubTrigger&gt;Share&lt;/DropdownMenu.SubTrigger&gt;
3787
+ &lt;DropdownMenu.Portal&gt;
3788
+ &lt;DropdownMenu.SubContent&gt;
3789
+ &lt;DropdownMenu.Item&gt;Email&lt;/DropdownMenu.Item&gt;
3790
+ &lt;DropdownMenu.Item&gt;Slack&lt;/DropdownMenu.Item&gt;
3791
+ &lt;/DropdownMenu.SubContent&gt;
3792
+ &lt;/DropdownMenu.Portal&gt;
3793
+ &lt;/DropdownMenu.Sub&gt;
3794
+
3795
+ &lt;DropdownMenu.Separator /&gt;
3796
+
3797
+ &lt;DropdownMenu.Item
3798
+ onSelect={() =&gt; handleDelete()}
3799
+ disabled={!canDelete}
3800
+ &gt;
3801
+ &lt;IconDelete /&gt;
3802
+ Delete
3803
+ &lt;/DropdownMenu.Item&gt;
3804
+ &lt;/DropdownMenu.Content&gt;
3805
+ &lt;/DropdownMenu.Portal&gt;
3806
+ &lt;/DropdownMenu.Root&gt;
3807
+ ```</span></div>
2940
3808
  </div>
2941
3809
 
2942
3810
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -2945,11 +3813,33 @@ label?: ReactNode</code></pre>
2945
3813
  <input id="c-9-components-dropdownmenu-stories" class="tg tg-stories" type="checkbox" hidden />
2946
3814
 
2947
3815
 
3816
+ <input id="c-9-components-dropdownmenu-props" class="tg tg-props" type="checkbox" hidden />
2948
3817
 
2949
3818
  <div class="panels">
2950
3819
 
2951
3820
 
2952
3821
 
3822
+ <div class="panel panel-props">
3823
+ <div class="note ok">
3824
+ <div class="row">
3825
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
3826
+ <span class="badge ok">6 prop types</span>
3827
+ </div>
3828
+ <pre><code>Component: src/dropdown-menu/index.ts::DropdownMenu</code></pre>
3829
+ <pre><code>Props:</code></pre>
3830
+ <pre><code>children?: ReactNode
3831
+
3832
+ defaultOpen?: boolean
3833
+
3834
+ dir?: &quot;ltr&quot; | &quot;rtl&quot;
3835
+
3836
+ modal?: boolean
3837
+
3838
+ onOpenChange?: (open: boolean) =&gt; void
3839
+
3840
+ open?: boolean</code></pre>
3841
+ </div>
3842
+ </div>
2953
3843
 
2954
3844
  <div class="panel panel-stories">
2955
3845
 
@@ -2969,7 +3859,9 @@ label?: ReactNode</code></pre>
2969
3859
  <span class="badge ok">story ok</span>
2970
3860
  </div>
2971
3861
  <div>Basic menu with item rows and a separated destructive action</div>
2972
- <div class="hint">A minimal DropdownMenu with four `Item`s — edit/duplicate/archive plus a separator before a destructive delete. Use this as the starting point for most overflow menus.</div>
3862
+ <div class="hint">A minimal DropdownMenu with four `Item`s — edit/duplicate/archive plus a
3863
+ separator before a destructive delete. Use this as the starting point for
3864
+ most overflow menus.</div>
2973
3865
  <pre><code>const Default = () =&gt; (
2974
3866
  &lt;DropdownMenu.Root&gt;
2975
3867
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3002,7 +3894,9 @@ label?: ReactNode</code></pre>
3002
3894
  <span class="badge ok">story ok</span>
3003
3895
  </div>
3004
3896
  <div>Menu with multiple `Separator`-split groups and a disabled item</div>
3005
- <div class="hint">Multiple clusters of `Item`s split by `Separator` rules — mirrors an &quot;edit history / clipboard / export&quot; overflow menu. Demonstrates the `disabled` state on a menu row.</div>
3897
+ <div class="hint">Multiple clusters of `Item`s split by `Separator` rules — mirrors an
3898
+ &quot;edit history / clipboard / export&quot; overflow menu. Demonstrates the
3899
+ `disabled` state on a menu row.</div>
3006
3900
  <pre><code>const WithGroupsAndDividers = () =&gt; (
3007
3901
  &lt;DropdownMenu.Root&gt;
3008
3902
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3033,7 +3927,9 @@ label?: ReactNode</code></pre>
3033
3927
  <span class="badge ok">story ok</span>
3034
3928
  </div>
3035
3929
  <div>Icon-leading items with a destructive delete row</div>
3036
- <div class="hint">Menu items with leading icons and a destructive row using the `data-[highlighted]:bg-red-100` + `text-red-500` escape hatch. Use this pattern when a row should read as destructive.</div>
3930
+ <div class="hint">Menu items with leading icons and a destructive row using the
3931
+ `data-[highlighted]:bg-red-100` + `text-red-500` escape hatch. Use this
3932
+ pattern when a row should read as destructive.</div>
3037
3933
  <pre><code>const WithIcons = () =&gt; (
3038
3934
  &lt;DropdownMenu.Root&gt;
3039
3935
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3066,7 +3962,9 @@ label?: ReactNode</code></pre>
3066
3962
  <span class="badge ok">story ok</span>
3067
3963
  </div>
3068
3964
  <div>Menu with `Label`-titled sections and a destructive logout row</div>
3069
- <div class="hint">`Label`-segmented Profile / Settings / Account sections with a destructive Logout row. Use `Label` to name groups that would otherwise be ambiguous from the item text alone.</div>
3965
+ <div class="hint">`Label`-segmented Profile / Settings / Account sections with a
3966
+ destructive Logout row. Use `Label` to name groups that would otherwise
3967
+ be ambiguous from the item text alone.</div>
3070
3968
  <pre><code>const WithGroupTitles = () =&gt; (
3071
3969
  &lt;DropdownMenu.Root&gt;
3072
3970
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3112,7 +4010,9 @@ label?: ReactNode</code></pre>
3112
4010
  <span class="badge ok">story ok</span>
3113
4011
  </div>
3114
4012
  <div>Single-level submenus for Share and Move-to flows</div>
3115
- <div class="hint">One level of nesting: Share and Move-to submenus wired via `Sub` / `SubTrigger` / `SubContent`. Each submenu is portaled independently so it escapes the parent&#39;s stacking context.</div>
4013
+ <div class="hint">One level of nesting: Share and Move-to submenus wired via `Sub` /
4014
+ `SubTrigger` / `SubContent`. Each submenu is portaled independently so
4015
+ it escapes the parent&#39;s stacking context.</div>
3116
4016
  <pre><code>const WithSubmenu = () =&gt; (
3117
4017
  &lt;DropdownMenu.Root&gt;
3118
4018
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3176,7 +4076,9 @@ label?: ReactNode</code></pre>
3176
4076
  <span class="badge ok">story ok</span>
3177
4077
  </div>
3178
4078
  <div>Two-level nested submenus inside a parent menu</div>
3179
- <div class="hint">Two levels of nesting: Organization → Teams → (Engineering, Design). Deeper nesting is rarely a good UX — prefer splitting into separate screens once the tree grows past two levels.</div>
4079
+ <div class="hint">Two levels of nesting: Organization → Teams → (Engineering, Design).
4080
+ Deeper nesting is rarely a good UX — prefer splitting into separate
4081
+ screens once the tree grows past two levels.</div>
3180
4082
  <pre><code>const NestedSubmenus = () =&gt; (
3181
4083
  &lt;DropdownMenu.Root&gt;
3182
4084
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3248,7 +4150,9 @@ label?: ReactNode</code></pre>
3248
4150
  <span class="badge ok">story ok</span>
3249
4151
  </div>
3250
4152
  <div>Submenu with `disabled` items and a disabled `SubTrigger`</div>
3251
- <div class="hint">Submenu that contains `disabled` `Item`s alongside a fully-disabled `SubTrigger`. Use `disabled` sparingly — prefer hiding unavailable actions outright unless the user needs to see them and understand why.</div>
4153
+ <div class="hint">Submenu that contains `disabled` `Item`s alongside a fully-disabled
4154
+ `SubTrigger`. Use `disabled` sparingly — prefer hiding unavailable
4155
+ actions outright unless the user needs to see them and understand why.</div>
3252
4156
  <pre><code>const SubmenuWithDisabledItems = () =&gt; (
3253
4157
  &lt;DropdownMenu.Root&gt;
3254
4158
  &lt;DropdownMenu.Trigger asChild&gt;
@@ -3297,6 +4201,7 @@ label?: ReactNode</code></pre>
3297
4201
  </div>
3298
4202
  </div>
3299
4203
 
4204
+
3300
4205
  </div>
3301
4206
  </article>
3302
4207
  <article
@@ -3311,16 +4216,35 @@ label?: ReactNode</code></pre>
3311
4216
  <div class="title">
3312
4217
  <h2><span class="status-dot dot-ok"></span> HoverCard.Root</h2>
3313
4218
  <div class="badges">
3314
-
4219
+ <label for="c-10-components-hovercard-props" class="badge ok as-toggle">6 prop types</label>
3315
4220
 
3316
4221
  <label for="c-10-components-hovercard-stories" class="badge ok as-toggle">7 stories</label>
3317
4222
 
4223
+
3318
4224
  </div>
3319
4225
  </div>
3320
4226
  <div class="meta" title="./src/hover-card/hover-card.stories.tsx">components-hovercard · ./src/hover-card/hover-card.stories.tsx</div>
3321
-
3322
- <div class="hint">HoverCard reveals rich, sighted-user preview content anchored to a trigger on pointer hover or keyboard focus. Compose it from `Root` / `Trigger` / `Portal` / `Content`. `Trigger` takes any focusable control through `asChild`; these stories use a `secondary` Button throughout. Radix mirrors open state onto whatever you pass, so the trigger can style itself off `data-state`.</div>
3323
-
4227
+ <div>Root provider for a rich hover preview of an entity</div>
4228
+ <div class="hint">HoverCard reveals rich, sighted-user preview content anchored to a trigger
4229
+ on pointer hover or keyboard focus. Compose it from `Root` / `Trigger` /
4230
+ `Portal` / `Content`.
4231
+
4232
+ `Trigger` takes any focusable control through `asChild`; these stories use a
4233
+ `secondary` Button throughout. Radix mirrors open state onto whatever you
4234
+ pass, so the trigger can style itself off `data-state`.</div>
4235
+ <div class="kv"><span class="chip">summary: Root provider for a rich hover preview of an entity</span><span class="chip">see: {@link https://www.radix-ui.com/primitives/docs/components/hover-card Radix UI HoverCard}</span><span class="chip">example: ```tsx
4236
+ import { HoverCard } from &#39;@agentero/design-system/hover-card&#39;;
4237
+
4238
+ &lt;HoverCard.Root&gt;
4239
+ &lt;HoverCard.Trigger&gt;@rafa&lt;/HoverCard.Trigger&gt;
4240
+ &lt;HoverCard.Portal&gt;
4241
+ &lt;HoverCard.Content&gt;
4242
+ &lt;ProfileCard /&gt;
4243
+ &lt;HoverCard.Arrow /&gt;
4244
+ &lt;/HoverCard.Content&gt;
4245
+ &lt;/HoverCard.Portal&gt;
4246
+ &lt;/HoverCard.Root&gt;
4247
+ ```</span></div>
3324
4248
  </div>
3325
4249
 
3326
4250
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -3329,11 +4253,33 @@ label?: ReactNode</code></pre>
3329
4253
  <input id="c-10-components-hovercard-stories" class="tg tg-stories" type="checkbox" hidden />
3330
4254
 
3331
4255
 
4256
+ <input id="c-10-components-hovercard-props" class="tg tg-props" type="checkbox" hidden />
3332
4257
 
3333
4258
  <div class="panels">
3334
4259
 
3335
4260
 
3336
4261
 
4262
+ <div class="panel panel-props">
4263
+ <div class="note ok">
4264
+ <div class="row">
4265
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
4266
+ <span class="badge ok">6 prop types</span>
4267
+ </div>
4268
+ <pre><code>Component: src/hover-card/index.ts::HoverCard</code></pre>
4269
+ <pre><code>Props:</code></pre>
4270
+ <pre><code>children?: ReactNode
4271
+
4272
+ closeDelay?: number
4273
+
4274
+ defaultOpen?: boolean
4275
+
4276
+ onOpenChange?: (open: boolean) =&gt; void
4277
+
4278
+ open?: boolean
4279
+
4280
+ openDelay?: number</code></pre>
4281
+ </div>
4282
+ </div>
3337
4283
 
3338
4284
  <div class="panel panel-stories">
3339
4285
 
@@ -3371,7 +4317,11 @@ label?: ReactNode</code></pre>
3371
4317
  <span class="badge ok">story ok</span>
3372
4318
  </div>
3373
4319
 
3374
- <div class="hint">Brushing the trigger and leaving without ever reaching the card is the most common way a hover card gets dismissed, so the exit reverses the entrance from wherever it got to. Driving it with keyframes instead would restart the exit at full opacity and scale, popping the half-faded card to fully visible on its way out.</div>
4320
+ <div class="hint">Brushing the trigger and leaving without ever reaching the card is the most
4321
+ common way a hover card gets dismissed, so the exit reverses the entrance
4322
+ from wherever it got to. Driving it with keyframes instead would restart the
4323
+ exit at full opacity and scale, popping the half-faded card to fully visible
4324
+ on its way out.</div>
3375
4325
  <pre><code>const AbandonedHover = () =&gt; &lt;HoverCard.Root openDelay={0} closeDelay={0}&gt;
3376
4326
  &lt;HoverCard.Trigger asChild&gt;
3377
4327
  &lt;Button variant=&quot;secondary&quot;&gt;Hover me&lt;/Button&gt;
@@ -3389,7 +4339,10 @@ label?: ReactNode</code></pre>
3389
4339
  <span class="badge ok">story ok</span>
3390
4340
  </div>
3391
4341
 
3392
- <div class="hint">Opens on focus as a supplementary affordance. Note this is not the same as being keyboard-accessible: focus does not move into the card and it closes on blur, so any interactive content inside stays unreachable by keyboard — never put essential actions there.</div>
4342
+ <div class="hint">Opens on focus as a supplementary affordance. Note this is not the same as
4343
+ being keyboard-accessible: focus does not move into the card and it closes
4344
+ on blur, so any interactive content inside stays unreachable by keyboard —
4345
+ never put essential actions there.</div>
3393
4346
  <pre><code>const OpensOnFocus = () =&gt; &lt;HoverCard.Root openDelay={0} closeDelay={0}&gt;
3394
4347
  &lt;HoverCard.Trigger asChild&gt;
3395
4348
  &lt;Button variant=&quot;secondary&quot;&gt;Focus me&lt;/Button&gt;
@@ -3435,7 +4388,10 @@ label?: ReactNode</code></pre>
3435
4388
  <span class="badge ok">story ok</span>
3436
4389
  </div>
3437
4390
 
3438
- <div class="hint">The whole point of a HoverCard over a Tooltip: freely laid-out content that may include its own links and actions. Keep those actions at `secondary` or below — a primary CTA inside a card the keyboard can&#39;t reach reads as the main path to something it isn&#39;t. The trigger still has to stand on its own.</div>
4391
+ <div class="hint">The whole point of a HoverCard over a Tooltip: freely laid-out content that
4392
+ may include its own links and actions. Keep those actions at `secondary` or
4393
+ below — a primary CTA inside a card the keyboard can&#39;t reach reads as the
4394
+ main path to something it isn&#39;t. The trigger still has to stand on its own.</div>
3439
4395
  <pre><code>const RichContent = () =&gt; &lt;HoverCard.Root openDelay={0} closeDelay={0}&gt;
3440
4396
  &lt;HoverCard.Trigger asChild&gt;
3441
4397
  &lt;Button variant=&quot;secondary&quot;&gt;Hover me&lt;/Button&gt;
@@ -3476,7 +4432,9 @@ label?: ReactNode</code></pre>
3476
4432
  <span class="badge ok">story ok</span>
3477
4433
  </div>
3478
4434
 
3479
- <div class="hint">An optional `Arrow` points back at the trigger; render it inside `Content`. It carries the card&#39;s border down both slopes and leaves its base open, so the card and the point read as one shape on any background.</div>
4435
+ <div class="hint">An optional `Arrow` points back at the trigger; render it inside `Content`.
4436
+ It carries the card&#39;s border down both slopes and leaves its base open, so
4437
+ the card and the point read as one shape on any background.</div>
3480
4438
  <pre><code>const WithArrow = () =&gt; &lt;HoverCard.Root openDelay={0} closeDelay={0}&gt;
3481
4439
  &lt;HoverCard.Trigger asChild&gt;
3482
4440
  &lt;Button variant=&quot;secondary&quot;&gt;Hover me&lt;/Button&gt;
@@ -3495,7 +4453,9 @@ label?: ReactNode</code></pre>
3495
4453
  <span class="badge ok">story ok</span>
3496
4454
  </div>
3497
4455
 
3498
- <div class="hint">`openDelay` / `closeDelay` tune the hover latency. Default is a deliberate `700ms` open so cards don&#39;t flash on incidental passes; drop it to `0` for trigger-dense UIs where an instant preview reads as more responsive.</div>
4456
+ <div class="hint">`openDelay` / `closeDelay` tune the hover latency. Default is a deliberate
4457
+ `700ms` open so cards don&#39;t flash on incidental passes; drop it to `0` for
4458
+ trigger-dense UIs where an instant preview reads as more responsive.</div>
3499
4459
  <pre><code>const Delays = () =&gt; (
3500
4460
  // Grid rather than flex so both triggers take the wider label&#39;s width —
3501
4461
  // a size difference would read as part of what the delay changes.
@@ -3525,6 +4485,7 @@ label?: ReactNode</code></pre>
3525
4485
  </div>
3526
4486
  </div>
3527
4487
 
4488
+
3528
4489
  </div>
3529
4490
  </article>
3530
4491
  <article
@@ -3543,12 +4504,19 @@ label?: ReactNode</code></pre>
3543
4504
 
3544
4505
  <label for="c-11-components-label-stories" class="badge ok as-toggle">4 stories</label>
3545
4506
 
4507
+
3546
4508
  </div>
3547
4509
  </div>
3548
4510
  <div class="meta" title="./src/label/label.stories.tsx">components-label · ./src/label/label.stories.tsx</div>
3549
-
3550
- <div class="hint">Label is the accessible caption for a form control, built on Radix&#39;s Label primitive: it associates with the control through `htmlFor` and does not select text on double-click. `optional` and `required` are display-only affordances — the control itself still has to carry `required` / `aria-required`.</div>
3551
-
4511
+ <div>Accessible caption for a form control</div>
4512
+ <div class="hint">Label is the accessible caption for a form control, built on Radix&#39;s Label
4513
+ primitive: it associates with the control through `htmlFor` and does not select
4514
+ text on double-click.
4515
+
4516
+ `optional` and `required` are display-only affordances — the control itself
4517
+ still has to carry `required` / `aria-required`.</div>
4518
+ <div class="kv"><span class="chip">summary: Accessible caption for a form control</span><span class="chip">example: &lt;Label htmlFor=&quot;phone&quot; optional&gt;Phone number&lt;/Label&gt;
4519
+ &lt;Input id=&quot;phone&quot; type=&quot;tel&quot; /&gt;</span></div>
3552
4520
  </div>
3553
4521
 
3554
4522
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -3556,6 +4524,7 @@ label?: ReactNode</code></pre>
3556
4524
 
3557
4525
  <input id="c-11-components-label-stories" class="tg tg-stories" type="checkbox" hidden />
3558
4526
 
4527
+
3559
4528
  <input id="c-11-components-label-props" class="tg tg-props" type="checkbox" hidden />
3560
4529
 
3561
4530
  <div class="panels">
@@ -3565,7 +4534,7 @@ label?: ReactNode</code></pre>
3565
4534
  <div class="panel panel-props">
3566
4535
  <div class="note ok">
3567
4536
  <div class="row">
3568
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
4537
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
3569
4538
  <span class="badge ok">3 prop types</span>
3570
4539
  </div>
3571
4540
  <pre><code>Component: src/label/label.tsx::Label</code></pre>
@@ -3623,7 +4592,8 @@ required?: boolean = false</code></pre>
3623
4592
  <span class="badge ok">story ok</span>
3624
4593
  </div>
3625
4594
  <div>Required field with a decorative asterisk</div>
3626
- <div class="hint">Appends an asterisk. It is `aria-hidden`, so the control still needs its own `required` attribute for assistive technology.</div>
4595
+ <div class="hint">Appends an asterisk. It is `aria-hidden`, so the control still needs its own
4596
+ `required` attribute for assistive technology.</div>
3627
4597
  <pre><code>const Required = () =&gt; &lt;Label required&gt;Full name&lt;/Label&gt;;</code></pre>
3628
4598
  </div>
3629
4599
  <div class="note ok">
@@ -3632,11 +4602,13 @@ required?: boolean = false</code></pre>
3632
4602
  <span class="badge ok">story ok</span>
3633
4603
  </div>
3634
4604
  <div>required takes precedence over optional</div>
3635
- <div class="hint">Contradictory props do not throw — `required` wins and the optional suffix is dropped, so a mistake never takes the page down.</div>
4605
+ <div class="hint">Contradictory props do not throw — `required` wins and the optional suffix is
4606
+ dropped, so a mistake never takes the page down.</div>
3636
4607
  <pre><code>const RequiredWinsOverOptional = () =&gt; &lt;Label optional required&gt;Agency name&lt;/Label&gt;;</code></pre>
3637
4608
  </div>
3638
4609
  </div>
3639
4610
 
4611
+
3640
4612
  </div>
3641
4613
  </article>
3642
4614
  <article
@@ -3655,12 +4627,16 @@ required?: boolean = false</code></pre>
3655
4627
 
3656
4628
  <label for="c-12-components-loading-stories" class="badge ok as-toggle">7 stories</label>
3657
4629
 
4630
+
3658
4631
  </div>
3659
4632
  </div>
3660
4633
  <div class="meta" title="./src/loading/loading.stories.tsx">components-loading · ./src/loading/loading.stories.tsx</div>
3661
-
3662
- <div class="hint">Loading displays a circular spinner that indicates an in-progress operation. Use for inline fetch, form submission, or asynchronous task indicators. The spinner inherits its color from the parent `color` and scales with the parent font size via `em`-based size variants (`sm`, `md`, `lg`).</div>
3663
-
4634
+ <div>Circular spinner for in-progress and loading states</div>
4635
+ <div class="hint">Loading displays a circular spinner that indicates an in-progress operation.
4636
+ Use for inline fetch, form submission, or asynchronous task indicators.
4637
+ The spinner inherits its color from the parent `color` and scales with the
4638
+ parent font size via `em`-based size variants (`sm`, `md`, `lg`).</div>
4639
+ <div class="kv"><span class="chip">summary: Circular spinner for in-progress and loading states</span><span class="chip">example: &lt;Loading /&gt;</span><span class="chip">example: &lt;Loading size=&quot;lg&quot; className=&quot;text-text-default-brand-primary&quot; /&gt;</span></div>
3664
4640
  </div>
3665
4641
 
3666
4642
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -3668,6 +4644,7 @@ required?: boolean = false</code></pre>
3668
4644
 
3669
4645
  <input id="c-12-components-loading-stories" class="tg tg-stories" type="checkbox" hidden />
3670
4646
 
4647
+
3671
4648
  <input id="c-12-components-loading-props" class="tg tg-props" type="checkbox" hidden />
3672
4649
 
3673
4650
  <div class="panels">
@@ -3677,7 +4654,7 @@ required?: boolean = false</code></pre>
3677
4654
  <div class="panel panel-props">
3678
4655
  <div class="note ok">
3679
4656
  <div class="row">
3680
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
4657
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
3681
4658
  <span class="badge ok">1 prop type</span>
3682
4659
  </div>
3683
4660
  <pre><code>Component: src/loading/loading.tsx::Loading</code></pre>
@@ -3711,7 +4688,9 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3711
4688
  <span class="badge ok">story ok</span>
3712
4689
  </div>
3713
4690
  <div>Default spinner at the `sm` size</div>
3714
- <div class="hint">The default spinner at `size=&quot;sm&quot;` (1em diameter), inheriting the current text color. Matches the out-of-the-box behavior when Loading is dropped into any layout.</div>
4691
+ <div class="hint">The default spinner at `size=&quot;sm&quot;` (1em diameter), inheriting the current
4692
+ text color. Matches the out-of-the-box behavior when Loading is dropped
4693
+ into any layout.</div>
3715
4694
  <pre><code>const Default = () =&gt; &lt;Loading size=&quot;sm&quot; /&gt;;</code></pre>
3716
4695
  </div>
3717
4696
  <div class="note ok">
@@ -3720,7 +4699,8 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3720
4699
  <span class="badge ok">story ok</span>
3721
4700
  </div>
3722
4701
  <div>Small 1em spinner for inline indicators</div>
3723
- <div class="hint">Small spinner (1em diameter) — the default. Ideal for inline indicators, buttons, and compact layouts where the spinner needs to sit next to text.</div>
4702
+ <div class="hint">Small spinner (1em diameter) — the default. Ideal for inline indicators,
4703
+ buttons, and compact layouts where the spinner needs to sit next to text.</div>
3724
4704
  <pre><code>const SizeSm = () =&gt; &lt;Loading size=&quot;sm&quot; /&gt;;</code></pre>
3725
4705
  </div>
3726
4706
  <div class="note ok">
@@ -3729,7 +4709,8 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3729
4709
  <span class="badge ok">story ok</span>
3730
4710
  </div>
3731
4711
  <div>Medium 1.5em spinner for cards and panels</div>
3732
- <div class="hint">Medium spinner (1.5em diameter). Use for cards, panels, and standalone loading states where the spinner is the primary visual signal.</div>
4712
+ <div class="hint">Medium spinner (1.5em diameter). Use for cards, panels, and standalone
4713
+ loading states where the spinner is the primary visual signal.</div>
3733
4714
  <pre><code>const SizeMd = () =&gt; &lt;Loading size=&quot;md&quot; /&gt;;</code></pre>
3734
4715
  </div>
3735
4716
  <div class="note ok">
@@ -3738,7 +4719,8 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3738
4719
  <span class="badge ok">story ok</span>
3739
4720
  </div>
3740
4721
  <div>Large 2em spinner for page or section loading</div>
3741
- <div class="hint">Large spinner (2em diameter). Use for page-level or section-level loading where the spinner needs more visual weight.</div>
4722
+ <div class="hint">Large spinner (2em diameter). Use for page-level or section-level loading
4723
+ where the spinner needs more visual weight.</div>
3742
4724
  <pre><code>const SizeLg = () =&gt; &lt;Loading size=&quot;lg&quot; /&gt;;</code></pre>
3743
4725
  </div>
3744
4726
  <div class="note ok">
@@ -3747,7 +4729,8 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3747
4729
  <span class="badge ok">story ok</span>
3748
4730
  </div>
3749
4731
  <div>Visual comparison of all three spinner sizes</div>
3750
- <div class="hint">All three sizes rendered side by side for visual comparison of the `em`-based scaling. Each spinner inherits the same parent text color.</div>
4732
+ <div class="hint">All three sizes rendered side by side for visual comparison of the
4733
+ `em`-based scaling. Each spinner inherits the same parent text color.</div>
3751
4734
  <pre><code>const Sizes = () =&gt; (
3752
4735
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;2rem&#39; }}&gt;
3753
4736
  {([&#39;sm&#39;, &#39;md&#39;, &#39;lg&#39;] as const).map(size =&gt; (
@@ -3762,7 +4745,9 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3762
4745
  <span class="badge ok">story ok</span>
3763
4746
  </div>
3764
4747
  <div>Spinner color inherits from the parent text color</div>
3765
- <div class="hint">The spinner color tracks the parent `color` (text color) via `border-current`. Wrap Loading in any element with a text color utility — or set `color` on Loading itself — and the spinner adopts that color without extra props.</div>
4748
+ <div class="hint">The spinner color tracks the parent `color` (text color) via `border-current`.
4749
+ Wrap Loading in any element with a text color utility — or set `color` on
4750
+ Loading itself — and the spinner adopts that color without extra props.</div>
3766
4751
  <pre><code>const InheritsColor = () =&gt; (
3767
4752
  &lt;div style={{ display: &#39;flex&#39;, alignItems: &#39;center&#39;, gap: &#39;2rem&#39; }}&gt;
3768
4753
  &lt;div className=&quot;text-text-default-base-primary&quot;&gt;
@@ -3783,7 +4768,9 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3783
4768
  <span class="badge ok">story ok</span>
3784
4769
  </div>
3785
4770
  <div>Spinner on a dark-background surface</div>
3786
- <div class="hint">Spinner on a dark surface to verify `border-current` contrast. The parent sets a light text color, which the spinner inherits so it remains visible against the dark background.</div>
4771
+ <div class="hint">Spinner on a dark surface to verify `border-current` contrast. The parent
4772
+ sets a light text color, which the spinner inherits so it remains visible
4773
+ against the dark background.</div>
3787
4774
  <pre><code>const OnDarkSurface = () =&gt; (
3788
4775
  &lt;div className=&quot;flex items-center gap-8 rounded-lg bg-bg-button-primary-enable p-8 text-text-default-base-inverse-primary&quot;&gt;
3789
4776
  &lt;Loading size=&quot;sm&quot; /&gt;
@@ -3794,6 +4781,7 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3794
4781
  </div>
3795
4782
  </div>
3796
4783
 
4784
+
3797
4785
  </div>
3798
4786
  </article>
3799
4787
  <article
@@ -3808,16 +4796,49 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3808
4796
  <div class="title">
3809
4797
  <h2><span class="status-dot dot-ok"></span> Modal.Root</h2>
3810
4798
  <div class="badges">
3811
-
4799
+ <label for="c-13-components-modal-props" class="badge ok as-toggle">5 prop types</label>
3812
4800
 
3813
4801
  <label for="c-13-components-modal-stories" class="badge ok as-toggle">6 stories</label>
3814
4802
 
4803
+
3815
4804
  </div>
3816
4805
  </div>
3817
4806
  <div class="meta" title="./src/modal/modal.stories.tsx">components-modal · ./src/modal/modal.stories.tsx</div>
3818
-
3819
- <div class="hint">Modal is a compound dialog built on Radix UI: `Root` owns the open state, `Content` is the centered surface (`size` md/lg), and `Title`/`Body`/`Footer` structure it. Close it with `Escape`, the overlay, the X button, or a `Modal.Close asChild` around your own button. `Content` also takes `variant=&quot;alert&quot;` for the modal the user has to answer: it drops all three implicit ways out and is announced as an `alertdialog`.</div>
3820
-
4807
+ <div>Root provider for a Modal&#39;s open state</div>
4808
+ <div class="hint">Modal is a compound dialog built on Radix UI: `Root` owns the open state,
4809
+ `Content` is the centered surface (`size` md/lg), and `Title`/`Body`/`Footer`
4810
+ structure it. Close it with `Escape`, the overlay, the X button, or a
4811
+ `Modal.Close asChild` around your own button.
4812
+
4813
+ `Content` also takes `variant=&quot;alert&quot;` for the modal the user has to answer:
4814
+ it drops all three implicit ways out and is announced as an `alertdialog`.</div>
4815
+ <div class="kv"><span class="chip">summary: Root provider for a Modal&#39;s open state</span><span class="chip">example: ```tsx
4816
+ import { Modal } from &#39;@agentero/design-system/modal&#39;;
4817
+
4818
+ &lt;Modal.Root open={isOpen} onOpenChange={setIsOpen}&gt;
4819
+ &lt;Modal.Content size=&quot;md&quot;&gt;
4820
+ &lt;Modal.Title&gt;Delete carrier&lt;/Modal.Title&gt;
4821
+ &lt;Modal.Description&gt;This action cannot be undone.&lt;/Modal.Description&gt;
4822
+ &lt;Modal.Footer&gt;
4823
+ &lt;Modal.Close asChild&gt;
4824
+ &lt;Button variant=&quot;ghost&quot;&gt;Cancel&lt;/Button&gt;
4825
+ &lt;/Modal.Close&gt;
4826
+ &lt;Button onClick={handleDelete}&gt;Delete&lt;/Button&gt;
4827
+ &lt;/Modal.Footer&gt;
4828
+ &lt;/Modal.Content&gt;
4829
+ &lt;/Modal.Root&gt;
4830
+ ```</span><span class="chip">example: ```tsx
4831
+ // Alert: no Escape, no overlay click, no X — the user must answer.
4832
+ &lt;Modal.Root open={isOpen}&gt;
4833
+ &lt;Modal.Content variant=&quot;alert&quot;&gt;
4834
+ &lt;Modal.Title&gt;Complete your Docusign integration&lt;/Modal.Title&gt;
4835
+ &lt;Modal.Body&gt;Authorize access to finish connecting your account.&lt;/Modal.Body&gt;
4836
+ &lt;Modal.Footer&gt;
4837
+ &lt;Button onClick={handleAuthorize}&gt;Authorize&lt;/Button&gt;
4838
+ &lt;/Modal.Footer&gt;
4839
+ &lt;/Modal.Content&gt;
4840
+ &lt;/Modal.Root&gt;
4841
+ ```</span></div>
3821
4842
  </div>
3822
4843
 
3823
4844
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -3826,11 +4847,31 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3826
4847
  <input id="c-13-components-modal-stories" class="tg tg-stories" type="checkbox" hidden />
3827
4848
 
3828
4849
 
4850
+ <input id="c-13-components-modal-props" class="tg tg-props" type="checkbox" hidden />
3829
4851
 
3830
4852
  <div class="panels">
3831
4853
 
3832
4854
 
3833
4855
 
4856
+ <div class="panel panel-props">
4857
+ <div class="note ok">
4858
+ <div class="row">
4859
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
4860
+ <span class="badge ok">5 prop types</span>
4861
+ </div>
4862
+ <pre><code>Component: src/modal/index.ts::Modal</code></pre>
4863
+ <pre><code>Props:</code></pre>
4864
+ <pre><code>children?: ReactNode
4865
+
4866
+ defaultOpen?: boolean
4867
+
4868
+ modal?: boolean
4869
+
4870
+ onOpenChange?: (open: boolean) =&gt; void
4871
+
4872
+ open?: boolean</code></pre>
4873
+ </div>
4874
+ </div>
3834
4875
 
3835
4876
  <div class="panel panel-stories">
3836
4877
 
@@ -3963,7 +5004,9 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3963
5004
  <span class="badge ok">story ok</span>
3964
5005
  </div>
3965
5006
 
3966
- <div class="hint">`variant=&quot;alert&quot;` for a decision the user cannot skip: `Escape` and overlay clicks are ignored, `Modal.Title` renders no X button, and the surface is announced as an `alertdialog`. Only the footer actions close it.</div>
5007
+ <div class="hint">`variant=&quot;alert&quot;` for a decision the user cannot skip: `Escape` and overlay
5008
+ clicks are ignored, `Modal.Title` renders no X button, and the surface is
5009
+ announced as an `alertdialog`. Only the footer actions close it.</div>
3967
5010
  <pre><code>const Alert = () =&gt; (
3968
5011
  &lt;Modal.Root&gt;
3969
5012
  &lt;Modal.Trigger asChild&gt;
@@ -3986,6 +5029,7 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
3986
5029
  </div>
3987
5030
  </div>
3988
5031
 
5032
+
3989
5033
  </div>
3990
5034
  </article>
3991
5035
  <article
@@ -4004,12 +5048,29 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
4004
5048
 
4005
5049
  <label for="c-14-components-pagination-stories" class="badge ok as-toggle">7 stories</label>
4006
5050
 
5051
+
4007
5052
  </div>
4008
5053
  </div>
4009
5054
  <div class="meta" title="./src/pagination/pagination.stories.tsx">components-pagination · ./src/pagination/pagination.stories.tsx</div>
4010
-
4011
- <div class="hint">Pagination is a 1-indexed paged navigation control with previous/next icon buttons, numeric page buttons, and a leading &quot;X - Y of Z&quot; entries summary. The page list collapses long ranges with `…` ellipses so the control stays compact regardless of total page count. Use it for lists, tables, or grids that are split across pages.</div>
4012
-
5055
+ <div>1-indexed paged navigation control with prev/next, numeric pages, and entries summary</div>
5056
+ <div class="hint">Pagination is a 1-indexed paged navigation control with previous/next icon
5057
+ buttons, numeric page buttons, and a leading &quot;X - Y of Z&quot; entries summary.
5058
+ The page list collapses long ranges with `…` ellipses so the control stays
5059
+ compact regardless of total page count. Use it for lists, tables, or grids
5060
+ that are split across pages.</div>
5061
+ <div class="kv"><span class="chip">summary: 1-indexed paged navigation control with prev/next, numeric pages, and entries summary</span><span class="chip">example: ```tsx
5062
+ import { useState } from &#39;react&#39;;
5063
+ import { Pagination } from &#39;@agentero/design-system/pagination&#39;;
5064
+
5065
+ const [page, setPage] = useState(1);
5066
+
5067
+ &lt;Pagination
5068
+ currentPage={page}
5069
+ pageSize={10}
5070
+ totalCount={1000}
5071
+ onPageChange={setPage}
5072
+ /&gt;
5073
+ ```</span></div>
4013
5074
  </div>
4014
5075
 
4015
5076
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4017,6 +5078,7 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
4017
5078
 
4018
5079
  <input id="c-14-components-pagination-stories" class="tg tg-stories" type="checkbox" hidden />
4019
5080
 
5081
+
4020
5082
  <input id="c-14-components-pagination-props" class="tg tg-props" type="checkbox" hidden />
4021
5083
 
4022
5084
  <div class="panels">
@@ -4026,7 +5088,7 @@ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;</code></pre>
4026
5088
  <div class="panel panel-props">
4027
5089
  <div class="note ok">
4028
5090
  <div class="row">
4029
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
5091
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
4030
5092
  <span class="badge ok">5 prop types</span>
4031
5093
  </div>
4032
5094
  <pre><code>Component: src/pagination/pagination.tsx::Pagination</code></pre>
@@ -4061,7 +5123,9 @@ totalCount: number</code></pre>
4061
5123
  <span class="badge ok">story ok</span>
4062
5124
  </div>
4063
5125
  <div>Default args playground for Pagination</div>
4064
- <div class="hint">Default args playground. The first page of a 1,000-item list paged 10 at a time — renders pages 1–5, an ellipsis, and the last page (100), with the previous-page button disabled because we&#39;re on page 1.</div>
5126
+ <div class="hint">Default args playground. The first page of a 1,000-item list paged 10 at a
5127
+ time — renders pages 1–5, an ellipsis, and the last page (100), with the
5128
+ previous-page button disabled because we&#39;re on page 1.</div>
4065
5129
  <pre><code>const Default = () =&gt; &lt;Pagination currentPage={1} totalCount={1000} pageSize={10} onPageChange={fn()} /&gt;;</code></pre>
4066
5130
  </div>
4067
5131
  <div class="note ok">
@@ -4070,7 +5134,9 @@ totalCount: number</code></pre>
4070
5134
  <span class="badge ok">story ok</span>
4071
5135
  </div>
4072
5136
  <div>Short page list with no ellipsis collapse</div>
4073
- <div class="hint">Short list whose total pages fit in the visible window — no ellipsis is rendered. Exercises the `totalPageNumbers &gt;= totalPageCount` branch in `getPages`.</div>
5137
+ <div class="hint">Short list whose total pages fit in the visible window — no ellipsis is
5138
+ rendered. Exercises the `totalPageNumbers &gt;= totalPageCount` branch in
5139
+ `getPages`.</div>
4074
5140
  <pre><code>const FewPages = () =&gt; &lt;Pagination
4075
5141
  currentPage={2}
4076
5142
  totalCount={30}
@@ -4083,7 +5149,8 @@ totalCount: number</code></pre>
4083
5149
  <span class="badge ok">story ok</span>
4084
5150
  </div>
4085
5151
  <div>Right-side ellipsis only (current page near start)</div>
4086
- <div class="hint">Current page sits near the start of the range — left ellipsis is hidden, right ellipsis is shown, and the last page button anchors the right edge.</div>
5152
+ <div class="hint">Current page sits near the start of the range — left ellipsis is hidden,
5153
+ right ellipsis is shown, and the last page button anchors the right edge.</div>
4087
5154
  <pre><code>const DotsRight = () =&gt; &lt;Pagination
4088
5155
  currentPage={2}
4089
5156
  totalCount={1000}
@@ -4096,7 +5163,8 @@ totalCount: number</code></pre>
4096
5163
  <span class="badge ok">story ok</span>
4097
5164
  </div>
4098
5165
  <div>Left-side ellipsis only (current page near end)</div>
4099
- <div class="hint">Current page sits near the end of the range — left ellipsis is shown, right ellipsis is hidden, and the first page button anchors the left edge.</div>
5166
+ <div class="hint">Current page sits near the end of the range — left ellipsis is shown, right
5167
+ ellipsis is hidden, and the first page button anchors the left edge.</div>
4100
5168
  <pre><code>const DotsLeft = () =&gt; &lt;Pagination
4101
5169
  currentPage={99}
4102
5170
  totalCount={1000}
@@ -4109,7 +5177,8 @@ totalCount: number</code></pre>
4109
5177
  <span class="badge ok">story ok</span>
4110
5178
  </div>
4111
5179
  <div>Both ellipses visible (current page in middle)</div>
4112
- <div class="hint">Current page sits in the middle of the range — both ellipses are visible, with the first and last page buttons anchoring each edge.</div>
5180
+ <div class="hint">Current page sits in the middle of the range — both ellipses are visible,
5181
+ with the first and last page buttons anchoring each edge.</div>
4113
5182
  <pre><code>const DotsBoth = () =&gt; &lt;Pagination
4114
5183
  currentPage={50}
4115
5184
  totalCount={1000}
@@ -4122,7 +5191,8 @@ totalCount: number</code></pre>
4122
5191
  <span class="badge ok">story ok</span>
4123
5192
  </div>
4124
5193
  <div>Last page selected with disabled next button</div>
4125
- <div class="hint">Last page selected — the next-page button is disabled and the active page indicator sits on the trailing number.</div>
5194
+ <div class="hint">Last page selected — the next-page button is disabled and the active page
5195
+ indicator sits on the trailing number.</div>
4126
5196
  <pre><code>const LastPage = () =&gt; &lt;Pagination currentPage={100} totalCount={1000} pageSize={10} onPageChange={fn()} /&gt;;</code></pre>
4127
5197
  </div>
4128
5198
  <div class="note ok">
@@ -4131,7 +5201,9 @@ totalCount: number</code></pre>
4131
5201
  <span class="badge ok">story ok</span>
4132
5202
  </div>
4133
5203
  <div>Interactive controlled example backed by `useState`</div>
4134
- <div class="hint">Interactive controlled example. Local `useState` owns the page; clicking a page, previous, or next button updates it so the active page indicator and entries summary follow along.</div>
5204
+ <div class="hint">Interactive controlled example. Local `useState` owns the page; clicking a
5205
+ page, previous, or next button updates it so the active page indicator and
5206
+ entries summary follow along.</div>
4135
5207
  <pre><code>const Controlled = ({ totalCount, pageSize }) =&gt; {
4136
5208
  const [page, setPage] = useState(1);
4137
5209
 
@@ -4147,6 +5219,7 @@ totalCount: number</code></pre>
4147
5219
  </div>
4148
5220
  </div>
4149
5221
 
5222
+
4150
5223
  </div>
4151
5224
  </article>
4152
5225
  <article
@@ -4161,16 +5234,32 @@ totalCount: number</code></pre>
4161
5234
  <div class="title">
4162
5235
  <h2><span class="status-dot dot-ok"></span> Popover.Root</h2>
4163
5236
  <div class="badges">
4164
-
5237
+ <label for="c-15-components-popover-props" class="badge ok as-toggle">5 prop types</label>
4165
5238
 
4166
5239
  <label for="c-15-components-popover-stories" class="badge ok as-toggle">4 stories</label>
4167
5240
 
5241
+
4168
5242
  </div>
4169
5243
  </div>
4170
5244
  <div class="meta" title="./src/popover/popover.stories.tsx">components-popover · ./src/popover/popover.stories.tsx</div>
4171
-
4172
- <div class="hint">Popover is a non-modal floating surface anchored to a trigger, used for rich interactive overlays such as forms, filters, and pickers. Compose it from `Root` / `Trigger` / `Content`, plus optional `Anchor` and `Close`. Built on Radix UI&#39;s Popover primitive, so focus management, dismissal, and collision detection come for free.</div>
4173
-
5245
+ <div>Root provider for a floating interactive overlay</div>
5246
+ <div class="hint">Popover is a non-modal floating surface anchored to a trigger, used for
5247
+ rich interactive overlays such as forms, filters, and pickers. Compose it
5248
+ from `Root` / `Trigger` / `Content`, plus optional `Anchor` and `Close`.
5249
+ Built on Radix UI&#39;s Popover primitive, so focus management, dismissal, and
5250
+ collision detection come for free.</div>
5251
+ <div class="kv"><span class="chip">summary: Root provider for a floating interactive overlay</span><span class="chip">see: {@link https://www.radix-ui.com/primitives/docs/components/popover Radix UI Popover}</span><span class="chip">example: ```tsx
5252
+ import { Popover } from &#39;@agentero/design-system/popover&#39;;
5253
+
5254
+ &lt;Popover.Root&gt;
5255
+ &lt;Popover.Trigger asChild&gt;
5256
+ &lt;Button&gt;Filters&lt;/Button&gt;
5257
+ &lt;/Popover.Trigger&gt;
5258
+ &lt;Popover.Content align=&quot;start&quot;&gt;
5259
+ &lt;FiltersForm /&gt;
5260
+ &lt;/Popover.Content&gt;
5261
+ &lt;/Popover.Root&gt;
5262
+ ```</span></div>
4174
5263
  </div>
4175
5264
 
4176
5265
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4179,11 +5268,31 @@ totalCount: number</code></pre>
4179
5268
  <input id="c-15-components-popover-stories" class="tg tg-stories" type="checkbox" hidden />
4180
5269
 
4181
5270
 
5271
+ <input id="c-15-components-popover-props" class="tg tg-props" type="checkbox" hidden />
4182
5272
 
4183
5273
  <div class="panels">
4184
5274
 
4185
5275
 
4186
5276
 
5277
+ <div class="panel panel-props">
5278
+ <div class="note ok">
5279
+ <div class="row">
5280
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
5281
+ <span class="badge ok">5 prop types</span>
5282
+ </div>
5283
+ <pre><code>Component: src/popover/index.ts::Popover</code></pre>
5284
+ <pre><code>Props:</code></pre>
5285
+ <pre><code>children?: ReactNode
5286
+
5287
+ defaultOpen?: boolean
5288
+
5289
+ modal?: boolean
5290
+
5291
+ onOpenChange?: (open: boolean) =&gt; void
5292
+
5293
+ open?: boolean</code></pre>
5294
+ </div>
5295
+ </div>
4187
5296
 
4188
5297
  <div class="panel panel-stories">
4189
5298
 
@@ -4203,7 +5312,8 @@ totalCount: number</code></pre>
4203
5312
  <span class="badge ok">story ok</span>
4204
5313
  </div>
4205
5314
  <div>Basic click-to-open popover surface</div>
4206
- <div class="hint">A minimal Popover: a trigger button that reveals a short text surface on click and dismisses on outside click or Escape.</div>
5315
+ <div class="hint">A minimal Popover: a trigger button that reveals a short text surface on
5316
+ click and dismisses on outside click or Escape.</div>
4207
5317
  <pre><code>const Default = () =&gt; (
4208
5318
  &lt;Popover.Root&gt;
4209
5319
  &lt;Popover.Trigger asChild&gt;
@@ -4245,7 +5355,8 @@ totalCount: number</code></pre>
4245
5355
  <span class="badge ok">story ok</span>
4246
5356
  </div>
4247
5357
  <div>Popover holding an interactive form with a `Close` action</div>
4248
- <div class="hint">Rich interactive content — the primary reason to reach for a Popover over a Tooltip. A `Close` inside the surface dismisses it after submitting.</div>
5358
+ <div class="hint">Rich interactive content — the primary reason to reach for a Popover over a
5359
+ Tooltip. A `Close` inside the surface dismisses it after submitting.</div>
4249
5360
  <pre><code>const WithForm = () =&gt; (
4250
5361
  &lt;Popover.Root&gt;
4251
5362
  &lt;Popover.Trigger asChild&gt;
@@ -4277,7 +5388,8 @@ totalCount: number</code></pre>
4277
5388
  <span class="badge ok">story ok</span>
4278
5389
  </div>
4279
5390
  <div>Popover positioned against a separate `Anchor` element</div>
4280
- <div class="hint">`Anchor` positions the Content against an element other than the Trigger — useful when the visual anchor differs from the toggle button.</div>
5391
+ <div class="hint">`Anchor` positions the Content against an element other than the Trigger —
5392
+ useful when the visual anchor differs from the toggle button.</div>
4281
5393
  <pre><code>const WithAnchor = () =&gt; (
4282
5394
  &lt;Popover.Root&gt;
4283
5395
  &lt;div className=&quot;flex flex-col items-center gap-4&quot;&gt;
@@ -4296,6 +5408,7 @@ totalCount: number</code></pre>
4296
5408
  </div>
4297
5409
  </div>
4298
5410
 
5411
+
4299
5412
  </div>
4300
5413
  </article>
4301
5414
  <article
@@ -4314,12 +5427,18 @@ totalCount: number</code></pre>
4314
5427
 
4315
5428
  <label for="c-16-components-progress-stories" class="badge ok as-toggle">4 stories</label>
4316
5429
 
5430
+
4317
5431
  </div>
4318
5432
  </div>
4319
5433
  <div class="meta" title="./src/progress/progress.stories.tsx">components-progress · ./src/progress/progress.stories.tsx</div>
4320
-
4321
- <div class="hint">Progress shows how far a bounded task has advanced. Pass `percentage` (0–100) and optionally a `label` rendered above the bar. The fill paints with `currentColor`, so recolor it with a plain text class — e.g. `className=&quot;text-brand-400&quot;`.</div>
4322
-
5434
+ <div>Horizontal progress bar with optional label</div>
5435
+ <div class="hint">Progress shows how far a bounded task has advanced. Pass `percentage`
5436
+ (0–100) and optionally a `label` rendered above the bar. The fill paints
5437
+ with `currentColor`, so recolor it with a plain text class — e.g.
5438
+ `className=&quot;text-brand-400&quot;`.</div>
5439
+ <div class="kv"><span class="chip">summary: Horizontal progress bar with optional label</span><span class="chip">example: ```tsx
5440
+ &lt;Progress percentage={62} label=&quot;Profile completion&quot; className=&quot;text-brand-400&quot; /&gt;
5441
+ ```</span></div>
4323
5442
  </div>
4324
5443
 
4325
5444
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4327,6 +5446,7 @@ totalCount: number</code></pre>
4327
5446
 
4328
5447
  <input id="c-16-components-progress-stories" class="tg tg-stories" type="checkbox" hidden />
4329
5448
 
5449
+
4330
5450
  <input id="c-16-components-progress-props" class="tg tg-props" type="checkbox" hidden />
4331
5451
 
4332
5452
  <div class="panels">
@@ -4336,7 +5456,7 @@ totalCount: number</code></pre>
4336
5456
  <div class="panel panel-props">
4337
5457
  <div class="note ok">
4338
5458
  <div class="row">
4339
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
5459
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
4340
5460
  <span class="badge ok">4 prop types</span>
4341
5461
  </div>
4342
5462
  <pre><code>Component: src/progress/progress.tsx::Progress</code></pre>
@@ -4429,6 +5549,7 @@ percentage: number</code></pre>
4429
5549
  </div>
4430
5550
  </div>
4431
5551
 
5552
+
4432
5553
  </div>
4433
5554
  </article>
4434
5555
  <article
@@ -4447,12 +5568,16 @@ percentage: number</code></pre>
4447
5568
 
4448
5569
  <label for="c-17-components-skeleton-stories" class="badge ok as-toggle">4 stories</label>
4449
5570
 
5571
+
4450
5572
  </div>
4451
5573
  </div>
4452
5574
  <div class="meta" title="./src/skeleton/skeleton.stories.tsx">components-skeleton · ./src/skeleton/skeleton.stories.tsx</div>
4453
-
4454
- <div class="hint">Skeleton renders a pulsing placeholder box while content loads. Size and shape it with Tailwind classes to mirror the content it stands in for.</div>
4455
-
5575
+ <div>Pulsing placeholder box for loading content</div>
5576
+ <div class="hint">Skeleton renders a pulsing placeholder box while content loads. Size and
5577
+ shape it with Tailwind classes to mirror the content it stands in for.</div>
5578
+ <div class="kv"><span class="chip">summary: Pulsing placeholder box for loading content</span><span class="chip">example: ```tsx
5579
+ &lt;Skeleton className=&quot;h-4 w-30&quot; /&gt;
5580
+ ```</span></div>
4456
5581
  </div>
4457
5582
 
4458
5583
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4461,6 +5586,7 @@ percentage: number</code></pre>
4461
5586
  <input id="c-17-components-skeleton-stories" class="tg tg-stories" type="checkbox" hidden />
4462
5587
 
4463
5588
 
5589
+
4464
5590
 
4465
5591
  <div class="panels">
4466
5592
 
@@ -4538,6 +5664,7 @@ percentage: number</code></pre>
4538
5664
  </div>
4539
5665
  </div>
4540
5666
 
5667
+
4541
5668
  </div>
4542
5669
  </article>
4543
5670
  <article
@@ -4552,16 +5679,19 @@ percentage: number</code></pre>
4552
5679
  <div class="title">
4553
5680
  <h2><span class="status-dot dot-ok"></span> Switch</h2>
4554
5681
  <div class="badges">
4555
- <label for="c-18-components-switch-props" class="badge ok as-toggle">4 prop types</label>
5682
+ <label for="c-18-components-switch-props" class="badge ok as-toggle">8 prop types</label>
4556
5683
 
4557
5684
  <label for="c-18-components-switch-stories" class="badge ok as-toggle">7 stories</label>
4558
5685
 
5686
+
4559
5687
  </div>
4560
5688
  </div>
4561
5689
  <div class="meta" title="./src/switch/switch.stories.tsx">components-switch · ./src/switch/switch.stories.tsx</div>
4562
-
4563
- <div class="hint">Two-state toggle for a setting that takes effect immediately. Prefer it over a Checkbox for a single boolean that applies instantly, and pair it with a `&lt;label htmlFor&gt;` to give it an accessible name.</div>
4564
-
5690
+ <div>Instant-effect on/off toggle built on Radix Switch</div>
5691
+ <div class="hint">Two-state toggle for a setting that takes effect immediately. Prefer it over
5692
+ a Checkbox for a single boolean that applies instantly, and pair it with a
5693
+ `&lt;label htmlFor&gt;` to give it an accessible name.</div>
5694
+ <div class="kv"><span class="chip">summary: Instant-effect on/off toggle built on Radix Switch</span><span class="chip">example: &lt;Switch checked={enabled} onCheckedChange={setEnabled} /&gt;</span><span class="chip">example: &lt;Switch id=&quot;email-notifications&quot; label=&quot;Email&quot; checked={on} onCheckedChange={setOn} /&gt;</span></div>
4565
5695
  </div>
4566
5696
 
4567
5697
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4569,6 +5699,7 @@ percentage: number</code></pre>
4569
5699
 
4570
5700
  <input id="c-18-components-switch-stories" class="tg tg-stories" type="checkbox" hidden />
4571
5701
 
5702
+
4572
5703
  <input id="c-18-components-switch-props" class="tg tg-props" type="checkbox" hidden />
4573
5704
 
4574
5705
  <div class="panels">
@@ -4578,13 +5709,17 @@ percentage: number</code></pre>
4578
5709
  <div class="panel panel-props">
4579
5710
  <div class="note ok">
4580
5711
  <div class="row">
4581
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
4582
- <span class="badge ok">4 prop types</span>
5712
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
5713
+ <span class="badge ok">8 prop types</span>
4583
5714
  </div>
4584
5715
  <pre><code>Component: src/switch/switch.tsx::Switch</code></pre>
4585
5716
  <pre><code>Props:</code></pre>
4586
5717
  <pre><code>asChild?: boolean
4587
5718
 
5719
+ checked?: boolean
5720
+
5721
+ defaultChecked?: boolean
5722
+
4588
5723
  /**
4589
5724
  * Optional text rendered beside the toggle and associated with it via
4590
5725
  * `htmlFor`. Provide an `id` so the association resolves. Omit it to keep
@@ -4592,6 +5727,10 @@ percentage: number</code></pre>
4592
5727
  */
4593
5728
  label?: string
4594
5729
 
5730
+ onCheckedChange?: (checked: boolean) =&gt; void
5731
+
5732
+ required?: boolean
5733
+
4595
5734
  reverse?: boolean
4596
5735
 
4597
5736
  size?: &quot;sm&quot; | &quot;md&quot;</code></pre>
@@ -4695,7 +5834,8 @@ size?: &quot;sm&quot; | &quot;md&quot;</code></pre>
4695
5834
  <span class="badge ok">story ok</span>
4696
5835
  </div>
4697
5836
 
4698
- <div class="hint">The built-in `label` prop renders an associated text label beside the toggle (wired via `htmlFor`/`id`); `reverse` places the label before the toggle.</div>
5837
+ <div class="hint">The built-in `label` prop renders an associated text label beside the toggle
5838
+ (wired via `htmlFor`/`id`); `reverse` places the label before the toggle.</div>
4699
5839
  <pre><code>const WithLabel = () =&gt; (
4700
5840
  &lt;div className=&quot;flex items-center gap-6&quot;&gt;
4701
5841
  &lt;Switch id=&quot;with-label&quot; label=&quot;Email&quot; defaultChecked /&gt;
@@ -4726,6 +5866,7 @@ size?: &quot;sm&quot; | &quot;md&quot;</code></pre>
4726
5866
  </div>
4727
5867
  </div>
4728
5868
 
5869
+
4729
5870
  </div>
4730
5871
  </article>
4731
5872
  <article
@@ -4740,16 +5881,34 @@ size?: &quot;sm&quot; | &quot;md&quot;</code></pre>
4740
5881
  <div class="title">
4741
5882
  <h2><span class="status-dot dot-ok"></span> Table.Root</h2>
4742
5883
  <div class="badges">
4743
-
5884
+ <label for="c-19-components-table-props" class="badge ok as-toggle">6 prop types</label>
4744
5885
 
4745
5886
  <label for="c-19-components-table-stories" class="badge ok as-toggle">9 stories</label>
4746
5887
 
5888
+
4747
5889
  </div>
4748
5890
  </div>
4749
5891
  <div class="meta" title="./src/data-table/table.stories.tsx">components-table · ./src/data-table/table.stories.tsx</div>
4750
-
4751
- <div class="hint">Low-level presentational table primitive: native `&lt;table&gt;` markup themed for scrolling, sticky rows, cell padding, dividers, hover, and expandable rows. For sorting/toolbar/pagination, prefer `DataTable`.</div>
4752
-
5892
+ <div>Table root that owns the scroll viewport and `&lt;table&gt;` element</div>
5893
+ <div class="hint">Low-level presentational table primitive: native `&lt;table&gt;` markup themed for
5894
+ scrolling, sticky rows, cell padding, dividers, hover, and expandable rows.
5895
+ For sorting/toolbar/pagination, prefer `DataTable`.</div>
5896
+ <div class="kv"><span class="chip">summary: Table root that owns the scroll viewport and `&lt;table&gt;` element</span><span class="chip">example: ```tsx
5897
+ import { Table } from &#39;@agentero/design-system/data-table&#39;;
5898
+
5899
+ &lt;Table.Root size=&quot;md&quot; sticky=&quot;head&quot;&gt;
5900
+ &lt;Table.Head&gt;
5901
+ &lt;Table.Row&gt;
5902
+ &lt;Table.Header&gt;Name&lt;/Table.Header&gt;
5903
+ &lt;/Table.Row&gt;
5904
+ &lt;/Table.Head&gt;
5905
+ &lt;Table.Body&gt;
5906
+ &lt;Table.Row&gt;
5907
+ &lt;Table.Cell&gt;Jane Doe&lt;/Table.Cell&gt;
5908
+ &lt;/Table.Row&gt;
5909
+ &lt;/Table.Body&gt;
5910
+ &lt;/Table.Root&gt;
5911
+ ```</span></div>
4753
5912
  </div>
4754
5913
 
4755
5914
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -4758,11 +5917,33 @@ size?: &quot;sm&quot; | &quot;md&quot;</code></pre>
4758
5917
  <input id="c-19-components-table-stories" class="tg tg-stories" type="checkbox" hidden />
4759
5918
 
4760
5919
 
5920
+ <input id="c-19-components-table-props" class="tg tg-props" type="checkbox" hidden />
4761
5921
 
4762
5922
  <div class="panels">
4763
5923
 
4764
5924
 
4765
5925
 
5926
+ <div class="panel panel-props">
5927
+ <div class="note ok">
5928
+ <div class="row">
5929
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
5930
+ <span class="badge ok">6 prop types</span>
5931
+ </div>
5932
+ <pre><code>Component: src/data-table/index.ts::Table</code></pre>
5933
+ <pre><code>Props:</code></pre>
5934
+ <pre><code>children?: ReactNode
5935
+
5936
+ embed?: boolean
5937
+
5938
+ enclosed?: boolean
5939
+
5940
+ ref?: Ref&lt;HTMLDivElement&gt; | undefined
5941
+
5942
+ size?: &quot;sm&quot; | &quot;md&quot; | &quot;lg&quot;
5943
+
5944
+ sticky?: &quot;header&quot; | &quot;headerAndFooter&quot;</code></pre>
5945
+ </div>
5946
+ </div>
4766
5947
 
4767
5948
  <div class="panel panel-stories">
4768
5949
 
@@ -4837,7 +6018,8 @@ import { Fragment } from "react";</code></pre>
4837
6018
  <span class="badge ok">story ok</span>
4838
6019
  </div>
4839
6020
  <div>enclosed — bordered, rounded card container</div>
4840
- <div class="hint">`enclosed` wraps the table in a bordered, rounded container — the standalone &quot;card&quot; look, as opposed to a full-bleed page table.</div>
6021
+ <div class="hint">`enclosed` wraps the table in a bordered, rounded container — the standalone
6022
+ &quot;card&quot; look, as opposed to a full-bleed page table.</div>
4841
6023
  <pre><code>const Enclosed = args =&gt; renderTable(args);</code></pre>
4842
6024
  </div>
4843
6025
  <div class="note ok">
@@ -4915,258 +6097,109 @@ import { Fragment } from "react";</code></pre>
4915
6097
  </div>
4916
6098
  </div>
4917
6099
 
6100
+
4918
6101
  </div>
4919
6102
  </article>
4920
6103
  <article
4921
6104
  class="card
4922
- has-error
4923
- has-info
6105
+ no-error
6106
+ no-info
4924
6107
  no-story-error
4925
6108
  no-doc-error"
4926
6109
  role="listitem"
4927
6110
  aria-label="Tabs.Root">
4928
6111
  <div class="head">
4929
6112
  <div class="title">
4930
- <h2><span class="status-dot dot-err"></span> Tabs.Root</h2>
6113
+ <h2><span class="status-dot dot-ok"></span> Tabs.Root</h2>
4931
6114
  <div class="badges">
4932
- <label for="c-20-components-tabs-err" class="badge err as-toggle">prop type error</label>
4933
- <label for="c-20-components-tabs-info" class="badge info as-toggle">1 info</label>
6115
+ <label for="c-20-components-tabs-props" class="badge ok as-toggle">9 prop types</label>
6116
+
4934
6117
  <label for="c-20-components-tabs-stories" class="badge ok as-toggle">8 stories</label>
4935
6118
 
6119
+
4936
6120
  </div>
4937
6121
  </div>
4938
6122
  <div class="meta" title="./src/tabs/tabs.stories.tsx">components-tabs · ./src/tabs/tabs.stories.tsx</div>
4939
-
4940
-
4941
-
6123
+ <div>Root provider for a Tabs group</div>
6124
+ <div class="hint">Tabs is a compound built on Radix UI: `Root` owns the selected tab, `List`
6125
+ holds the `Trigger`s, and one `Content` renders per tab. `variant` picks the
6126
+ look — `line` (default) underlines the active tab, `enclosed` renders
6127
+ segmented pills, `button` renders button-like tabs.
6128
+
6129
+ `Label` is text styled as an inactive trigger, for a single title sitting in
6130
+ the same row as the tabs.</div>
6131
+ <div class="kv"><span class="chip">summary: Root provider for a Tabs group</span><span class="chip">example: ```tsx
6132
+ import { Tabs } from &#39;@agentero/design-system/tabs&#39;;
6133
+
6134
+ &lt;Tabs.Root defaultValue=&quot;overview&quot;&gt;
6135
+ &lt;Tabs.List&gt;
6136
+ &lt;Tabs.Trigger value=&quot;overview&quot;&gt;Overview&lt;/Tabs.Trigger&gt;
6137
+ &lt;Tabs.Trigger value=&quot;activity&quot;&gt;Activity&lt;/Tabs.Trigger&gt;
6138
+ &lt;/Tabs.List&gt;
6139
+ &lt;Tabs.Content value=&quot;overview&quot;&gt;…&lt;/Tabs.Content&gt;
6140
+ &lt;Tabs.Content value=&quot;activity&quot;&gt;…&lt;/Tabs.Content&gt;
6141
+ &lt;/Tabs.Root&gt;
6142
+ ```</span></div>
4942
6143
  </div>
4943
6144
 
4944
6145
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
4945
- <input id="c-20-components-tabs-err" class="tg tg-err" type="checkbox" hidden />
4946
- <input id="c-20-components-tabs-info" class="tg tg-info" type="checkbox" hidden />
6146
+
6147
+
4947
6148
  <input id="c-20-components-tabs-stories" class="tg tg-stories" type="checkbox" hidden />
4948
6149
 
4949
6150
 
6151
+ <input id="c-20-components-tabs-props" class="tg tg-props" type="checkbox" hidden />
4950
6152
 
4951
6153
  <div class="panels">
4952
6154
 
4953
- <div class="panel panel-err">
4954
-
4955
- <div class="note err">
4956
- <div class="note-title">Prop type error</div>
4957
- <div class="note-body"><pre><code>No component file found for the &quot;Tabs.Root&quot; component.
4958
- 4 | import { Tabs } from &#39;.&#39;;
4959
- 5 |
4960
- &gt; 6 | const meta = {
4961
- | ^
4962
- 7 | title: &#39;Components/Tabs&#39;,
4963
- 8 | component: Tabs.Root,
4964
- 9 | tags: [&#39;autodocs&#39;]
4965
-
4966
- ./src/tabs/tabs.stories.tsx:
4967
- import type { Meta, StoryObj } from &#39;@storybook/react-vite&#39;;
4968
- import { expect, userEvent, within } from &#39;storybook/test&#39;;
4969
-
4970
- import { Tabs } from &#39;.&#39;;
4971
-
4972
- const meta = {
4973
- title: &#39;Components/Tabs&#39;,
4974
- component: Tabs.Root,
4975
- tags: [&#39;autodocs&#39;]
4976
- } satisfies Meta&lt;typeof Tabs.Root&gt;;
4977
-
4978
- export default meta;
4979
-
4980
- type Story = StoryObj&lt;typeof meta&gt;;
4981
-
4982
- const TABS = [
4983
- { value: &#39;overview&#39;, label: &#39;Overview&#39;, body: &#39;A summary of the policy and its coverage.&#39; },
4984
- { value: &#39;documents&#39;, label: &#39;Documents&#39;, body: &#39;Declarations, endorsements and forms.&#39; },
4985
- { value: &#39;activity&#39;, label: &#39;Activity&#39;, body: &#39;A timeline of recent changes and events.&#39; }
4986
- ] as const;
4987
-
4988
- const TabItems = () =&gt;
4989
- TABS.map(({ value, label }) =&gt; (
4990
- &lt;Tabs.Trigger key={value} value={value}&gt;
4991
- {label}
4992
- &lt;/Tabs.Trigger&gt;
4993
- ));
4994
-
4995
- const TabPanels = () =&gt;
4996
- TABS.map(({ value, body }) =&gt; (
4997
- &lt;Tabs.Content key={value} value={value} className=&quot;p-4 text-sm text-text-default-base-primary&quot;&gt;
4998
- {body}
4999
- &lt;/Tabs.Content&gt;
5000
- ));
5001
-
5002
- /** `line` (default): the active tab is marked with an animated underline. */
5003
- export const Default: Story = {
5004
- args: {
5005
- variant: &#39;line&#39;,
5006
- defaultValue: &#39;overview&#39;
5007
- },
5008
- argTypes: {
5009
- variant: {
5010
- control: &#39;radio&#39;,
5011
- options: [&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;],
5012
- description: &#39;line = underline; enclosed = segmented pills; button = button-like tabs&#39;
5013
- }
5014
- },
5015
- render: args =&gt; (
5016
- &lt;Tabs.Root {...args}&gt;
5017
- &lt;Tabs.List&gt;
5018
- &lt;TabItems /&gt;
5019
- &lt;/Tabs.List&gt;
5020
- &lt;TabPanels /&gt;
5021
- &lt;/Tabs.Root&gt;
5022
- )
5023
- };
5024
-
5025
- /** `enclosed` renders segmented pills; the active tab sits on a raised surface. */
5026
- export const Enclosed: Story = {
5027
- render: () =&gt; (
5028
- &lt;Tabs.Root variant=&quot;enclosed&quot; defaultValue=&quot;overview&quot;&gt;
5029
- &lt;Tabs.List&gt;
5030
- &lt;TabItems /&gt;
5031
- &lt;/Tabs.List&gt;
5032
- &lt;TabPanels /&gt;
5033
- &lt;/Tabs.Root&gt;
5034
- )
5035
- };
5036
-
5037
- /** `button` renders button-like tabs, with room for a leading icon per trigger. */
5038
- export const Buttons: Story = {
5039
- render: () =&gt; (
5040
- &lt;Tabs.Root variant=&quot;button&quot; defaultValue=&quot;overview&quot;&gt;
5041
- &lt;Tabs.List&gt;
5042
- &lt;TabItems /&gt;
5043
- &lt;/Tabs.List&gt;
5044
- &lt;TabPanels /&gt;
5045
- &lt;/Tabs.Root&gt;
5046
- )
5047
- };
5048
-
5049
- /** `position` aligns the tab list within the row (`start` is the default). */
5050
- export const Positions: Story = {
5051
- render: () =&gt; (
5052
- &lt;div className=&quot;flex flex-col gap-8&quot;&gt;
5053
- {([&#39;start&#39;, &#39;center&#39;, &#39;end&#39;] as const).map(position =&gt; (
5054
- &lt;Tabs.Root key={position} variant=&quot;enclosed&quot; position={position} defaultValue=&quot;overview&quot;&gt;
5055
- &lt;Tabs.List&gt;
5056
- &lt;TabItems /&gt;
5057
- &lt;/Tabs.List&gt;
5058
- &lt;TabPanels /&gt;
5059
- &lt;/Tabs.Root&gt;
5060
- ))}
5061
- &lt;/div&gt;
5062
- )
5063
- };
5064
-
5065
- /** `position=&quot;full&quot;` stretches the tab list to fill the available width. */
5066
- export const FullWidth: Story = {
5067
- render: () =&gt; (
5068
- &lt;Tabs.Root variant=&quot;enclosed&quot; position=&quot;full&quot; defaultValue=&quot;overview&quot;&gt;
5069
- &lt;Tabs.List&gt;
5070
- &lt;TabItems /&gt;
5071
- &lt;/Tabs.List&gt;
5072
- &lt;TabPanels /&gt;
5073
- &lt;/Tabs.Root&gt;
5074
- )
5075
- };
5076
-
5077
- /**
5078
- * Triggers accept `asChild` to render as another element — e.g. a router link.
5079
- * The trigger resets the anchor&#39;s default underline, so link-based tabs match
5080
- * the button-based ones.
5081
- */
5082
- export const AsChildLinks: Story = {
5083
- render: () =&gt; (
5084
- &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
5085
- &lt;Tabs.List&gt;
5086
- {TABS.map(({ value, label }) =&gt; (
5087
- &lt;Tabs.Trigger key={value} value={value} asChild&gt;
5088
- &lt;a href={`#${value}`}&gt;{label}&lt;/a&gt;
5089
- &lt;/Tabs.Trigger&gt;
5090
- ))}
5091
- &lt;/Tabs.List&gt;
5092
- &lt;TabPanels /&gt;
5093
- &lt;/Tabs.Root&gt;
5094
- ),
5095
- play: async ({ canvasElement }) =&gt; {
5096
- const canvas = within(canvasElement);
5097
- const overview = canvas.getByRole(&#39;tab&#39;, { name: /overview/i });
5098
-
5099
- await expect(overview.tagName).toBe(&#39;A&#39;);
5100
- await expect(getComputedStyle(overview).textDecorationLine).toBe(&#39;none&#39;);
5101
- }
5102
- };
5103
-
5104
- /** Selecting a tab reveals its panel and hides the others. */
5105
- export const SwitchTabs: Story = {
5106
- args: {
5107
- variant: &#39;line&#39;,
5108
- defaultValue: &#39;overview&#39;
5109
- },
5110
- render: args =&gt; (
5111
- &lt;Tabs.Root {...args}&gt;
5112
- &lt;Tabs.List&gt;
5113
- &lt;TabItems /&gt;
5114
- &lt;/Tabs.List&gt;
5115
- &lt;TabPanels /&gt;
5116
- &lt;/Tabs.Root&gt;
5117
- ),
5118
- play: async ({ canvasElement }) =&gt; {
5119
- const canvas = within(canvasElement);
5120
- const overview = canvas.getByRole(&#39;tab&#39;, { name: /overview/i });
5121
- const documents = canvas.getByRole(&#39;tab&#39;, { name: /documents/i });
5122
-
5123
- await expect(overview).toHaveAttribute(&#39;data-state&#39;, &#39;active&#39;);
5124
- await expect(await canvas.findByText(/summary of the policy/i)).toBeVisible();
5125
-
5126
- await userEvent.click(documents);
5127
- await expect(documents).toHaveAttribute(&#39;data-state&#39;, &#39;active&#39;);
5128
- await expect(overview).toHaveAttribute(&#39;data-state&#39;, &#39;inactive&#39;);
5129
- await expect(await canvas.findByText(/declarations, endorsements/i)).toBeVisible();
5130
- }
5131
- };
5132
-
5133
- /**
5134
- * A standalone `Label` gives a panel with a single, non-interactive title the
5135
- * inactive trigger&#39;s exact look: outside a `Root` it never gets the active
5136
- * data-state, and `pointer-events-none` keeps hover styles off. It is a plain
5137
- * `span`, so wrap it in a heading element for heading semantics. No tab or
5138
- * tablist role is announced.
5139
- */
5140
- export const SingleTitle: Story = {
5141
- render: () =&gt; (
5142
- &lt;div className=&quot;flex flex-col items-start gap-6&quot;&gt;
5143
- {([&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;] as const).map(variant =&gt; (
5144
- &lt;h2 key={variant}&gt;
5145
- &lt;Tabs.Label variant={variant}&gt;Shared coverages ({variant})&lt;/Tabs.Label&gt;
5146
- &lt;/h2&gt;
5147
- ))}
5148
- &lt;/div&gt;
5149
- ),
5150
- play: async ({ canvasElement }) =&gt; {
5151
- const canvas = within(canvasElement);
5152
-
5153
- await expect(canvas.getAllByRole(&#39;heading&#39;)).toHaveLength(3);
5154
- await expect(canvas.queryByRole(&#39;tablist&#39;)).not.toBeInTheDocument();
5155
- await expect(canvas.queryByRole(&#39;tab&#39;)).not.toBeInTheDocument();
5156
- }
5157
- };
5158
- </code></pre></div>
5159
- </div>
5160
- </div>
5161
6155
 
5162
- <div class="panel panel-info">
5163
-
5164
- <div class="note info">
5165
- <div class="note-title">Info</div>
5166
- <div class="note-body">No description found. Write a jsdoc comment such as /** Component description */.</div>
5167
- </div>
5168
- </div>
5169
6156
 
6157
+ <div class="panel panel-props">
6158
+ <div class="note ok">
6159
+ <div class="row">
6160
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
6161
+ <span class="badge ok">9 prop types</span>
6162
+ </div>
6163
+ <pre><code>Component: src/tabs/index.ts::Tabs</code></pre>
6164
+ <pre><code>Props:</code></pre>
6165
+ <pre><code>/**
6166
+ * Whether a tab is activated automatically or manually.
6167
+ */
6168
+ activationMode?: &quot;manual&quot; | &quot;automatic&quot; = automatic
6169
+
6170
+ asChild?: boolean
6171
+
6172
+ /**
6173
+ * The value of the tab to select by default, if uncontrolled
6174
+ */
6175
+ defaultValue?: string
6176
+
6177
+ /**
6178
+ * The direction of navigation between toolbar items.
6179
+ */
6180
+ dir?: &quot;ltr&quot; | &quot;rtl&quot;
6181
+
6182
+ /**
6183
+ * A function called when a new tab is selected
6184
+ */
6185
+ onValueChange?: (value: string) =&gt; void
6186
+
6187
+ /**
6188
+ * The orientation the tabs are layed out.
6189
+ * Mainly so arrow navigation is done accordingly (left &amp; right vs. up &amp; down)
6190
+ */
6191
+ orientation?: &quot;horizontal&quot; | &quot;vertical&quot; = horizontal
6192
+
6193
+ position?: &quot;center&quot; | &quot;start&quot; | &quot;end&quot; | &quot;full&quot;
6194
+
6195
+ /**
6196
+ * The value for the selected tab, if controlled
6197
+ */
6198
+ value?: string
6199
+
6200
+ variant?: &quot;enclosed&quot; | &quot;button&quot; | &quot;line&quot;</code></pre>
6201
+ </div>
6202
+ </div>
5170
6203
 
5171
6204
  <div class="panel panel-stories">
5172
6205
 
@@ -5268,7 +6301,9 @@ export const SingleTitle: Story = {
5268
6301
  <span class="badge ok">story ok</span>
5269
6302
  </div>
5270
6303
 
5271
- <div class="hint">Triggers accept `asChild` to render as another element — e.g. a router link. The trigger resets the anchor&#39;s default underline, so link-based tabs match the button-based ones.</div>
6304
+ <div class="hint">Triggers accept `asChild` to render as another element — e.g. a router link.
6305
+ The trigger resets the anchor&#39;s default underline, so link-based tabs match
6306
+ the button-based ones.</div>
5272
6307
  <pre><code>const AsChildLinks = () =&gt; (
5273
6308
  &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
5274
6309
  &lt;Tabs.List&gt;
@@ -5302,7 +6337,11 @@ export const SingleTitle: Story = {
5302
6337
  <span class="badge ok">story ok</span>
5303
6338
  </div>
5304
6339
 
5305
- <div class="hint">A standalone `Label` gives a panel with a single, non-interactive title the inactive trigger&#39;s exact look: outside a `Root` it never gets the active data-state, and `pointer-events-none` keeps hover styles off. It is a plain `span`, so wrap it in a heading element for heading semantics. No tab or tablist role is announced.</div>
6340
+ <div class="hint">A standalone `Label` gives a panel with a single, non-interactive title the
6341
+ inactive trigger&#39;s exact look: outside a `Root` it never gets the active
6342
+ data-state, and `pointer-events-none` keeps hover styles off. It is a plain
6343
+ `span`, so wrap it in a heading element for heading semantics. No tab or
6344
+ tablist role is announced.</div>
5306
6345
  <pre><code>const SingleTitle = () =&gt; (
5307
6346
  &lt;div className=&quot;flex flex-col items-start gap-6&quot;&gt;
5308
6347
  {([&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;] as const).map(variant =&gt; (
@@ -5315,6 +6354,7 @@ export const SingleTitle: Story = {
5315
6354
  </div>
5316
6355
  </div>
5317
6356
 
6357
+
5318
6358
  </div>
5319
6359
  </article>
5320
6360
  <article
@@ -5329,16 +6369,22 @@ export const SingleTitle: Story = {
5329
6369
  <div class="title">
5330
6370
  <h2><span class="status-dot dot-ok"></span> Tag</h2>
5331
6371
  <div class="badges">
5332
- <label for="c-21-components-tag-props" class="badge ok as-toggle">6 prop types</label>
6372
+ <label for="c-21-components-tag-props" class="badge ok as-toggle">8 prop types</label>
5333
6373
 
5334
6374
  <label for="c-21-components-tag-stories" class="badge ok as-toggle">10 stories</label>
5335
6375
 
6376
+
5336
6377
  </div>
5337
6378
  </div>
5338
6379
  <div class="meta" title="./src/tag/tag.stories.tsx">components-tag · ./src/tag/tag.stories.tsx</div>
5339
-
5340
- <div class="hint">Tag is a compact semantic label for statuses, categories, counts, and attributes. Pick `color` for meaning, `variant` for fill emphasis, and `size` for prominence. A plain Tag is a static badge; pass `asChild` to make it an interactive link or button, which adds the pointer cursor and hover fill.</div>
5341
-
6380
+ <div>Compact semantic label; renders a static badge `&lt;span&gt;` or, with `asChild`, an interactive element</div>
6381
+ <div class="hint">Tag is a compact semantic label for statuses, categories, counts, and
6382
+ attributes. Pick `color` for meaning, `variant` for fill emphasis, and
6383
+ `size` for prominence. A plain Tag is a static badge; pass `asChild` to make
6384
+ it an interactive link or button, which adds the pointer cursor and hover fill.</div>
6385
+ <div class="kv"><span class="chip">summary: Compact semantic label; renders a static badge `&lt;span&gt;` or, with `asChild`, an interactive element</span><span class="chip">example: &lt;Tag color=&quot;positive&quot;&gt;Active&lt;/Tag&gt;</span><span class="chip">example: &lt;Tag asChild color=&quot;informative&quot;&gt;
6386
+ &lt;a href=&quot;/carriers&quot;&gt;View carriers&lt;/a&gt;
6387
+ &lt;/Tag&gt;</span></div>
5342
6388
  </div>
5343
6389
 
5344
6390
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -5346,6 +6392,7 @@ export const SingleTitle: Story = {
5346
6392
 
5347
6393
  <input id="c-21-components-tag-stories" class="tg tg-stories" type="checkbox" hidden />
5348
6394
 
6395
+
5349
6396
  <input id="c-21-components-tag-props" class="tg tg-props" type="checkbox" hidden />
5350
6397
 
5351
6398
  <div class="panels">
@@ -5355,8 +6402,8 @@ export const SingleTitle: Story = {
5355
6402
  <div class="panel panel-props">
5356
6403
  <div class="note ok">
5357
6404
  <div class="row">
5358
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
5359
- <span class="badge ok">6 prop types</span>
6405
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
6406
+ <span class="badge ok">8 prop types</span>
5360
6407
  </div>
5361
6408
  <pre><code>Component: src/tag/tag.tsx::Tag</code></pre>
5362
6409
  <pre><code>Props:</code></pre>
@@ -5367,10 +6414,19 @@ export const SingleTitle: Story = {
5367
6414
  */
5368
6415
  asChild?: boolean
5369
6416
 
6417
+ children?: ReactNode
6418
+
5370
6419
  color?: &quot;neutral&quot; | &quot;danger&quot; | &quot;warning&quot; | &quot;creative&quot; | &quot;dynamic&quot; | &quot;playful&quot; | &quot;positive&quot; | &quot;informative&quot;
5371
6420
 
5372
6421
  pill?: boolean
5373
6422
 
6423
+ /**
6424
+ * Allows getting a ref to the component instance.
6425
+ * Once the component unmounts, React will set `ref.current` to `null`
6426
+ * (or call the ref with `null` if you passed a callback ref).
6427
+ */
6428
+ ref?: ((((instance: HTMLSpanElement | null) =&gt; void | (() =&gt; VoidOrUndefinedOnly)) | RefObject&lt;HTMLSpanElement | null&gt;) &amp; (((instance: HTMLElement | null) =&gt; void | (() =&gt; VoidOrUndefinedOnly)) | RefObject&lt;...&gt;)) | null | undefined
6429
+
5374
6430
  size?: &quot;sm&quot; | &quot;md&quot; | &quot;xs&quot;
5375
6431
 
5376
6432
  truncate?: boolean
@@ -5397,7 +6453,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5397
6453
  <span class="badge ok">story ok</span>
5398
6454
  </div>
5399
6455
  <div>Default args playground for Tag</div>
5400
- <div class="hint">Args-controlled playground. Toggle `color`, `variant`, `size`, `pill`, and `truncate` from the Controls panel to explore every visual combination.</div>
6456
+ <div class="hint">Args-controlled playground. Toggle `color`, `variant`, `size`, `pill`, and
6457
+ `truncate` from the Controls panel to explore every visual combination.</div>
5401
6458
  <pre><code>const Default = () =&gt; &lt;Tag color=&quot;neutral&quot; variant=&quot;secondary&quot; size=&quot;sm&quot;&gt;Default&lt;/Tag&gt;;</code></pre>
5402
6459
  </div>
5403
6460
  <div class="note ok">
@@ -5406,7 +6463,9 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5406
6463
  <span class="badge ok">story ok</span>
5407
6464
  </div>
5408
6465
  <div>All three sizes across icon-only, icon + text, and text-only</div>
5409
- <div class="hint">The three sizes — `xs` (20px), `sm` (24px, default), and `md` (32px) — each shown icon-only, icon + text, and text-only so the type and icon scale are visible.</div>
6466
+ <div class="hint">The three sizes — `xs` (20px), `sm` (24px, default), and `md` (32px) — each
6467
+ shown icon-only, icon + text, and text-only so the type and icon scale are
6468
+ visible.</div>
5410
6469
  <pre><code>const Sizes = () =&gt; (
5411
6470
  &lt;Stack&gt;
5412
6471
  {([&#39;xs&#39;, &#39;sm&#39;, &#39;md&#39;] as const).map(size =&gt; (
@@ -5440,7 +6499,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5440
6499
  <span class="badge ok">story ok</span>
5441
6500
  </div>
5442
6501
  <div>Rounded (default) vs pill</div>
5443
- <div class="hint">The `Style` axis: the default rounded corners (top row) versus `pill` fully rounded (bottom row), shown across every fill variant.</div>
6502
+ <div class="hint">The `Style` axis: the default rounded corners (top row) versus `pill` fully
6503
+ rounded (bottom row), shown across every fill variant.</div>
5444
6504
  <pre><code>const Styles = () =&gt; (
5445
6505
  &lt;Stack gap=&quot;0.5rem&quot;&gt;
5446
6506
  &lt;Row&gt;
@@ -5466,7 +6526,10 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5466
6526
  <span class="badge ok">story ok</span>
5467
6527
  </div>
5468
6528
  <div>Static badge vs interactive (asChild) hover</div>
5469
- <div class="hint">Static badge vs interactive Tag. A plain `&lt;span&gt;` badge has no hover; pass `asChild` with a `&lt;button&gt;` (or `&lt;a&gt;`) to make it interactive — that adds the pointer cursor and reveals the hover fill on `:hover`. Hover the middle and right Tags to see it.</div>
6529
+ <div class="hint">Static badge vs interactive Tag. A plain `&lt;span&gt;` badge has no hover; pass
6530
+ `asChild` with a `&lt;button&gt;` (or `&lt;a&gt;`) to make it interactive — that adds the
6531
+ pointer cursor and reveals the hover fill on `:hover`. Hover the middle and
6532
+ right Tags to see it.</div>
5470
6533
  <pre><code>const Interactive = () =&gt; (
5471
6534
  &lt;Row&gt;
5472
6535
  &lt;Tag color=&quot;informative&quot; variant=&quot;secondary&quot;&gt;
@@ -5489,7 +6552,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5489
6552
  <span class="badge ok">story ok</span>
5490
6553
  </div>
5491
6554
  <div>`secondary` variant across all colors</div>
5492
- <div class="hint">`secondary` fills with a tinted background plus a matching border, shown across every color.</div>
6555
+ <div class="hint">`secondary` fills with a tinted background plus a matching border, shown
6556
+ across every color.</div>
5493
6557
  <pre><code>const Secondary = () =&gt; (
5494
6558
  &lt;Row&gt;
5495
6559
  {COLORS.map(color =&gt; (
@@ -5506,7 +6570,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5506
6570
  <span class="badge ok">story ok</span>
5507
6571
  </div>
5508
6572
  <div>`tertiary` variant across all colors</div>
5509
- <div class="hint">`tertiary` (default) fills with a tinted background and no border, shown across every color.</div>
6573
+ <div class="hint">`tertiary` (default) fills with a tinted background and no border, shown
6574
+ across every color.</div>
5510
6575
  <pre><code>const Tertiary = () =&gt; (
5511
6576
  &lt;Row&gt;
5512
6577
  {COLORS.map(color =&gt; (
@@ -5523,7 +6588,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5523
6588
  <span class="badge ok">story ok</span>
5524
6589
  </div>
5525
6590
  <div>`ghost` variant across all colors</div>
5526
- <div class="hint">`ghost` shows colored text alone with no background or border, across every color.</div>
6591
+ <div class="hint">`ghost` shows colored text alone with no background or border, across every
6592
+ color.</div>
5527
6593
  <pre><code>const Ghost = () =&gt; (
5528
6594
  &lt;Row&gt;
5529
6595
  {COLORS.map(color =&gt; (
@@ -5540,7 +6606,9 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5540
6606
  <span class="badge ok">story ok</span>
5541
6607
  </div>
5542
6608
  <div>`invisible` variant as span and as interactive button</div>
5543
- <div class="hint">`invisible` stays fully transparent until hovered, then reveals its fill. The top row renders plain `&lt;span&gt;` Tags; the bottom row renders interactive Tags via `asChild` with a `&lt;button&gt;` child.</div>
6609
+ <div class="hint">`invisible` stays fully transparent until hovered, then reveals its fill.
6610
+ The top row renders plain `&lt;span&gt;` Tags; the bottom row renders interactive
6611
+ Tags via `asChild` with a `&lt;button&gt;` child.</div>
5544
6612
  <pre><code>const Invisible = () =&gt; (
5545
6613
  &lt;Stack gap=&quot;0.5rem&quot;&gt;
5546
6614
  &lt;Row&gt;
@@ -5566,7 +6634,8 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5566
6634
  <span class="badge ok">story ok</span>
5567
6635
  </div>
5568
6636
  <div>Variant × color grid with icons</div>
5569
- <div class="hint">Every variant for every color rendered with a leading and trailing icon. Icons are tinted with each color&#39;s `icon-tag-*` token.</div>
6637
+ <div class="hint">Every variant for every color rendered with a leading and trailing icon.
6638
+ Icons are tinted with each color&#39;s `icon-tag-*` token.</div>
5570
6639
  <pre><code>const WithIcon = () =&gt; (
5571
6640
  &lt;Stack&gt;
5572
6641
  {COLORS.map(color =&gt; (
@@ -5589,7 +6658,9 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5589
6658
  <span class="badge ok">story ok</span>
5590
6659
  </div>
5591
6660
  <div>Variant × color matrix — default, pill, button, and icon layouts</div>
5592
- <div class="hint">Full matrix: every variant for every color, repeated as default, as `pill`, as an interactive `asChild` `&lt;button&gt;`, with a single leading icon, with leading + trailing icons, and icon-only.</div>
6661
+ <div class="hint">Full matrix: every variant for every color, repeated as default, as `pill`,
6662
+ as an interactive `asChild` `&lt;button&gt;`, with a single leading icon, with
6663
+ leading + trailing icons, and icon-only.</div>
5593
6664
  <pre><code>const Colors = () =&gt; (
5594
6665
  &lt;div style={{ display: &#39;flex&#39;, gap: &#39;4rem&#39;, flexWrap: &#39;wrap&#39; }}&gt;
5595
6666
  &lt;Stack&gt;
@@ -5689,6 +6760,7 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5689
6760
  </div>
5690
6761
  </div>
5691
6762
 
6763
+
5692
6764
  </div>
5693
6765
  </article>
5694
6766
  <article
@@ -5707,12 +6779,18 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5707
6779
 
5708
6780
  <label for="c-22-components-toast-stories" class="badge ok as-toggle">11 stories</label>
5709
6781
 
6782
+
5710
6783
  </div>
5711
6784
  </div>
5712
6785
  <div class="meta" title="./src/toast/toast.stories.tsx">components-toast · ./src/toast/toast.stories.tsx</div>
5713
-
5714
- <div class="hint">Toast renders transient feedback about an outcome — saved, failed, warning, info — without interrupting the user&#39;s flow. Mount `&lt;Toast /&gt;` once near the app root to register the provider, then call the imperative `toast()` API from anywhere in the tree. Five semantic types (`neutral`, `success`, `error`, `warning`, `info`) × two layouts (`inline`, `expanded`) cover the common feedback patterns.</div>
5715
-
6786
+ <div>Toast provider; mount once near the app root</div>
6787
+ <div class="hint">Toast renders transient feedback about an outcome — saved, failed, warning,
6788
+ info — without interrupting the user&#39;s flow. Mount `&lt;Toast /&gt;` once near
6789
+ the app root to register the provider, then call the imperative `toast()`
6790
+ API from anywhere in the tree. Five semantic types (`neutral`, `success`,
6791
+ `error`, `warning`, `info`) × two layouts (`inline`, `expanded`) cover the
6792
+ common feedback patterns.</div>
6793
+ <div class="kv"><span class="chip">summary: Toast provider; mount once near the app root</span><span class="chip">example: &lt;Toast /&gt;</span><span class="chip">example: &lt;Toast position=&quot;top-center&quot; duration={4000} /&gt;</span></div>
5716
6794
  </div>
5717
6795
 
5718
6796
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -5720,6 +6798,7 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5720
6798
 
5721
6799
  <input id="c-22-components-toast-stories" class="tg tg-stories" type="checkbox" hidden />
5722
6800
 
6801
+
5723
6802
  <input id="c-22-components-toast-props" class="tg tg-props" type="checkbox" hidden />
5724
6803
 
5725
6804
  <div class="panels">
@@ -5729,7 +6808,7 @@ variant?: &quot;ghost&quot; | &quot;secondary&quot; | &quot;tertiary&quot; | &qu
5729
6808
  <div class="panel panel-props">
5730
6809
  <div class="note ok">
5731
6810
  <div class="row">
5732
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
6811
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
5733
6812
  <span class="badge ok">11 prop types</span>
5734
6813
  </div>
5735
6814
  <pre><code>Component: src/toast/toast.tsx::Toast</code></pre>
@@ -5772,12 +6851,12 @@ invert?: boolean
5772
6851
  /**
5773
6852
  * Offset from the screen edge, in pixels or as a CSS length.
5774
6853
  */
5775
- offset?: string | number
6854
+ offset?: string | number | undefined
5776
6855
 
5777
6856
  /**
5778
6857
  * Placement of the toaster on the screen. Defaults to `&#39;bottom-right&#39;`.
5779
6858
  */
5780
- position?: ToastPosition = bottom-right
6859
+ position?: &quot;top-left&quot; | &quot;top-center&quot; | &quot;top-right&quot; | &quot;bottom-left&quot; | &quot;bottom-center&quot; | &quot;bottom-right&quot; = &#39;bottom-right&#39;
5781
6860
 
5782
6861
  /**
5783
6862
  * When `true`, sonner paints colored backgrounds per type (DS uses its own icon tokens by default).
@@ -5809,7 +6888,9 @@ visibleToasts?: number</code></pre>
5809
6888
  <span class="badge ok">story ok</span>
5810
6889
  </div>
5811
6890
  <div>Default playground for the Toast provider</div>
5812
- <div class="hint">Args-controlled playground. Click the button to fire a neutral toast; tweak `position` and `duration` from the Controls panel to preview the provider defaults.</div>
6891
+ <div class="hint">Args-controlled playground. Click the button to fire a neutral toast; tweak
6892
+ `position` and `duration` from the Controls panel to preview the provider
6893
+ defaults.</div>
5813
6894
  <pre><code>const Default = () =&gt; (
5814
6895
  &lt;div style={{ minHeight: &#39;240px&#39; }}&gt;
5815
6896
  &lt;Button variant=&quot;secondary&quot; onClick={() =&gt; toast(&#39;Hello from Toast&#39;)}&gt;
@@ -5824,7 +6905,9 @@ visibleToasts?: number</code></pre>
5824
6905
  <span class="badge ok">story ok</span>
5825
6906
  </div>
5826
6907
  <div>Inline layout across all five semantic types</div>
5827
- <div class="hint">Inline layout (default). Compact treatment — title with an optional description stacked directly below it. The `type` drives the icon color. Use for short acknowledgments that don&#39;t need a colored rail.</div>
6908
+ <div class="hint">Inline layout (default). Compact treatment — title with an optional
6909
+ description stacked directly below it. The `type` drives the icon color.
6910
+ Use for short acknowledgments that don&#39;t need a colored rail.</div>
5828
6911
  <pre><code>const Inline = () =&gt; (
5829
6912
  &lt;div style={{ display: &#39;flex&#39;, flexWrap: &#39;wrap&#39;, gap: &#39;0.5rem&#39; }}&gt;
5830
6913
  &lt;Button
@@ -5867,7 +6950,9 @@ visibleToasts?: number</code></pre>
5867
6950
  <span class="badge ok">story ok</span>
5868
6951
  </div>
5869
6952
  <div>Expanded layout across all five semantic types</div>
5870
- <div class="hint">Expanded layout. Multi-line treatment with a 0.375rem colored left rail that tracks the toast&#39;s `type`. Use for feedback that benefits from a description on its own line or a trailing action button.</div>
6953
+ <div class="hint">Expanded layout. Multi-line treatment with a 0.375rem colored left rail
6954
+ that tracks the toast&#39;s `type`. Use for feedback that benefits from a
6955
+ description on its own line or a trailing action button.</div>
5871
6956
  <pre><code>const Expanded = () =&gt; (
5872
6957
  &lt;div style={{ display: &#39;flex&#39;, flexWrap: &#39;wrap&#39;, gap: &#39;0.5rem&#39; }}&gt;
5873
6958
  &lt;Button
@@ -5929,7 +7014,9 @@ visibleToasts?: number</code></pre>
5929
7014
  <span class="badge ok">story ok</span>
5930
7015
  </div>
5931
7016
  <div>Toast with a structured action button</div>
5932
- <div class="hint">Toast with a structured `action` object. Passing `{ label, onClick }` renders the built-in secondary Button; the handler runs and the toast auto-dismisses afterward.</div>
7017
+ <div class="hint">Toast with a structured `action` object. Passing `{ label, onClick }`
7018
+ renders the built-in secondary Button; the handler runs and the toast
7019
+ auto-dismisses afterward.</div>
5933
7020
  <pre><code>const WithActionObject = () =&gt; (
5934
7021
  &lt;Button
5935
7022
  variant=&quot;secondary&quot;
@@ -5950,7 +7037,9 @@ visibleToasts?: number</code></pre>
5950
7037
  <span class="badge ok">story ok</span>
5951
7038
  </div>
5952
7039
  <div>Toast with a custom ReactNode action</div>
5953
- <div class="hint">Toast with a raw-ReactNode `action`. Pass any JSX to render a custom trailing control — a link, a pair of buttons, etc. — when the default secondary Button doesn&#39;t fit.</div>
7040
+ <div class="hint">Toast with a raw-ReactNode `action`. Pass any JSX to render a custom
7041
+ trailing control — a link, a pair of buttons, etc. — when the default
7042
+ secondary Button doesn&#39;t fit.</div>
5954
7043
  <pre><code>const WithActionNode = () =&gt; (
5955
7044
  &lt;Button
5956
7045
  variant=&quot;secondary&quot;
@@ -5974,7 +7063,8 @@ visibleToasts?: number</code></pre>
5974
7063
  <span class="badge ok">story ok</span>
5975
7064
  </div>
5976
7065
  <div>Toast with an action and a cancel control</div>
5977
- <div class="hint">Toast with both `action` and `cancel`. Cancel renders as a ghost Button next to the action; its handler runs and the toast auto-dismisses.</div>
7066
+ <div class="hint">Toast with both `action` and `cancel`. Cancel renders as a ghost Button
7067
+ next to the action; its handler runs and the toast auto-dismisses.</div>
5978
7068
  <pre><code>const WithActionAndCancel = () =&gt; (
5979
7069
  &lt;Button
5980
7070
  variant=&quot;secondary&quot;
@@ -5996,7 +7086,9 @@ visibleToasts?: number</code></pre>
5996
7086
  <span class="badge ok">story ok</span>
5997
7087
  </div>
5998
7088
  <div>Non-dismissible toast (no close button)</div>
5999
- <div class="hint">Non-dismissible toast. Setting `dismissible: false` hides the close button; the toast still auto-dismisses when its `duration` elapses, or programmatically via `toast.dismiss(id)`.</div>
7089
+ <div class="hint">Non-dismissible toast. Setting `dismissible: false` hides the close button;
7090
+ the toast still auto-dismisses when its `duration` elapses, or
7091
+ programmatically via `toast.dismiss(id)`.</div>
6000
7092
  <pre><code>const NonDismissible = () =&gt; (
6001
7093
  &lt;Button
6002
7094
  variant=&quot;secondary&quot;
@@ -6016,7 +7108,8 @@ visibleToasts?: number</code></pre>
6016
7108
  <span class="badge ok">story ok</span>
6017
7109
  </div>
6018
7110
  <div>Toast with a custom `duration`</div>
6019
- <div class="hint">Long-duration toast. `duration` (in ms) overrides the provider default so long-running operations stay visible until they&#39;re relevant.</div>
7111
+ <div class="hint">Long-duration toast. `duration` (in ms) overrides the provider default so
7112
+ long-running operations stay visible until they&#39;re relevant.</div>
6020
7113
  <pre><code>const LongDuration = () =&gt; (
6021
7114
  &lt;Button
6022
7115
  variant=&quot;secondary&quot;
@@ -6036,7 +7129,8 @@ visibleToasts?: number</code></pre>
6036
7129
  <span class="badge ok">story ok</span>
6037
7130
  </div>
6038
7131
  <div>Dismiss a toast programmatically via its id</div>
6039
- <div class="hint">Programmatic dismissal. `toast()` returns the toast id, which you can pass to `toast.dismiss(id)` to clear it before its duration elapses.</div>
7132
+ <div class="hint">Programmatic dismissal. `toast()` returns the toast id, which you can pass
7133
+ to `toast.dismiss(id)` to clear it before its duration elapses.</div>
6040
7134
  <pre><code>const ProgrammaticDismiss = () =&gt; {
6041
7135
  let toastId: string | number | undefined;
6042
7136
  return (
@@ -6065,7 +7159,9 @@ visibleToasts?: number</code></pre>
6065
7159
  <span class="badge ok">story ok</span>
6066
7160
  </div>
6067
7161
  <div>Wire a toast to an async operation via `toast.promise`</div>
6068
- <div class="hint">`toast.promise` wires a toast to an async operation — loading while the promise is pending, success or error when it settles. Useful for save/submit flows where the outcome feeds back into the same toast.</div>
7162
+ <div class="hint">`toast.promise` wires a toast to an async operation — loading while the
7163
+ promise is pending, success or error when it settles. Useful for
7164
+ save/submit flows where the outcome feeds back into the same toast.</div>
6069
7165
  <pre><code>const WithPromise = () =&gt; {
6070
7166
  const fakeFetch = () =&gt;
6071
7167
  new Promise&lt;string&gt;((resolve, reject) =&gt; {
@@ -6095,7 +7191,9 @@ visibleToasts?: number</code></pre>
6095
7191
  <span class="badge ok">story ok</span>
6096
7192
  </div>
6097
7193
  <div>Override the default type-based icon</div>
6098
- <div class="hint">Custom `icon` override. Pass any ReactNode as `icon` to replace the type-based default — helpful when the toast reflects a domain-specific action (e.g., a sync icon for a sync-in-progress toast).</div>
7194
+ <div class="hint">Custom `icon` override. Pass any ReactNode as `icon` to replace the
7195
+ type-based default — helpful when the toast reflects a domain-specific
7196
+ action (e.g., a sync icon for a sync-in-progress toast).</div>
6099
7197
  <pre><code>const CustomIcon = () =&gt; (
6100
7198
  &lt;Button
6101
7199
  variant=&quot;secondary&quot;
@@ -6115,6 +7213,7 @@ visibleToasts?: number</code></pre>
6115
7213
  </div>
6116
7214
  </div>
6117
7215
 
7216
+
6118
7217
  </div>
6119
7218
  </article>
6120
7219
  <article
@@ -6129,16 +7228,22 @@ visibleToasts?: number</code></pre>
6129
7228
  <div class="title">
6130
7229
  <h2><span class="status-dot dot-ok"></span> Tooltip</h2>
6131
7230
  <div class="badges">
6132
- <label for="c-23-components-tooltip-props" class="badge ok as-toggle">9 prop types</label>
7231
+ <label for="c-23-components-tooltip-props" class="badge ok as-toggle">12 prop types</label>
6133
7232
 
6134
7233
  <label for="c-23-components-tooltip-stories" class="badge ok as-toggle">5 stories</label>
6135
7234
 
7235
+
6136
7236
  </div>
6137
7237
  </div>
6138
7238
  <div class="meta" title="./src/tooltip/tooltip.stories.tsx">components-tooltip · ./src/tooltip/tooltip.stories.tsx</div>
6139
-
6140
- <div class="hint">Tooltip reveals a short, non-essential hint anchored to a trigger element on hover or focus.</div>
6141
-
7239
+ <div>Hover/focus hint anchored to a trigger element</div>
7240
+ <div class="hint">Tooltip reveals a short, non-essential hint anchored to a trigger element
7241
+ on hover or focus.</div>
7242
+ <div class="kv"><span class="chip">summary: Hover/focus hint anchored to a trigger element</span><span class="chip">example: ```tsx
7243
+ &lt;Tooltip content=&quot;Archive this carrier&quot; asChild&gt;
7244
+ &lt;IconButton aria-label=&quot;Archive&quot;&gt;&lt;IconArchive /&gt;&lt;/IconButton&gt;
7245
+ &lt;/Tooltip&gt;
7246
+ ```</span></div>
6142
7247
  </div>
6143
7248
 
6144
7249
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -6146,6 +7251,7 @@ visibleToasts?: number</code></pre>
6146
7251
 
6147
7252
  <input id="c-23-components-tooltip-stories" class="tg tg-stories" type="checkbox" hidden />
6148
7253
 
7254
+
6149
7255
  <input id="c-23-components-tooltip-props" class="tg tg-props" type="checkbox" hidden />
6150
7256
 
6151
7257
  <div class="panels">
@@ -6155,8 +7261,8 @@ visibleToasts?: number</code></pre>
6155
7261
  <div class="panel panel-props">
6156
7262
  <div class="note ok">
6157
7263
  <div class="row">
6158
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
6159
- <span class="badge ok">9 prop types</span>
7264
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
7265
+ <span class="badge ok">12 prop types</span>
6160
7266
  </div>
6161
7267
  <pre><code>Component: src/tooltip/tooltip.tsx::Tooltip</code></pre>
6162
7268
  <pre><code>Props:</code></pre>
@@ -6185,6 +7291,8 @@ className?: string
6185
7291
  */
6186
7292
  content: ReactNode
6187
7293
 
7294
+ defaultOpen?: boolean
7295
+
6188
7296
  /**
6189
7297
  * Delay in ms before opening on hover. Defaults to `0`; focus always opens instantly.
6190
7298
  */
@@ -6195,10 +7303,14 @@ delayDuration?: number = 0
6195
7303
  */
6196
7304
  hideWhenDetached?: boolean
6197
7305
 
7306
+ onOpenChange?: (open: boolean) =&gt; void
7307
+
7308
+ open?: boolean
7309
+
6198
7310
  /**
6199
7311
  * Preferred side of the trigger; flips on collision. Defaults to `&#39;top&#39;`.
6200
7312
  */
6201
- side?: &quot;top&quot; | &quot;right&quot; | &quot;bottom&quot; | &quot;left&quot; = top
7313
+ side?: &quot;right&quot; | &quot;top&quot; | &quot;bottom&quot; | &quot;left&quot; = &#39;top&#39;
6202
7314
 
6203
7315
  /**
6204
7316
  * Distance in pixels between the tooltip and its trigger. Defaults to `4`.
@@ -6297,6 +7409,7 @@ sideOffset?: number = 4</code></pre>
6297
7409
  </div>
6298
7410
  </div>
6299
7411
 
7412
+
6300
7413
  </div>
6301
7414
  </article>
6302
7415
  <article
@@ -6315,12 +7428,20 @@ sideOffset?: number = 4</code></pre>
6315
7428
 
6316
7429
  <label for="c-24-components-validationlist-stories" class="badge ok as-toggle">4 stories</label>
6317
7430
 
7431
+
6318
7432
  </div>
6319
7433
  </div>
6320
7434
  <div class="meta" title="./src/validation-list/validation-list.stories.tsx">components-validationlist · ./src/validation-list/validation-list.stories.tsx</div>
6321
-
6322
- <div class="hint">ValidationList renders a bulleted checklist of rules that light up as a value satisfies them. Each rule&#39;s `pattern` is a `RegExp` or a predicate `(value) =&gt; boolean`, so character-class checks and arbitrary logic (length, membership, …) live in the same list. It is presentational — pair it with your form validation; it does not own the input or block submission.</div>
6323
-
7435
+ <div>Checklist of rules that turn active as the value satisfies them</div>
7436
+ <div class="hint">ValidationList renders a bulleted checklist of rules that light up as a value
7437
+ satisfies them. Each rule&#39;s `pattern` is a `RegExp` or a predicate
7438
+ `(value) =&gt; boolean`, so character-class checks and arbitrary logic (length,
7439
+ membership, …) live in the same list. It is presentational — pair it with
7440
+ your form validation; it does not own the input or block submission.</div>
7441
+ <div class="kv"><span class="chip">summary: Checklist of rules that turn active as the value satisfies them</span><span class="chip">example: &lt;ValidationList
7442
+ value={password}
7443
+ rules={[{ text: &#39;At least 10 characters&#39;, pattern: value =&gt; value.length &gt;= 10 }]}
7444
+ /&gt;</span></div>
6324
7445
  </div>
6325
7446
 
6326
7447
  <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
@@ -6328,6 +7449,7 @@ sideOffset?: number = 4</code></pre>
6328
7449
 
6329
7450
  <input id="c-24-components-validationlist-stories" class="tg tg-stories" type="checkbox" hidden />
6330
7451
 
7452
+
6331
7453
  <input id="c-24-components-validationlist-props" class="tg tg-props" type="checkbox" hidden />
6332
7454
 
6333
7455
  <div class="panels">
@@ -6337,7 +7459,7 @@ sideOffset?: number = 4</code></pre>
6337
7459
  <div class="panel panel-props">
6338
7460
  <div class="note ok">
6339
7461
  <div class="row">
6340
- <span class="ex-name">Prop types <small>(react-docgen-typescript)</small></span>
7462
+ <span class="ex-name">Prop types <small>(react-component-meta)</small></span>
6341
7463
  <span class="badge ok">2 prop types</span>
6342
7464
  </div>
6343
7465
  <pre><code>Component: src/validation-list/validation-list.tsx::ValidationList</code></pre>
@@ -6412,420 +7534,11 @@ value: string</code></pre>
6412
7534
  </div>
6413
7535
  </div>
6414
7536
 
6415
- </div>
6416
- </article>
6417
- </div>
6418
- <div class="error-groups" role="region" aria-label="Prop type error groups">
6419
- <section class="group">
6420
- <input id="no-component-import-found-toggle" class="group-tg" type="checkbox" hidden />
6421
- <label for="no-component-import-found-toggle" class="group-header">
6422
- <span class="caret">▸</span>
6423
- <span class="group-title">No component import found</span>
6424
- <span class="group-count">1</span>
6425
- </label>
6426
- <div class="group-cards">
6427
- <article
6428
- class="card
6429
- has-error
6430
- has-info
6431
- no-story-error
6432
- no-doc-error"
6433
- role="listitem"
6434
- aria-label="Tabs.Root">
6435
- <div class="head">
6436
- <div class="title">
6437
- <h2><span class="status-dot dot-err"></span> Tabs.Root</h2>
6438
- <div class="badges">
6439
- <label for="c-error-0-components-tabs-err" class="badge err as-toggle">prop type error</label>
6440
- <label for="c-error-0-components-tabs-info" class="badge info as-toggle">1 info</label>
6441
- <label for="c-error-0-components-tabs-stories" class="badge ok as-toggle">8 stories</label>
6442
-
6443
- </div>
6444
- </div>
6445
- <div class="meta" title="./src/tabs/tabs.stories.tsx">components-tabs · ./src/tabs/tabs.stories.tsx</div>
6446
-
6447
-
6448
7537
 
6449
7538
  </div>
6450
-
6451
- <!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
6452
- <input id="c-error-0-components-tabs-err" class="tg tg-err" type="checkbox" hidden />
6453
- <input id="c-error-0-components-tabs-info" class="tg tg-info" type="checkbox" hidden />
6454
- <input id="c-error-0-components-tabs-stories" class="tg tg-stories" type="checkbox" hidden />
6455
-
6456
-
6457
-
6458
- <div class="panels">
6459
-
6460
- <div class="panel panel-err">
6461
-
6462
- <div class="note err">
6463
- <div class="note-title">Prop type error</div>
6464
- <div class="note-body"><pre><code>No component file found for the &quot;Tabs.Root&quot; component.
6465
- 4 | import { Tabs } from &#39;.&#39;;
6466
- 5 |
6467
- &gt; 6 | const meta = {
6468
- | ^
6469
- 7 | title: &#39;Components/Tabs&#39;,
6470
- 8 | component: Tabs.Root,
6471
- 9 | tags: [&#39;autodocs&#39;]
6472
-
6473
- ./src/tabs/tabs.stories.tsx:
6474
- import type { Meta, StoryObj } from &#39;@storybook/react-vite&#39;;
6475
- import { expect, userEvent, within } from &#39;storybook/test&#39;;
6476
-
6477
- import { Tabs } from &#39;.&#39;;
6478
-
6479
- const meta = {
6480
- title: &#39;Components/Tabs&#39;,
6481
- component: Tabs.Root,
6482
- tags: [&#39;autodocs&#39;]
6483
- } satisfies Meta&lt;typeof Tabs.Root&gt;;
6484
-
6485
- export default meta;
6486
-
6487
- type Story = StoryObj&lt;typeof meta&gt;;
6488
-
6489
- const TABS = [
6490
- { value: &#39;overview&#39;, label: &#39;Overview&#39;, body: &#39;A summary of the policy and its coverage.&#39; },
6491
- { value: &#39;documents&#39;, label: &#39;Documents&#39;, body: &#39;Declarations, endorsements and forms.&#39; },
6492
- { value: &#39;activity&#39;, label: &#39;Activity&#39;, body: &#39;A timeline of recent changes and events.&#39; }
6493
- ] as const;
6494
-
6495
- const TabItems = () =&gt;
6496
- TABS.map(({ value, label }) =&gt; (
6497
- &lt;Tabs.Trigger key={value} value={value}&gt;
6498
- {label}
6499
- &lt;/Tabs.Trigger&gt;
6500
- ));
6501
-
6502
- const TabPanels = () =&gt;
6503
- TABS.map(({ value, body }) =&gt; (
6504
- &lt;Tabs.Content key={value} value={value} className=&quot;p-4 text-sm text-text-default-base-primary&quot;&gt;
6505
- {body}
6506
- &lt;/Tabs.Content&gt;
6507
- ));
6508
-
6509
- /** `line` (default): the active tab is marked with an animated underline. */
6510
- export const Default: Story = {
6511
- args: {
6512
- variant: &#39;line&#39;,
6513
- defaultValue: &#39;overview&#39;
6514
- },
6515
- argTypes: {
6516
- variant: {
6517
- control: &#39;radio&#39;,
6518
- options: [&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;],
6519
- description: &#39;line = underline; enclosed = segmented pills; button = button-like tabs&#39;
6520
- }
6521
- },
6522
- render: args =&gt; (
6523
- &lt;Tabs.Root {...args}&gt;
6524
- &lt;Tabs.List&gt;
6525
- &lt;TabItems /&gt;
6526
- &lt;/Tabs.List&gt;
6527
- &lt;TabPanels /&gt;
6528
- &lt;/Tabs.Root&gt;
6529
- )
6530
- };
6531
-
6532
- /** `enclosed` renders segmented pills; the active tab sits on a raised surface. */
6533
- export const Enclosed: Story = {
6534
- render: () =&gt; (
6535
- &lt;Tabs.Root variant=&quot;enclosed&quot; defaultValue=&quot;overview&quot;&gt;
6536
- &lt;Tabs.List&gt;
6537
- &lt;TabItems /&gt;
6538
- &lt;/Tabs.List&gt;
6539
- &lt;TabPanels /&gt;
6540
- &lt;/Tabs.Root&gt;
6541
- )
6542
- };
6543
-
6544
- /** `button` renders button-like tabs, with room for a leading icon per trigger. */
6545
- export const Buttons: Story = {
6546
- render: () =&gt; (
6547
- &lt;Tabs.Root variant=&quot;button&quot; defaultValue=&quot;overview&quot;&gt;
6548
- &lt;Tabs.List&gt;
6549
- &lt;TabItems /&gt;
6550
- &lt;/Tabs.List&gt;
6551
- &lt;TabPanels /&gt;
6552
- &lt;/Tabs.Root&gt;
6553
- )
6554
- };
6555
-
6556
- /** `position` aligns the tab list within the row (`start` is the default). */
6557
- export const Positions: Story = {
6558
- render: () =&gt; (
6559
- &lt;div className=&quot;flex flex-col gap-8&quot;&gt;
6560
- {([&#39;start&#39;, &#39;center&#39;, &#39;end&#39;] as const).map(position =&gt; (
6561
- &lt;Tabs.Root key={position} variant=&quot;enclosed&quot; position={position} defaultValue=&quot;overview&quot;&gt;
6562
- &lt;Tabs.List&gt;
6563
- &lt;TabItems /&gt;
6564
- &lt;/Tabs.List&gt;
6565
- &lt;TabPanels /&gt;
6566
- &lt;/Tabs.Root&gt;
6567
- ))}
6568
- &lt;/div&gt;
6569
- )
6570
- };
6571
-
6572
- /** `position=&quot;full&quot;` stretches the tab list to fill the available width. */
6573
- export const FullWidth: Story = {
6574
- render: () =&gt; (
6575
- &lt;Tabs.Root variant=&quot;enclosed&quot; position=&quot;full&quot; defaultValue=&quot;overview&quot;&gt;
6576
- &lt;Tabs.List&gt;
6577
- &lt;TabItems /&gt;
6578
- &lt;/Tabs.List&gt;
6579
- &lt;TabPanels /&gt;
6580
- &lt;/Tabs.Root&gt;
6581
- )
6582
- };
6583
-
6584
- /**
6585
- * Triggers accept `asChild` to render as another element — e.g. a router link.
6586
- * The trigger resets the anchor&#39;s default underline, so link-based tabs match
6587
- * the button-based ones.
6588
- */
6589
- export const AsChildLinks: Story = {
6590
- render: () =&gt; (
6591
- &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
6592
- &lt;Tabs.List&gt;
6593
- {TABS.map(({ value, label }) =&gt; (
6594
- &lt;Tabs.Trigger key={value} value={value} asChild&gt;
6595
- &lt;a href={`#${value}`}&gt;{label}&lt;/a&gt;
6596
- &lt;/Tabs.Trigger&gt;
6597
- ))}
6598
- &lt;/Tabs.List&gt;
6599
- &lt;TabPanels /&gt;
6600
- &lt;/Tabs.Root&gt;
6601
- ),
6602
- play: async ({ canvasElement }) =&gt; {
6603
- const canvas = within(canvasElement);
6604
- const overview = canvas.getByRole(&#39;tab&#39;, { name: /overview/i });
6605
-
6606
- await expect(overview.tagName).toBe(&#39;A&#39;);
6607
- await expect(getComputedStyle(overview).textDecorationLine).toBe(&#39;none&#39;);
6608
- }
6609
- };
6610
-
6611
- /** Selecting a tab reveals its panel and hides the others. */
6612
- export const SwitchTabs: Story = {
6613
- args: {
6614
- variant: &#39;line&#39;,
6615
- defaultValue: &#39;overview&#39;
6616
- },
6617
- render: args =&gt; (
6618
- &lt;Tabs.Root {...args}&gt;
6619
- &lt;Tabs.List&gt;
6620
- &lt;TabItems /&gt;
6621
- &lt;/Tabs.List&gt;
6622
- &lt;TabPanels /&gt;
6623
- &lt;/Tabs.Root&gt;
6624
- ),
6625
- play: async ({ canvasElement }) =&gt; {
6626
- const canvas = within(canvasElement);
6627
- const overview = canvas.getByRole(&#39;tab&#39;, { name: /overview/i });
6628
- const documents = canvas.getByRole(&#39;tab&#39;, { name: /documents/i });
6629
-
6630
- await expect(overview).toHaveAttribute(&#39;data-state&#39;, &#39;active&#39;);
6631
- await expect(await canvas.findByText(/summary of the policy/i)).toBeVisible();
6632
-
6633
- await userEvent.click(documents);
6634
- await expect(documents).toHaveAttribute(&#39;data-state&#39;, &#39;active&#39;);
6635
- await expect(overview).toHaveAttribute(&#39;data-state&#39;, &#39;inactive&#39;);
6636
- await expect(await canvas.findByText(/declarations, endorsements/i)).toBeVisible();
6637
- }
6638
- };
6639
-
6640
- /**
6641
- * A standalone `Label` gives a panel with a single, non-interactive title the
6642
- * inactive trigger&#39;s exact look: outside a `Root` it never gets the active
6643
- * data-state, and `pointer-events-none` keeps hover styles off. It is a plain
6644
- * `span`, so wrap it in a heading element for heading semantics. No tab or
6645
- * tablist role is announced.
6646
- */
6647
- export const SingleTitle: Story = {
6648
- render: () =&gt; (
6649
- &lt;div className=&quot;flex flex-col items-start gap-6&quot;&gt;
6650
- {([&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;] as const).map(variant =&gt; (
6651
- &lt;h2 key={variant}&gt;
6652
- &lt;Tabs.Label variant={variant}&gt;Shared coverages ({variant})&lt;/Tabs.Label&gt;
6653
- &lt;/h2&gt;
6654
- ))}
6655
- &lt;/div&gt;
6656
- ),
6657
- play: async ({ canvasElement }) =&gt; {
6658
- const canvas = within(canvasElement);
6659
-
6660
- await expect(canvas.getAllByRole(&#39;heading&#39;)).toHaveLength(3);
6661
- await expect(canvas.queryByRole(&#39;tablist&#39;)).not.toBeInTheDocument();
6662
- await expect(canvas.queryByRole(&#39;tab&#39;)).not.toBeInTheDocument();
6663
- }
6664
- };
6665
- </code></pre></div>
6666
- </div>
6667
- </div>
6668
-
6669
- <div class="panel panel-info">
6670
-
6671
- <div class="note info">
6672
- <div class="note-title">Info</div>
6673
- <div class="note-body">No description found. Write a jsdoc comment such as /** Component description */.</div>
7539
+ </article>
6674
7540
  </div>
6675
- </div>
6676
-
6677
-
6678
- <div class="panel panel-stories">
6679
-
6680
-
6681
-
6682
- <div class="note ok">
6683
- <div class="row">
6684
- <span class="ex-name">Imports</span>
6685
- </div>
6686
- <pre><code>import { Tabs } from "@agentero/design-system";</code></pre>
6687
- </div>
6688
-
6689
-
6690
- <div class="note ok">
6691
- <div class="row">
6692
- <span class="ex-name">Default</span>
6693
- <span class="badge ok">story ok</span>
6694
- </div>
6695
-
6696
- <div class="hint">`line` (default): the active tab is marked with an animated underline.</div>
6697
- <pre><code>const Default = () =&gt; &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
6698
- &lt;Tabs.List&gt;
6699
- &lt;TabItems /&gt;
6700
- &lt;/Tabs.List&gt;
6701
- &lt;TabPanels /&gt;
6702
- &lt;/Tabs.Root&gt;;</code></pre>
6703
- </div>
6704
- <div class="note ok">
6705
- <div class="row">
6706
- <span class="ex-name">Enclosed</span>
6707
- <span class="badge ok">story ok</span>
6708
- </div>
6709
-
6710
- <div class="hint">`enclosed` renders segmented pills; the active tab sits on a raised surface.</div>
6711
- <pre><code>const Enclosed = () =&gt; (
6712
- &lt;Tabs.Root variant=&quot;enclosed&quot; defaultValue=&quot;overview&quot;&gt;
6713
- &lt;Tabs.List&gt;
6714
- &lt;TabItems /&gt;
6715
- &lt;/Tabs.List&gt;
6716
- &lt;TabPanels /&gt;
6717
- &lt;/Tabs.Root&gt;
6718
- );</code></pre>
6719
- </div>
6720
- <div class="note ok">
6721
- <div class="row">
6722
- <span class="ex-name">Buttons</span>
6723
- <span class="badge ok">story ok</span>
6724
- </div>
6725
-
6726
- <div class="hint">`button` renders button-like tabs, with room for a leading icon per trigger.</div>
6727
- <pre><code>const Buttons = () =&gt; (
6728
- &lt;Tabs.Root variant=&quot;button&quot; defaultValue=&quot;overview&quot;&gt;
6729
- &lt;Tabs.List&gt;
6730
- &lt;TabItems /&gt;
6731
- &lt;/Tabs.List&gt;
6732
- &lt;TabPanels /&gt;
6733
- &lt;/Tabs.Root&gt;
6734
- );</code></pre>
6735
- </div>
6736
- <div class="note ok">
6737
- <div class="row">
6738
- <span class="ex-name">Positions</span>
6739
- <span class="badge ok">story ok</span>
6740
- </div>
6741
-
6742
- <div class="hint">`position` aligns the tab list within the row (`start` is the default).</div>
6743
- <pre><code>const Positions = () =&gt; (
6744
- &lt;div className=&quot;flex flex-col gap-8&quot;&gt;
6745
- {([&#39;start&#39;, &#39;center&#39;, &#39;end&#39;] as const).map(position =&gt; (
6746
- &lt;Tabs.Root key={position} variant=&quot;enclosed&quot; position={position} defaultValue=&quot;overview&quot;&gt;
6747
- &lt;Tabs.List&gt;
6748
- &lt;TabItems /&gt;
6749
- &lt;/Tabs.List&gt;
6750
- &lt;TabPanels /&gt;
6751
- &lt;/Tabs.Root&gt;
6752
- ))}
6753
- &lt;/div&gt;
6754
- );</code></pre>
6755
- </div>
6756
- <div class="note ok">
6757
- <div class="row">
6758
- <span class="ex-name">Full Width</span>
6759
- <span class="badge ok">story ok</span>
6760
- </div>
6761
-
6762
- <div class="hint">`position=&quot;full&quot;` stretches the tab list to fill the available width.</div>
6763
- <pre><code>const FullWidth = () =&gt; (
6764
- &lt;Tabs.Root variant=&quot;enclosed&quot; position=&quot;full&quot; defaultValue=&quot;overview&quot;&gt;
6765
- &lt;Tabs.List&gt;
6766
- &lt;TabItems /&gt;
6767
- &lt;/Tabs.List&gt;
6768
- &lt;TabPanels /&gt;
6769
- &lt;/Tabs.Root&gt;
6770
- );</code></pre>
6771
- </div>
6772
- <div class="note ok">
6773
- <div class="row">
6774
- <span class="ex-name">As Child Links</span>
6775
- <span class="badge ok">story ok</span>
6776
- </div>
6777
-
6778
- <div class="hint">Triggers accept `asChild` to render as another element — e.g. a router link. The trigger resets the anchor&#39;s default underline, so link-based tabs match the button-based ones.</div>
6779
- <pre><code>const AsChildLinks = () =&gt; (
6780
- &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
6781
- &lt;Tabs.List&gt;
6782
- {TABS.map(({ value, label }) =&gt; (
6783
- &lt;Tabs.Trigger key={value} value={value} asChild&gt;
6784
- &lt;a href={`#${value}`}&gt;{label}&lt;/a&gt;
6785
- &lt;/Tabs.Trigger&gt;
6786
- ))}
6787
- &lt;/Tabs.List&gt;
6788
- &lt;TabPanels /&gt;
6789
- &lt;/Tabs.Root&gt;
6790
- );</code></pre>
6791
- </div>
6792
- <div class="note ok">
6793
- <div class="row">
6794
- <span class="ex-name">Switch Tabs</span>
6795
- <span class="badge ok">story ok</span>
6796
- </div>
6797
-
6798
- <div class="hint">Selecting a tab reveals its panel and hides the others.</div>
6799
- <pre><code>const SwitchTabs = () =&gt; &lt;Tabs.Root variant=&quot;line&quot; defaultValue=&quot;overview&quot;&gt;
6800
- &lt;Tabs.List&gt;
6801
- &lt;TabItems /&gt;
6802
- &lt;/Tabs.List&gt;
6803
- &lt;TabPanels /&gt;
6804
- &lt;/Tabs.Root&gt;;</code></pre>
6805
- </div>
6806
- <div class="note ok">
6807
- <div class="row">
6808
- <span class="ex-name">Single Title</span>
6809
- <span class="badge ok">story ok</span>
6810
- </div>
6811
-
6812
- <div class="hint">A standalone `Label` gives a panel with a single, non-interactive title the inactive trigger&#39;s exact look: outside a `Root` it never gets the active data-state, and `pointer-events-none` keeps hover styles off. It is a plain `span`, so wrap it in a heading element for heading semantics. No tab or tablist role is announced.</div>
6813
- <pre><code>const SingleTitle = () =&gt; (
6814
- &lt;div className=&quot;flex flex-col items-start gap-6&quot;&gt;
6815
- {([&#39;line&#39;, &#39;enclosed&#39;, &#39;button&#39;] as const).map(variant =&gt; (
6816
- &lt;h2 key={variant}&gt;
6817
- &lt;Tabs.Label variant={variant}&gt;Shared coverages ({variant})&lt;/Tabs.Label&gt;
6818
- &lt;/h2&gt;
6819
- ))}
6820
- &lt;/div&gt;
6821
- );</code></pre>
6822
- </div>
6823
- </div>
6824
7541
 
6825
- </div>
6826
- </article></div>
6827
- </section>
6828
- </div>
6829
7542
 
6830
7543
 
6831
7544
  </div>