@viraui/react 2026.6.0 → 2026.6.2

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 (168) hide show
  1. package/dist/catalog.json +5 -5
  2. package/dist/components/radio/radio-group.d.ts +1 -1
  3. package/dist/components/stack/stack.d.ts +4 -1
  4. package/dist/components/tabs/tabs.css +1 -1
  5. package/dist/components/text/text.css +1 -1
  6. package/dist/components/text/text.d.ts +12 -2
  7. package/dist/components/text/text.js +2 -1
  8. package/dist/components/textfield/textfield.d.ts +1 -0
  9. package/dist/components/title/title.css +1 -1
  10. package/dist/components/title/title.d.ts +12 -2
  11. package/dist/components/title/title.js +2 -1
  12. package/dist/specs/PROTOCOL.md +1 -1
  13. package/dist/specs/activity-hints.xml +18 -3
  14. package/dist/specs/components/accordion/patterns.xml +69 -5
  15. package/dist/specs/components/accordion/props.xml +4 -4
  16. package/dist/specs/components/accordion/usage.xml +8 -4
  17. package/dist/specs/components/annotate/patterns.xml +50 -3
  18. package/dist/specs/components/annotate/props.xml +22 -22
  19. package/dist/specs/components/annotate/usage.xml +7 -6
  20. package/dist/specs/components/autocomplete/patterns.xml +123 -7
  21. package/dist/specs/components/autocomplete/props.xml +14 -14
  22. package/dist/specs/components/autocomplete/usage.xml +11 -6
  23. package/dist/specs/components/avatar/patterns.xml +78 -3
  24. package/dist/specs/components/avatar/props.xml +8 -8
  25. package/dist/specs/components/avatar/usage.xml +9 -3
  26. package/dist/specs/components/avatar-group/patterns.xml +65 -3
  27. package/dist/specs/components/avatar-group/props.xml +8 -8
  28. package/dist/specs/components/avatar-group/usage.xml +10 -7
  29. package/dist/specs/components/badge/patterns.xml +57 -3
  30. package/dist/specs/components/badge/props.xml +8 -8
  31. package/dist/specs/components/badge/usage.xml +5 -3
  32. package/dist/specs/components/beam/meta.xml +1 -1
  33. package/dist/specs/components/beam/patterns.xml +68 -3
  34. package/dist/specs/components/beam/props.xml +22 -22
  35. package/dist/specs/components/beam/usage.xml +7 -7
  36. package/dist/specs/components/bleed/patterns.xml +54 -3
  37. package/dist/specs/components/bleed/props.xml +2 -2
  38. package/dist/specs/components/bleed/usage.xml +6 -3
  39. package/dist/specs/components/breakpoints/meta.xml +1 -1
  40. package/dist/specs/components/breakpoints/patterns.xml +1 -6
  41. package/dist/specs/components/breakpoints/props.xml +4 -2
  42. package/dist/specs/components/breakpoints/usage.xml +10 -2
  43. package/dist/specs/components/button/patterns.xml +124 -6
  44. package/dist/specs/components/button/props.xml +33 -32
  45. package/dist/specs/components/button/usage.xml +13 -13
  46. package/dist/specs/components/checkbox/patterns.xml +83 -3
  47. package/dist/specs/components/checkbox/props.xml +10 -10
  48. package/dist/specs/components/checkbox/usage.xml +11 -6
  49. package/dist/specs/components/chip/patterns.xml +74 -3
  50. package/dist/specs/components/chip/props.xml +14 -14
  51. package/dist/specs/components/chip/usage.xml +10 -6
  52. package/dist/specs/components/clamp-text/patterns.xml +1 -4
  53. package/dist/specs/components/clamp-text/props.xml +2 -2
  54. package/dist/specs/components/clamp-text/usage.xml +8 -5
  55. package/dist/specs/components/dialog/patterns.xml +136 -15
  56. package/dist/specs/components/dialog/props.xml +2 -2
  57. package/dist/specs/components/dialog/usage.xml +9 -7
  58. package/dist/specs/components/elevator/patterns.xml +54 -3
  59. package/dist/specs/components/elevator/usage.xml +8 -5
  60. package/dist/specs/components/fieldset/patterns.xml +97 -3
  61. package/dist/specs/components/fieldset/usage.xml +7 -5
  62. package/dist/specs/components/fit-text/patterns.xml +1 -4
  63. package/dist/specs/components/fit-text/props.xml +2 -2
  64. package/dist/specs/components/fit-text/usage.xml +8 -6
  65. package/dist/specs/components/glow/meta.xml +1 -1
  66. package/dist/specs/components/glow/patterns.xml +74 -3
  67. package/dist/specs/components/glow/props.xml +16 -16
  68. package/dist/specs/components/glow/usage.xml +8 -7
  69. package/dist/specs/components/grid/patterns.xml +88 -5
  70. package/dist/specs/components/grid/props.xml +23 -23
  71. package/dist/specs/components/grid/usage.xml +9 -5
  72. package/dist/specs/components/icon-button/patterns.xml +97 -6
  73. package/dist/specs/components/icon-button/props.xml +32 -32
  74. package/dist/specs/components/icon-button/usage.xml +11 -9
  75. package/dist/specs/components/linear-progress/patterns.xml +58 -3
  76. package/dist/specs/components/linear-progress/props.xml +6 -6
  77. package/dist/specs/components/linear-progress/usage.xml +9 -8
  78. package/dist/specs/components/masonry/patterns.xml +68 -5
  79. package/dist/specs/components/masonry/props.xml +2 -2
  80. package/dist/specs/components/masonry/usage.xml +9 -4
  81. package/dist/specs/components/menu/patterns.xml +179 -15
  82. package/dist/specs/components/menu/usage.xml +8 -7
  83. package/dist/specs/components/meter/patterns.xml +49 -3
  84. package/dist/specs/components/meter/props.xml +6 -6
  85. package/dist/specs/components/meter/usage.xml +10 -7
  86. package/dist/specs/components/popover/patterns.xml +118 -9
  87. package/dist/specs/components/popover/props.xml +2 -2
  88. package/dist/specs/components/popover/usage.xml +9 -8
  89. package/dist/specs/components/progressive-blur/meta.xml +1 -1
  90. package/dist/specs/components/progressive-blur/patterns.xml +1 -4
  91. package/dist/specs/components/progressive-blur/props.xml +2 -2
  92. package/dist/specs/components/progressive-blur/usage.xml +7 -6
  93. package/dist/specs/components/radio/patterns.xml +55 -5
  94. package/dist/specs/components/radio/props.xml +8 -8
  95. package/dist/specs/components/radio/usage.xml +9 -6
  96. package/dist/specs/components/select/patterns.xml +124 -8
  97. package/dist/specs/components/select/props.xml +18 -18
  98. package/dist/specs/components/select/usage.xml +11 -10
  99. package/dist/specs/components/separator/patterns.xml +121 -3
  100. package/dist/specs/components/separator/props.xml +4 -4
  101. package/dist/specs/components/separator/usage.xml +8 -5
  102. package/dist/specs/components/shimmer/patterns.xml +23 -3
  103. package/dist/specs/components/shimmer/props.xml +8 -8
  104. package/dist/specs/components/shimmer/usage.xml +7 -5
  105. package/dist/specs/components/skeleton/patterns.xml +172 -4
  106. package/dist/specs/components/skeleton/props.xml +14 -14
  107. package/dist/specs/components/skeleton/usage.xml +11 -7
  108. package/dist/specs/components/slider/patterns.xml +111 -3
  109. package/dist/specs/components/slider/props.xml +10 -10
  110. package/dist/specs/components/slider/usage.xml +11 -5
  111. package/dist/specs/components/spinner/patterns.xml +35 -3
  112. package/dist/specs/components/spinner/props.xml +2 -2
  113. package/dist/specs/components/spinner/usage.xml +8 -5
  114. package/dist/specs/components/stack/patterns.xml +359 -3
  115. package/dist/specs/components/stack/props.xml +24 -22
  116. package/dist/specs/components/stack/usage.xml +16 -10
  117. package/dist/specs/components/static-noise/meta.xml +1 -1
  118. package/dist/specs/components/static-noise/patterns.xml +20 -3
  119. package/dist/specs/components/static-noise/usage.xml +5 -5
  120. package/dist/specs/components/surface/patterns.xml +188 -3
  121. package/dist/specs/components/surface/props.xml +26 -26
  122. package/dist/specs/components/surface/usage.xml +15 -12
  123. package/dist/specs/components/switch/patterns.xml +73 -3
  124. package/dist/specs/components/switch/props.xml +12 -12
  125. package/dist/specs/components/switch/usage.xml +10 -5
  126. package/dist/specs/components/tabs/patterns.xml +111 -6
  127. package/dist/specs/components/tabs/props.xml +2 -2
  128. package/dist/specs/components/tabs/usage.xml +7 -3
  129. package/dist/specs/components/text/patterns.xml +97 -3
  130. package/dist/specs/components/text/props.xml +48 -43
  131. package/dist/specs/components/text/usage.xml +11 -4
  132. package/dist/specs/components/textarea/patterns.xml +49 -3
  133. package/dist/specs/components/textarea/props.xml +7 -6
  134. package/dist/specs/components/textarea/usage.xml +8 -5
  135. package/dist/specs/components/textfield/patterns.xml +163 -3
  136. package/dist/specs/components/textfield/props.xml +12 -11
  137. package/dist/specs/components/textfield/usage.xml +9 -3
  138. package/dist/specs/components/title/patterns.xml +74 -3
  139. package/dist/specs/components/title/props.xml +48 -43
  140. package/dist/specs/components/title/usage.xml +10 -7
  141. package/dist/specs/components/toast/patterns.xml +85 -8
  142. package/dist/specs/components/toast/usage.xml +8 -5
  143. package/dist/specs/components/toggle-button/patterns.xml +101 -3
  144. package/dist/specs/components/toggle-button/props.xml +16 -16
  145. package/dist/specs/components/toggle-button/usage.xml +9 -5
  146. package/dist/specs/components/toggle-group/patterns.xml +34 -5
  147. package/dist/specs/components/toggle-group/usage.xml +9 -5
  148. package/dist/specs/components/tooltip/patterns.xml +110 -6
  149. package/dist/specs/components/tooltip/props.xml +2 -2
  150. package/dist/specs/components/tooltip/usage.xml +8 -5
  151. package/dist/specs/components/typewriter/patterns.xml +18 -3
  152. package/dist/specs/components/typewriter/props.xml +2 -2
  153. package/dist/specs/components/typewriter/usage.xml +9 -8
  154. package/dist/specs/foundation/attributes.xml +67 -37
  155. package/dist/specs/foundation/bootstrap.xml +6 -6
  156. package/dist/specs/foundation/elevation.xml +51 -3
  157. package/dist/specs/foundation/modules.xml +117 -40
  158. package/dist/specs/foundation/theme-topics.xml +62 -27
  159. package/dist/specs/foundation/toggles.xml +2 -2
  160. package/dist/specs/index.xml +42 -6
  161. package/dist/specs/patterns/card-grid.xml +35 -0
  162. package/dist/specs/patterns/compose-layout-first.xml +32 -0
  163. package/dist/specs/patterns/equal-width-actions.xml +22 -0
  164. package/dist/specs/patterns/page-chrome.xml +34 -0
  165. package/dist/specs/patterns/settings-panel.xml +30 -0
  166. package/dist/specs/patterns/settings-row.xml +9 -7
  167. package/dist/specs/patterns/stack-as-surface.xml +37 -0
  168. package/package.json +9 -9
