@viraui/react 2026.5.0 → 2026.6.1
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.
- package/dist/catalog.json +5 -5
- package/dist/components/avatar/avatar.js +1 -1
- package/dist/components/stack/stack.d.ts +4 -1
- package/dist/components/tabs/tabs.css +1 -1
- package/dist/components/text/text.css +1 -1
- package/dist/components/text/text.d.ts +16 -5
- package/dist/components/text/text.js +2 -1
- package/dist/components/textfield/textfield.d.ts +1 -0
- package/dist/components/title/title.css +1 -1
- package/dist/components/title/title.d.ts +12 -2
- package/dist/components/title/title.js +2 -1
- package/dist/preflight.css +4 -1
- package/dist/specs/PROTOCOL.md +23 -19
- package/dist/specs/activity-hints.xml +18 -3
- package/dist/specs/components/accordion/patterns.xml +69 -5
- package/dist/specs/components/accordion/props.xml +4 -4
- package/dist/specs/components/accordion/usage.xml +8 -4
- package/dist/specs/components/annotate/patterns.xml +50 -3
- package/dist/specs/components/annotate/props.xml +22 -22
- package/dist/specs/components/annotate/usage.xml +7 -6
- package/dist/specs/components/autocomplete/patterns.xml +123 -7
- package/dist/specs/components/autocomplete/props.xml +14 -14
- package/dist/specs/components/autocomplete/usage.xml +11 -6
- package/dist/specs/components/avatar/patterns.xml +78 -3
- package/dist/specs/components/avatar/props.xml +8 -8
- package/dist/specs/components/avatar/usage.xml +9 -3
- package/dist/specs/components/avatar-group/patterns.xml +65 -3
- package/dist/specs/components/avatar-group/props.xml +8 -8
- package/dist/specs/components/avatar-group/usage.xml +10 -7
- package/dist/specs/components/badge/patterns.xml +57 -3
- package/dist/specs/components/badge/props.xml +8 -8
- package/dist/specs/components/badge/usage.xml +5 -3
- package/dist/specs/components/beam/meta.xml +1 -1
- package/dist/specs/components/beam/patterns.xml +68 -3
- package/dist/specs/components/beam/props.xml +22 -22
- package/dist/specs/components/beam/usage.xml +7 -7
- package/dist/specs/components/bleed/patterns.xml +54 -3
- package/dist/specs/components/bleed/props.xml +2 -2
- package/dist/specs/components/bleed/usage.xml +6 -3
- package/dist/specs/components/breakpoints/meta.xml +1 -1
- package/dist/specs/components/breakpoints/patterns.xml +1 -6
- package/dist/specs/components/breakpoints/props.xml +4 -2
- package/dist/specs/components/breakpoints/usage.xml +10 -2
- package/dist/specs/components/button/patterns.xml +124 -6
- package/dist/specs/components/button/props.xml +33 -32
- package/dist/specs/components/button/usage.xml +13 -13
- package/dist/specs/components/checkbox/patterns.xml +83 -3
- package/dist/specs/components/checkbox/props.xml +10 -10
- package/dist/specs/components/checkbox/usage.xml +11 -6
- package/dist/specs/components/chip/patterns.xml +74 -3
- package/dist/specs/components/chip/props.xml +14 -14
- package/dist/specs/components/chip/usage.xml +10 -6
- package/dist/specs/components/clamp-text/patterns.xml +1 -4
- package/dist/specs/components/clamp-text/props.xml +2 -2
- package/dist/specs/components/clamp-text/usage.xml +8 -5
- package/dist/specs/components/dialog/patterns.xml +136 -15
- package/dist/specs/components/dialog/props.xml +2 -2
- package/dist/specs/components/dialog/usage.xml +9 -7
- package/dist/specs/components/elevator/patterns.xml +54 -3
- package/dist/specs/components/elevator/usage.xml +8 -5
- package/dist/specs/components/fieldset/patterns.xml +97 -3
- package/dist/specs/components/fieldset/usage.xml +7 -5
- package/dist/specs/components/fit-text/patterns.xml +1 -4
- package/dist/specs/components/fit-text/props.xml +2 -2
- package/dist/specs/components/fit-text/usage.xml +8 -6
- package/dist/specs/components/glow/meta.xml +1 -1
- package/dist/specs/components/glow/patterns.xml +74 -3
- package/dist/specs/components/glow/props.xml +16 -16
- package/dist/specs/components/glow/usage.xml +8 -7
- package/dist/specs/components/grid/patterns.xml +88 -5
- package/dist/specs/components/grid/props.xml +23 -23
- package/dist/specs/components/grid/usage.xml +9 -5
- package/dist/specs/components/icon-button/patterns.xml +97 -6
- package/dist/specs/components/icon-button/props.xml +32 -32
- package/dist/specs/components/icon-button/usage.xml +11 -9
- package/dist/specs/components/linear-progress/patterns.xml +58 -3
- package/dist/specs/components/linear-progress/props.xml +6 -6
- package/dist/specs/components/linear-progress/usage.xml +9 -8
- package/dist/specs/components/masonry/patterns.xml +68 -5
- package/dist/specs/components/masonry/props.xml +2 -2
- package/dist/specs/components/masonry/usage.xml +9 -4
- package/dist/specs/components/menu/patterns.xml +179 -15
- package/dist/specs/components/menu/usage.xml +8 -7
- package/dist/specs/components/meter/patterns.xml +49 -3
- package/dist/specs/components/meter/props.xml +6 -6
- package/dist/specs/components/meter/usage.xml +10 -7
- package/dist/specs/components/popover/patterns.xml +118 -9
- package/dist/specs/components/popover/props.xml +2 -2
- package/dist/specs/components/popover/usage.xml +9 -8
- package/dist/specs/components/progressive-blur/meta.xml +1 -1
- package/dist/specs/components/progressive-blur/patterns.xml +1 -4
- package/dist/specs/components/progressive-blur/props.xml +2 -2
- package/dist/specs/components/progressive-blur/usage.xml +7 -6
- package/dist/specs/components/radio/patterns.xml +55 -5
- package/dist/specs/components/radio/props.xml +8 -8
- package/dist/specs/components/radio/usage.xml +9 -6
- package/dist/specs/components/select/patterns.xml +124 -8
- package/dist/specs/components/select/props.xml +18 -18
- package/dist/specs/components/select/usage.xml +11 -10
- package/dist/specs/components/separator/patterns.xml +121 -3
- package/dist/specs/components/separator/props.xml +4 -4
- package/dist/specs/components/separator/usage.xml +8 -5
- package/dist/specs/components/shimmer/patterns.xml +23 -3
- package/dist/specs/components/shimmer/props.xml +8 -8
- package/dist/specs/components/shimmer/usage.xml +7 -5
- package/dist/specs/components/skeleton/patterns.xml +172 -4
- package/dist/specs/components/skeleton/props.xml +14 -14
- package/dist/specs/components/skeleton/usage.xml +11 -7
- package/dist/specs/components/slider/patterns.xml +111 -3
- package/dist/specs/components/slider/props.xml +10 -10
- package/dist/specs/components/slider/usage.xml +11 -5
- package/dist/specs/components/spinner/patterns.xml +35 -3
- package/dist/specs/components/spinner/props.xml +2 -2
- package/dist/specs/components/spinner/usage.xml +8 -5
- package/dist/specs/components/stack/patterns.xml +359 -3
- package/dist/specs/components/stack/props.xml +24 -22
- package/dist/specs/components/stack/usage.xml +16 -10
- package/dist/specs/components/static-noise/meta.xml +1 -1
- package/dist/specs/components/static-noise/patterns.xml +20 -3
- package/dist/specs/components/static-noise/usage.xml +5 -5
- package/dist/specs/components/surface/patterns.xml +188 -3
- package/dist/specs/components/surface/props.xml +26 -26
- package/dist/specs/components/surface/usage.xml +15 -12
- package/dist/specs/components/switch/patterns.xml +73 -3
- package/dist/specs/components/switch/props.xml +12 -12
- package/dist/specs/components/switch/usage.xml +10 -5
- package/dist/specs/components/tabs/patterns.xml +111 -6
- package/dist/specs/components/tabs/props.xml +2 -2
- package/dist/specs/components/tabs/usage.xml +7 -3
- package/dist/specs/components/text/patterns.xml +97 -3
- package/dist/specs/components/text/props.xml +48 -43
- package/dist/specs/components/text/usage.xml +11 -4
- package/dist/specs/components/textarea/patterns.xml +49 -3
- package/dist/specs/components/textarea/props.xml +7 -6
- package/dist/specs/components/textarea/usage.xml +8 -5
- package/dist/specs/components/textfield/patterns.xml +163 -3
- package/dist/specs/components/textfield/props.xml +12 -11
- package/dist/specs/components/textfield/usage.xml +9 -3
- package/dist/specs/components/title/patterns.xml +74 -3
- package/dist/specs/components/title/props.xml +48 -43
- package/dist/specs/components/title/usage.xml +10 -7
- package/dist/specs/components/toast/patterns.xml +85 -8
- package/dist/specs/components/toast/usage.xml +8 -5
- package/dist/specs/components/toggle-button/patterns.xml +101 -3
- package/dist/specs/components/toggle-button/props.xml +16 -16
- package/dist/specs/components/toggle-button/usage.xml +9 -5
- package/dist/specs/components/toggle-group/patterns.xml +34 -5
- package/dist/specs/components/toggle-group/usage.xml +9 -5
- package/dist/specs/components/tooltip/patterns.xml +110 -6
- package/dist/specs/components/tooltip/props.xml +2 -2
- package/dist/specs/components/tooltip/usage.xml +8 -5
- package/dist/specs/components/typewriter/patterns.xml +18 -3
- package/dist/specs/components/typewriter/props.xml +2 -2
- package/dist/specs/components/typewriter/usage.xml +9 -8
- package/dist/specs/foundation/attributes.xml +67 -37
- package/dist/specs/foundation/bootstrap.xml +6 -6
- package/dist/specs/foundation/elevation.xml +51 -3
- package/dist/specs/foundation/modules.xml +117 -40
- package/dist/specs/foundation/theme-topics.xml +62 -27
- package/dist/specs/foundation/toggles.xml +2 -2
- package/dist/specs/index.xml +42 -6
- package/dist/specs/patterns/card-grid.xml +35 -0
- package/dist/specs/patterns/compose-layout-first.xml +32 -0
- package/dist/specs/patterns/equal-width-actions.xml +22 -0
- package/dist/specs/patterns/page-chrome.xml +34 -0
- package/dist/specs/patterns/settings-panel.xml +30 -0
- package/dist/specs/patterns/settings-row.xml +9 -7
- package/dist/specs/patterns/stack-as-surface.xml +37 -0
- package/package.json +2 -2
|
@@ -52,37 +52,37 @@
|
|
|
52
52
|
<prop name="zIndex" kind="react">
|
|
53
53
|
<description>Stacking order for arrow and note via `--vui-annotate-z-index`. Same value on both parts.</description>
|
|
54
54
|
</prop>
|
|
55
|
-
<
|
|
55
|
+
<prop name="arrow-x" kind="css">
|
|
56
56
|
<description>Horizontal arrow offset.</description>
|
|
57
|
-
</
|
|
58
|
-
<
|
|
57
|
+
</prop>
|
|
58
|
+
<prop name="arrow-y" kind="css">
|
|
59
59
|
<description>Vertical arrow offset.</description>
|
|
60
|
-
</
|
|
61
|
-
<
|
|
60
|
+
</prop>
|
|
61
|
+
<prop name="color" kind="css">
|
|
62
62
|
<description>Arrow, note, and mark accent color. Defaults to var(--global-foreground).</description>
|
|
63
|
-
</
|
|
64
|
-
<
|
|
63
|
+
</prop>
|
|
64
|
+
<prop name="label-gap" kind="css">
|
|
65
65
|
<description>Gap between arrow and note on all sides.</description>
|
|
66
|
-
</
|
|
67
|
-
<
|
|
66
|
+
</prop>
|
|
67
|
+
<prop name="label-max-width" kind="css">
|
|
68
68
|
<description>Max width for the note part.</description>
|
|
69
|
-
</
|
|
70
|
-
<
|
|
69
|
+
</prop>
|
|
70
|
+
<prop name="rotate" kind="css">
|
|
71
71
|
<description>Note rotation angle.</description>
|
|
72
|
-
</
|
|
73
|
-
<
|
|
72
|
+
</prop>
|
|
73
|
+
<prop name="target-gap" kind="css">
|
|
74
74
|
<description>Gap between the target and the arrow.</description>
|
|
75
|
-
</
|
|
76
|
-
<
|
|
75
|
+
</prop>
|
|
76
|
+
<prop name="text-align" kind="css">
|
|
77
77
|
<description>Text alignment for the note. Defaults to start.</description>
|
|
78
|
-
</
|
|
79
|
-
<
|
|
78
|
+
</prop>
|
|
79
|
+
<prop name="text-x" kind="css">
|
|
80
80
|
<description>Legacy horizontal note offset custom property. Prefer textOffsetX from React.</description>
|
|
81
|
-
</
|
|
82
|
-
<
|
|
81
|
+
</prop>
|
|
82
|
+
<prop name="text-y" kind="css">
|
|
83
83
|
<description>Legacy vertical note offset custom property. Prefer textOffsetY from React.</description>
|
|
84
|
-
</
|
|
85
|
-
<
|
|
84
|
+
</prop>
|
|
85
|
+
<prop name="z-index" kind="css">
|
|
86
86
|
<description>Stacking order for arrow and note. Defaults to auto.</description>
|
|
87
|
-
</
|
|
87
|
+
</prop>
|
|
88
88
|
</props>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<usage surface="annotate">
|
|
3
|
-
<do>
|
|
4
|
-
<do>
|
|
5
|
-
<do>
|
|
6
|
-
<dont>
|
|
7
|
-
<dont>
|
|
3
|
+
<do>Wrap a Button CTA, a Surface graphic (QR / icon tile), or an inline phrase inside Text/Title — children stay the real content</do>
|
|
4
|
+
<do>Compose onboarding / empty-state callouts inside Stack + Surface shells with Title/Text/Button for the labeled instructions</do>
|
|
5
|
+
<do>Add optional `mark` highlighter behind the wrapped phrase while keeping `note` decorative</do>
|
|
6
|
+
<dont>Putting critical instructions or status only in `note` — assistive tech does not announce it; put that copy in Text/Title/Button</dont>
|
|
7
|
+
<dont>Using Annotate instead of Tooltip/Popover when focus, hover, or keyboard behavior is required</dont>
|
|
8
|
+
<dont>Nesting Annotate inside `overflow: hidden` parents without room for the arrow and label</dont>
|
|
9
|
+
<dont>Adding `position: relative` on Annotate — it breaks CSS anchor `position-area` placement</dont>
|
|
8
10
|
<dont>Expecting the label to participate in hit-testing or selection</dont>
|
|
9
|
-
<dont>Adding position:relative on Annotate — it breaks CSS anchor position-area placement</dont>
|
|
10
11
|
</usage>
|
|
@@ -1,14 +1,130 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<patterns surface="autocomplete">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
|
|
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
|
-
{(
|
|
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>
|
|
12
|
-
|
|
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
|
-
<
|
|
60
|
+
<prop name="control-group-background" kind="css">
|
|
61
61
|
<description>Autocomplete control group background.</description>
|
|
62
|
-
</
|
|
63
|
-
<
|
|
62
|
+
</prop>
|
|
63
|
+
<prop name="control-group-border-color" kind="css">
|
|
64
64
|
<description>Autocomplete control group border color; invalid state overrides.</description>
|
|
65
|
-
</
|
|
66
|
-
<
|
|
65
|
+
</prop>
|
|
66
|
+
<prop name="control-group-border-radius" kind="css">
|
|
67
67
|
<description>Autocomplete control group corner radius.</description>
|
|
68
|
-
</
|
|
69
|
-
<
|
|
68
|
+
</prop>
|
|
69
|
+
<prop name="control-group-color" kind="css">
|
|
70
70
|
<description>Autocomplete control group foreground color.</description>
|
|
71
|
-
</
|
|
72
|
-
<
|
|
71
|
+
</prop>
|
|
72
|
+
<prop name="input-height" kind="css">
|
|
73
73
|
<description>Autocomplete control group block size.</description>
|
|
74
|
-
</
|
|
75
|
-
<
|
|
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
|
-
</
|
|
78
|
-
<
|
|
77
|
+
</prop>
|
|
78
|
+
<prop name="list-padding" kind="css">
|
|
79
79
|
<description>Popup list padding custom property used for scroll padding.</description>
|
|
80
|
-
</
|
|
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>
|
|
5
|
-
<do>
|
|
6
|
-
<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="s"` and `type="button"`</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
|
|
9
|
-
<dont>Leaving the input without label or aria-label
|
|
10
|
-
<dont>Conditionally
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
<
|
|
26
|
+
<prop name="background" kind="css">
|
|
27
27
|
<description>Root background fill behind image or fallback.</description>
|
|
28
|
-
</
|
|
29
|
-
<
|
|
28
|
+
</prop>
|
|
29
|
+
<prop name="foreground" kind="css">
|
|
30
30
|
<description>Root foreground color for fallback content.</description>
|
|
31
|
-
</
|
|
32
|
-
<
|
|
31
|
+
</prop>
|
|
32
|
+
<prop name="radius" kind="css">
|
|
33
33
|
<description>Corner radius on the root; size presets also adjust this.</description>
|
|
34
|
-
</
|
|
35
|
-
<
|
|
34
|
+
</prop>
|
|
35
|
+
<prop name="size" kind="css">
|
|
36
36
|
<description>Avatar inline and block size on the root.</description>
|
|
37
|
-
</
|
|
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
|
|
4
|
-
<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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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={<Surface borderStyle="dashed" …/>}`. 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
|
-
<
|
|
27
|
+
<prop name="gap-size" kind="css">
|
|
28
28
|
<description>Cutout gap used by overlap clip-path math.</description>
|
|
29
|
-
</
|
|
30
|
-
<
|
|
29
|
+
</prop>
|
|
30
|
+
<prop name="item-radius" kind="css">
|
|
31
31
|
<description>Corner radius applied to grouped avatar items.</description>
|
|
32
|
-
</
|
|
33
|
-
<
|
|
32
|
+
</prop>
|
|
33
|
+
<prop name="overlap-distance" kind="css">
|
|
34
34
|
<description>Negative margin overlap between adjacent avatars.</description>
|
|
35
|
-
</
|
|
36
|
-
<
|
|
35
|
+
</prop>
|
|
36
|
+
<prop name="size" kind="css">
|
|
37
37
|
<description>Rendered avatar size used for overlap layout.</description>
|
|
38
|
-
</
|
|
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
|
|
4
|
-
<do>
|
|
5
|
-
<do>
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
<dont>
|
|
9
|
-
<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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
<
|
|
25
|
+
<prop name="color" kind="css">
|
|
26
26
|
<description>Status-dot accent color. Defaults to var(--global-primary).</description>
|
|
27
|
-
</
|
|
28
|
-
<
|
|
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
|
-
</
|
|
31
|
-
<
|
|
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
|
-
</
|
|
34
|
-
<
|
|
33
|
+
</prop>
|
|
34
|
+
<prop name="size" kind="css">
|
|
35
35
|
<description>Status-dot diameter. Defaults to 0.5rem.</description>
|
|
36
|
-
</
|
|
36
|
+
</prop>
|
|
37
37
|
</props>
|