@@ -1,14 +1,130 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="autocomplete">
3
- <example title="Autocomplete structure">
4
- <tsx><![CDATA[<Autocomplete>
5
- <Autocomplete.Item value="…">…</Autocomplete.Item>
6
- <Autocomplete.Group label="…" items={[…]}>
3
+ <!-- Sources: preview-grid autocomplete-search + editor font-autocomplete — cleaned (no handlers, Controllers, i18n, virtualizer CSS). Portal baked in root. -->
4
+
5
+ <example title="Teammate search with item addon">
6
+ <tsx><![CDATA[
7
+ <Autocomplete
8
+ label="Assign reviewer"
9
+ description="Pick a teammate who can approve this payout batch."
10
+ empty="No teammates match that name."
11
+ placeholder="Search by name…"
12
+ items={reviewers}
13
+ itemToStringValue={(person) => person.label}
14
+ startAddon={<Magnifier aria-hidden size={16} />}
15
+ >
16
+ {(person) => (
17
+ <Autocomplete.Item
18
+ key={person.id}
19
+ addon={<Avatar alt={person.label} fallback={person.fallback} size="s" src={person.src} />}
20
+ value={person}
21
+ >
22
+ {`${person.label} · ${person.role}`}
23
+ </Autocomplete.Item>
24
+ )}
25
+ </Autocomplete>
26
+ ]]></tsx>
27
+ <notes>From preview-grid `autocomplete-search` AssignReviewer. List render fn + `Autocomplete.Item` `addon`. Empty/status are root props — not child parts.</notes>
28
+ </example>
29
+
30
+ <example title="Free-form category suggest">
31
+ <tsx><![CDATA[
32
+ <Autocomplete
33
+ label="Expense category"
34
+ description="Suggest a ledger category — free-form text stays allowed."
35
+ empty="No category match. Keep typing to create a custom label."
36
+ placeholder="SaaS, travel, contractors…"
37
+ items={expenseCategories}
38
+ itemToStringValue={(category) => category.label}
39
+ startAddon={<Magnifier aria-hidden size={16} />}
40
+ >
41
+ {(category) => (
42
+ <Autocomplete.Item key={category.id} value={category}>
43
+ {category.label}
44
+ </Autocomplete.Item>
45
+ )}
46
+ </Autocomplete>
47
+ ]]></tsx>
48
+ <notes>From preview-grid `autocomplete-search` ExpenseCategory. Flat items; free-form input is the Autocomplete default.</notes>
49
+ </example>
50
+
51
+ <example title="Grouped desks with Collection">
52
+ <tsx><![CDATA[
53
+ <Autocomplete
54
+ label="Transfer desk"
55
+ description="Route an urgent payout to the desk covering that region."
56
+ empty="No transfer desk matches."
57
+ placeholder="Paris, Austin, Singapore…"
58
+ items={transferDesks}
59
+ itemToStringValue={(desk) => desk.label}
60
+ startAddon={<Magnifier aria-hidden size={16} />}
61
+ >
62
+ {(group) => (
63
+ <Autocomplete.Group key={group.value} items={group.items} label={group.value}>
64
+ <Autocomplete.Collection>
65
+ {(desk) => (
66
+ <Autocomplete.Item key={desk.id} value={desk}>
67
+ {`${desk.label} · ${desk.hours}`}
68
+ </Autocomplete.Item>
69
+ )}
70
+ </Autocomplete.Collection>
71
+ </Autocomplete.Group>
72
+ )}
73
+ </Autocomplete>
74
+ ]]></tsx>
75
+ <notes>From preview-grid `autocomplete-search` TransferDesk. Grouped `items` + `Autocomplete.Group` / `Collection` — public parts only.</notes>
76
+ </example>
77
+
78
+ <example title="Async status + empty">
79
+ <tsx><![CDATA[
80
+ <Autocomplete
81
+ label="Search help center"
82
+ description="Async docs search."
83
+ empty="No articles for that query."
84
+ filter={null}
85
+ items={results}
86
+ itemToStringValue={(article) => article.title}
87
+ placeholder="Wire limits, SEPA, tax forms…"
88
+ startAddon={<Magnifier aria-hidden size={16} />}
89
+ status={
90
+ <Stack columnGap="s" direction="row" vAlign="center">
91
+ <Spinner aria-hidden size="s" />
92
+ <Text size="xs" tone="muted">
93
+ Searching help center…
94
+ </Text>
95
+ </Stack>
96
+ }
97
+ >
98
+ {(article) => (
99
+ <Autocomplete.Item key={article.id} value={article}>
100
+ {`${article.title} · ${article.section}`}
101
+ </Autocomplete.Item>
102
+ )}
103
+ </Autocomplete>
104
+ ]]></tsx>
105
+ <notes>From preview-grid `autocomplete-search` HelpCenter. Keep `status` mounted; update children when pending/error. `filter={null}` when filtering outside.</notes>
106
+ </example>
107
+
108
+ <example title="Suggested fonts Group">
109
+ <tsx><![CDATA[
110
+ <Autocomplete
111
+ label="Heading font"
112
+ empty="No fonts match."
113
+ items={suggested}
114
+ itemToStringValue={(font) => font.family}
115
+ openOnInputClick
116
+ >
117
+ <Autocomplete.Group label="Suggested" items={suggested}>
7
118
  <Autocomplete.Collection>
8
- {(item) => <Autocomplete.Item value={item}>…</Autocomplete.Item>}
119
+ {(font) => (
120
+ <Autocomplete.Item key={font.id} value={font}>
121
+ {font.family}
122
+ </Autocomplete.Item>
123
+ )}
9
124
  </Autocomplete.Collection>
10
125
  </Autocomplete.Group>
11
- </Autocomplete>]]></tsx>
12
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
126
+ </Autocomplete>
127
+ ]]></tsx>
128
+ <notes>From `editor/controls/font-picker/font-autocomplete` browse mode. Suggested group via `Group` + `Collection`; drop virtualizer / preview dwell from the hint.</notes>
13
129
  </example>
14
130
  </patterns>
@@ -57,25 +57,25 @@
57
57
  <prop name="status" kind="react">
58
58
  <description>Content rendered inside baked `Autocomplete.Status` (async / limit messaging). Keep the slot mounted; update children when status changes.</description>
59
59
  </prop>
60
- <css_var suffix="control-group-background">
60
+ <prop name="control-group-background" kind="css">
61
61
  <description>Autocomplete control group background.</description>
62
- </css_var>
63
- <css_var suffix="control-group-border-color">
62
+ </prop>
63
+ <prop name="control-group-border-color" kind="css">
64
64
  <description>Autocomplete control group border color; invalid state overrides.</description>
65
- </css_var>
66
- <css_var suffix="control-group-border-radius">
65
+ </prop>
66
+ <prop name="control-group-border-radius" kind="css">
67
67
  <description>Autocomplete control group corner radius.</description>
68
- </css_var>
69
- <css_var suffix="control-group-color">
68
+ </prop>
69
+ <prop name="control-group-color" kind="css">
70
70
  <description>Autocomplete control group foreground color.</description>
71
- </css_var>
72
- <css_var suffix="input-height">
71
+ </prop>
72
+ <prop name="input-height" kind="css">
73
73
  <description>Autocomplete control group block size.</description>
74
- </css_var>
75
- <css_var suffix="list-border-radius">
74
+ </prop>
75
+ <prop name="list-border-radius" kind="css">
76
76
  <description>Popup list border radius custom property on the popup root.</description>
77
- </css_var>
78
- <css_var suffix="list-padding">
77
+ </prop>
78
+ <prop name="list-padding" kind="css">
79
79
  <description>Popup list padding custom property used for scroll padding.</description>
80
- </css_var>
80
+ </prop>
81
81
  </props>
@@ -1,11 +1,16 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="autocomplete">
3
3
  <do>Suggest options while allowing free-form text in the input</do>
4
- <do>Filterable tag, movie, or docs search with optional empty and status copy</do>
5
- <do>Grouped suggestion lists via Autocomplete.Group and Collection</do>
6
- <do>Async or limited result lists that need polite status announcements</do>
4
+ <do>Prefer Autocomplete over Select when users may type a value not in the list (tags, categories, search)</do>
5
+ <do>Form section: Fieldset legend + Autocomplete with sibling Textfield/Select when they share one section — Stack owns gap</do>
6
+ <do>Fill a form column via a parent Stack `fullWidth` / `expandChildren` (Autocomplete has no `fullWidth` prop) — not CSS `width: 100%`</do>
7
+ <do>`startAddon` / `endAddon` for leading/trailing chrome (same control-group pattern as Textfield) — IconButton/Button addons use `size=&quot;s&quot;` and `type=&quot;button&quot;`</do>
8
+ <do>Grouped suggestion lists via `Autocomplete.Group` + `Autocomplete.Collection`; item rows via `Autocomplete.Item` `addon` (e.g. Avatar)</do>
9
+ <do>Async or limited result lists: pass `empty` for no-match copy; keep root `status` mounted and update its children — Spinner + Text inside `status` is fine</do>
7
10
  <do>Custom portal host (iframe preview, shadow root, or app overlay root) via `container` on the portal-owning public part</do>
8
- <dont>Expecting Select-like closed selection state</dont>
9
- <dont>Leaving the input without label or aria-label</dont>
10
- <dont>Conditionally unmounting Empty or Status instead of updating their children</dont>
11
+ <dont>Expecting Select-like closed selection from a fixed list — use Select when the value must be one of the options</dont>
12
+ <dont>Leaving the input without `label` or `aria-label`</dont>
13
+ <dont>Conditionally dropping the `status` prop instead of updating its children — baked Status stays mounted</dont>
14
+ <dont>Inventing `width: 100%` / `w-full` CSS on Autocomplete when a parent Stack can own the fill</dont>
15
+ <dont>Wrapping a lone Autocomplete in Fieldset when its own label is enough</dont>
11
16
  </usage>
@@ -1,7 +1,82 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="avatar">
3
- <example title="Avatar structure">
4
- <tsx><![CDATA[<Avatar fallback="AB" />]]></tsx>
5
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
3
+ <!-- Sources: viraui-app/components — cleaned (no handlers, no portal chrome, no app-only state). -->
4
+
5
+ <example title="Autocomplete item addon">
6
+ <tsx><![CDATA[
7
+ <Autocomplete
8
+ empty="No teammates match that name."
9
+ itemToStringValue={(person) => person.label}
10
+ items={reviewers}
11
+ label="Assign reviewer"
12
+ placeholder="Search by name…"
13
+ >
14
+ {(person) => (
15
+ <Autocomplete.Item
16
+ key={person.id}
17
+ addon={<Avatar alt={person.label} fallback={person.fallback} size="s" src={person.src} />}
18
+ value={person}
19
+ >
20
+ {`${person.label} · ${person.role}`}
21
+ </Autocomplete.Item>
22
+ )}
23
+ </Autocomplete>
24
+ ]]></tsx>
25
+ <notes>From `editor/preview-grid/blocks/autocomplete-search` AssignReviewerField. Small Avatar as Autocomplete.Item `addon`. Drop portal props and controlled value handlers.</notes>
26
+ </example>
27
+
28
+ <example title="Account menu profile row">
29
+ <tsx><![CDATA[
30
+ <Stack columnGap="s" direction="row" vAlign="center">
31
+ <Avatar alt="Maya Chen" fallback="MC" size="s" src="https://example.com/maya.jpg" />
32
+ <Stack rowGap="s">
33
+ <Text weight="semibold">Maya Chen</Text>
34
+ <Text size="s" tone="muted">
35
+ maya@ledger.io
36
+ </Text>
37
+ </Stack>
38
+ </Stack>
39
+ ]]></tsx>
40
+ <notes>From `editor/preview-grid/blocks/menu-account` ProfileSummary. Compact row: Avatar + name/email column. Use `size="m"` in the open menu header copy of the same cluster.</notes>
41
+ </example>
42
+
43
+ <example title="Directory list row">
44
+ <tsx><![CDATA[
45
+ <Surface color={2} radius="m" hPadding="m" vPadding="m">
46
+ <Stack columnGap="m" direction="row" hAlign="space-between" vAlign="center">
47
+ <Stack columnGap="m" direction="row" vAlign="center">
48
+ <Avatar alt="Sarah Chen" fallback="SC" size="s" src="https://example.com/sarah.jpg" />
49
+ <Stack rowGap="xs">
50
+ <Text weight="semibold">Sarah Chen</Text>
51
+ <Text size="s" tone="muted">
52
+ Product Design
53
+ </Text>
54
+ </Stack>
55
+ </Stack>
56
+ <Button size="s" variant="secondary">
57
+ Details
58
+ </Button>
59
+ </Stack>
60
+ </Surface>
61
+ ]]></tsx>
62
+ <notes>From `editor/preview-grid/blocks/team-directory` row. Leading Avatar + text column + trailing action. Drop Popover/Badge/Tooltip kitchen chrome from this hint.</notes>
63
+ </example>
64
+
65
+ <example title="Profile sheet hero">
66
+ <tsx><![CDATA[
67
+ <Stack rowGap="m" hAlign="center">
68
+ <Avatar alt="Sarah Chen" fallback="SC" size="l" src="https://example.com/sarah.jpg" />
69
+ <Text align="center" render={<p />} tone="muted" size="s" lineHeight="s" maxWidth="25ch">
70
+ Leads design systems and interaction patterns across the portfolio experience.
71
+ </Text>
72
+ <Text align="center" family="mono" size="s">
73
+ sarah@ledger.io
74
+ </Text>
75
+ <Button size="s" variant="secondary">
76
+ View profile
77
+ </Button>
78
+ </Stack>
79
+ ]]></tsx>
80
+ <notes>From `editor/preview-grid/blocks/team-directory` Popover.Sheet body. Large Avatar as profile hero. Drop shared Popover handle / portal wiring.</notes>
6
81
  </example>
7
82
  </patterns>
@@ -23,16 +23,16 @@
23
23
  <prop name="src" kind="react">
24
24
  <description>Supplies the avatar image source URL.</description>
25
25
  </prop>
26
- <css_var suffix="background">
26
+ <prop name="background" kind="css">
27
27
  <description>Root background fill behind image or fallback.</description>
28
- </css_var>
29
- <css_var suffix="foreground">
28
+ </prop>
29
+ <prop name="foreground" kind="css">
30
30
  <description>Root foreground color for fallback content.</description>
31
- </css_var>
32
- <css_var suffix="radius">
31
+ </prop>
32
+ <prop name="radius" kind="css">
33
33
  <description>Corner radius on the root; size presets also adjust this.</description>
34
- </css_var>
35
- <css_var suffix="size">
34
+ </prop>
35
+ <prop name="size" kind="css">
36
36
  <description>Avatar inline and block size on the root.</description>
37
- </css_var>
37
+ </prop>
38
38
  </props>
@@ -1,7 +1,13 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="avatar">
3
- <do>Show a user or entity photo with text or image fallback</do>
4
- <do>Display profile chips from xs through large sizes</do>
3
+ <do>Show a user or entity photo with `src`, `alt`, and `fallback` (initials or icon)</do>
4
+ <do>Pick footprint with `size` (`xs`–`l`) — not child layout or custom width CSS</do>
5
+ <do>Profile row: Stack row + Avatar + Text column (name / muted email)</do>
6
+ <do>Account menu: Avatar inside `Menu.Trigger` chip (Stack/button + Text); wrap Menu in Surface for chrome — Menu owns popup, do not nest in Popover</do>
7
+ <do>Presence: wrap Avatar in Badge with `show` + `color`; keep name/role in nearby Text</do>
8
+ <do>List pickers: small Avatar as Autocomplete.Item / Select option `addon`</do>
9
+ <do>Directory / sheet hero: Avatar + Text (+ Button) inside Surface or Stack — size `l` for hero, `s` for rows</do>
10
+ <dont>Treating Avatar as a control — put Menu, Popover, or Button around it when the row is interactive</dont>
11
+ <dont>Omitting meaningful `alt` when the image conveys identity</dont>
5
12
  <dont>Relying on Avatar children for layout sizing</dont>
6
- <dont>Omitting meaningful alt text when the image conveys identity</dont>
7
13
  </usage>
@@ -1,7 +1,69 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="avatar-group">
3
- <example title="AvatarGroup structure">
4
- <tsx><![CDATA[<AvatarGroup avatars={[{ fallback: "AB" }]} />]]></tsx>
5
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
3
+ <!-- Sources: viraui-app/components — cleaned (no handlers, no kitchen Annotate/Badge chrome). -->
4
+
5
+ <example title="Contributors with overflow">
6
+ <tsx><![CDATA[
7
+ <Surface overflow="hidden" border="all" color={1} radius="l">
8
+ <Stack rowGap="m" hPadding="m" vPadding="m">
9
+ <Title size="6" render={<h2 />}>
10
+ Contributors
11
+ </Title>
12
+ <AvatarGroup
13
+ avatars={[
14
+ { alt: 'Contributor 1', fallback: 'A', src: 'https://example.com/a.jpg' },
15
+ { alt: 'Contributor 2', fallback: 'B', src: 'https://example.com/b.jpg' },
16
+ { alt: 'Contributor 3', fallback: 'C', src: 'https://example.com/c.jpg' },
17
+ { alt: 'Contributor 4', fallback: 'D', src: 'https://example.com/d.jpg' },
18
+ { alt: 'Contributor 5', fallback: 'E', src: 'https://example.com/e.jpg' },
19
+ { alt: 'Contributor 6', fallback: 'F', src: 'https://example.com/f.jpg' },
20
+ { alt: 'Contributor 7', fallback: 'G', src: 'https://example.com/g.jpg' },
21
+ { alt: 'Contributor 8', fallback: 'H', src: 'https://example.com/h.jpg' },
22
+ { alt: 'Contributor 9', fallback: 'I', src: 'https://example.com/i.jpg' },
23
+ { alt: 'Contributor 10', fallback: 'J', src: 'https://example.com/j.jpg' },
24
+ { alt: 'Contributor 11', fallback: 'K', src: 'https://example.com/k.jpg' },
25
+ { alt: 'Contributor 12', fallback: 'L', src: 'https://example.com/l.jpg' },
26
+ { alt: 'Contributor 13', fallback: 'M', src: 'https://example.com/m.jpg' },
27
+ { alt: 'Contributor 14', fallback: 'N', src: 'https://example.com/n.jpg' },
28
+ ]}
29
+ maxVisible={13}
30
+ overflowText="+810"
31
+ size="s"
32
+ />
33
+ </Stack>
34
+ </Surface>
35
+ ]]></tsx>
36
+ <notes>From `editor/preview-grid/blocks/contributors`. Pass `overflowText` explicitly — AvatarGroup does not derive hidden-count labels. Shared `size` on the group; never per-avatar sizes.</notes>
37
+ </example>
38
+
39
+ <example title="Empty team invite cluster">
40
+ <tsx><![CDATA[
41
+ <Surface border="all" color={1} radius="l" hPadding="m" vPadding="m">
42
+ <Stack
43
+ rowGap="m"
44
+ hPadding="l"
45
+ vPadding="2xl"
46
+ hAlign="center"
47
+ render={<Surface border="all" borderStyle="dashed" radius="l" />}
48
+ >
49
+ <AvatarGroup
50
+ avatars={[
51
+ { alt: 'Team member one', fallback: 'AL', src: 'https://example.com/al.jpg' },
52
+ { alt: 'Team member two', fallback: 'MR', src: 'https://example.com/mr.jpg' },
53
+ { alt: 'Team member three', fallback: 'EV', src: 'https://example.com/ev.jpg' },
54
+ ]}
55
+ size="m"
56
+ />
57
+ <Title align="center" size="5" render={<h3 />}>
58
+ No Team Members
59
+ </Title>
60
+ <Text size="s" align="center" maxWidth="14rem" tone="muted">
61
+ Invite your team to collaborate on this project.
62
+ </Text>
63
+ <Button>Invite Members</Button>
64
+ </Stack>
65
+ </Surface>
66
+ ]]></tsx>
67
+ <notes>From `editor/preview-grid/blocks/empty-team`. Medium AvatarGroup as empty-state media. Replaced inline dashed border style with `Stack render={&lt;Surface borderStyle="dashed" …/&gt;}`. Drop Annotate/Badge kitchen chrome.</notes>
6
68
  </example>
7
69
  </patterns>
@@ -24,16 +24,16 @@
24
24
  <prop name="size" kind="react">
25
25
  <description>Selects the shared avatar footprint for every rendered avatar.</description>
26
26
  </prop>
27
- <css_var suffix="gap-size">
27
+ <prop name="gap-size" kind="css">
28
28
  <description>Cutout gap used by overlap clip-path math.</description>
29
- </css_var>
30
- <css_var suffix="item-radius">
29
+ </prop>
30
+ <prop name="item-radius" kind="css">
31
31
  <description>Corner radius applied to grouped avatar items.</description>
32
- </css_var>
33
- <css_var suffix="overlap-distance">
32
+ </prop>
33
+ <prop name="overlap-distance" kind="css">
34
34
  <description>Negative margin overlap between adjacent avatars.</description>
35
- </css_var>
36
- <css_var suffix="size">
35
+ </prop>
36
+ <prop name="size" kind="css">
37
37
  <description>Rendered avatar size used for overlap layout.</description>
38
- </css_var>
38
+ </prop>
39
39
  </props>
@@ -1,10 +1,13 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="avatar-group">
3
- <do>Show a compact list of people or entities with consistent avatar sizing</do>
4
- <do>Display overlapping identity clusters in horizontal or vertical layouts</do>
5
- <do>Collapse long avatar lists into a final overflow pill such as +15 or +9938</do>
6
- <dont>Passing per-avatar size values instead of using the group size prop</dont>
7
- <dont>Expecting AvatarGroup to derive hidden-count labels instead of passing overflowText directly</dont>
8
- <dont>Expecting grouped avatars to always render as circles — items keep theme radius/squircle via --vui-avatar-group-item-radius</dont>
9
- <dont>Using non-positive maxVisible values expecting truncation</dont>
3
+ <do>Show overlapping people/entity clusters with shared group `size` and `avatars` payloads</do>
4
+ <do>Choose overlap axis with `direction` (`horizontal` or `vertical`)</do>
5
+ <do>Truncate long lists: positive `maxVisible` plus explicit `overflowText` (e.g. `+15`) — group does not invent the count label</do>
6
+ <do>Empty / invite states: AvatarGroup + Title + Text + Button inside Surface (optional dashed Surface via Stack `render`)</do>
7
+ <do>Contributors strip: AvatarGroup under Title inside Surface — Stack `rowGap` / padding owns spacing</do>
8
+ <dont>Passing per-avatar `size` — group applies one shared size to every item</dont>
9
+ <dont>Expecting AvatarGroup to derive hidden-count labels instead of passing `overflowText`</dont>
10
+ <dont>Using non-positive `maxVisible` expecting truncation</dont>
11
+ <dont>Expecting grouped avatars to always render as circles — items keep theme radius/squircle via `--vui-avatar-group-item-radius`</dont>
12
+ <dont>Using AvatarGroup for interactive per-item actions — map Avatar rows with Menu/Button instead</dont>
10
13
  </usage>
@@ -1,7 +1,61 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="badge">
3
- <example title="Badge structure">
4
- <tsx><![CDATA[<Badge>{child}</Badge>]]></tsx>
5
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
3
+ <!-- Sources: viraui-app / design-kitchen preview-grid — cleaned. Badge = status-dot overlay only; labeled tags use Chip. -->
4
+
5
+ <example title="CTA with attention dot">
6
+ <tsx><![CDATA[
7
+ <Surface border="all" color={1} radius="l" hPadding="m" vPadding="m">
8
+ <Stack
9
+ rowGap="m"
10
+ hPadding="l"
11
+ vPadding="2xl"
12
+ hAlign="center"
13
+ render={<Surface border="all" borderStyle="dashed" radius="l" />}
14
+ >
15
+ <AvatarGroup
16
+ avatars={[
17
+ { alt: '', fallback: 'AL' },
18
+ { alt: '', fallback: 'MR' },
19
+ { alt: '', fallback: 'EV' },
20
+ ]}
21
+ size="m"
22
+ />
23
+ <Title align="center" size="5" render={<h3 />}>
24
+ No Team Members
25
+ </Title>
26
+ <Text size="s" align="center" maxWidth="14rem" tone="muted">
27
+ Invite your team to collaborate on this project.
28
+ </Text>
29
+ <Badge show color="green">
30
+ <Button>Invite Members</Button>
31
+ </Badge>
32
+ </Stack>
33
+ </Surface>
34
+ ]]></tsx>
35
+ <notes>From `editor/preview-grid/blocks/empty-team`. Badge wraps Button; `show` + `color` drive the corner dot. Drop Annotate kitchen chrome. Meaning stays on the button label.</notes>
36
+ </example>
37
+
38
+ <example title="Avatar online indicator">
39
+ <tsx><![CDATA[
40
+ <Badge color="green" show>
41
+ <Avatar alt="Sarah Chen" fallback="SC" size="s" src="…" />
42
+ </Badge>
43
+ ]]></tsx>
44
+ <notes>From `editor/preview-grid/blocks/team-directory` member rows. Default position `top-end`. Dot is decorative — name/role live in nearby Text.</notes>
45
+ </example>
46
+
47
+ <example title="Control with notify dot">
48
+ <tsx><![CDATA[
49
+ <Badge show color="yellow">
50
+ <ToggleButton
51
+ aria-label="Mute notifications"
52
+ restingIcon={<BellSlash />}
53
+ pressedIcon={<BellOn />}
54
+ size="s"
55
+ variant="secondary"
56
+ />
57
+ </Badge>
58
+ ]]></tsx>
59
+ <notes>From `editor/preview-grid/blocks/team-directory` header. Yellow attention dot on a ToggleButton. App may toggle `show` with pressed state — pattern shows on state.</notes>
6
60
  </example>
7
61
  </patterns>
@@ -22,16 +22,16 @@
22
22
  <prop name="size" kind="react">
23
23
  <description>Diameter of the status dot via `--vui-badge-size`.</description>
24
24
  </prop>
25
- <css_var suffix="color">
25
+ <prop name="color" kind="css">
26
26
  <description>Status-dot accent color. Defaults to var(--global-primary).</description>
27
- </css_var>
28
- <css_var suffix="position-x">
27
+ </prop>
28
+ <prop name="position-x" kind="css">
29
29
  <description>Horizontal status-dot anchor. Position presets set it to 0% for start or 100% for end.</description>
30
- </css_var>
31
- <css_var suffix="position-y">
30
+ </prop>
31
+ <prop name="position-y" kind="css">
32
32
  <description>Vertical status-dot anchor. Position presets set it to 0% for top or 100% for bottom.</description>
33
- </css_var>
34
- <css_var suffix="size">
33
+ </prop>
34
+ <prop name="size" kind="css">
35
35
  <description>Status-dot diameter. Defaults to 0.5rem.</description>
36
- </css_var>
36
+ </prop>
37
37
  </props>
@@ -1,9 +1,11 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="badge">
3
- <do>Show online/offline or presence on an Avatar or icon without changing the child component API</do>
4
- <do>Mark a control as needing attention with a small corner indicator</do>
5
- <do>Keep Chip for labeled text badges; use Badge only for the status-dot overlay</do>
3
+ <do>Status-dot overlay only — wrap one child; toggle with `show`, accent with `color`, corner with `position`</do>
4
+ <do>Presence on identity: Badge wraps Avatar; put name/role in nearby Text — dot is decorative</do>
5
+ <do>Attention on controls: Badge wraps Button or ToggleButton; meaning stays on the control label / `aria-label`</do>
6
+ <do>Keep Chip for labeled text tags; use Badge only for the corner status dot</do>
6
7
  <dont>Using the visible dot as the only source of status for assistive tech</dont>
7
8
  <dont>Wrapping multiple element children when only one should receive the radial mask cutout</dont>
8
9
  <dont>Expecting the dot to participate in hit-testing</dont>
10
+ <dont>Putting count or text inside Badge — out of scope; use Chip or Text</dont>
9
11
  </usage>
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <meta id="beam" title="Beam" category="effect" shared_contract="beam">
3
- <summary>Decorative animated border, line, or pulse glow on a transparent Surface shell (radius only). Put the visual card as children. CSS-module geometry plus shared ~30fps pulse rAF for pulse variants. Memory/CPU cost — use sparingly.</summary>
3
+ <summary>Decorative animated border, line, or pulse glow on a transparent Surface shell (radius only). Put the visual card as children. CSS-module geometry plus shared ~30fps pulse rAF for pulse variants. Memory/CPU-heavy — use sparingly; prefer one focal instance per view.</summary>
4
4
  <exports>
5
5
  <export name="Beam" />
6
6
  </exports>