@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
|
@@ -1,7 +1,78 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<patterns surface="title">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<!-- Sources: viraui-app + design-kitchen preview-grid — cleaned (no handlers, no i18n). -->
|
|
4
|
+
|
|
5
|
+
<example title="Auth hero heading">
|
|
6
|
+
<tsx><![CDATA[
|
|
7
|
+
<Title size="1" render={<h1 />} maxWidth="32rem" lineHeight="s">
|
|
8
|
+
Ship real UI at the speed of thought.
|
|
9
|
+
</Title>
|
|
10
|
+
]]></tsx>
|
|
11
|
+
<notes>From `auth/login-view`. Pair `size` with `render={<h1 />}` — visual preset and heading semantics stay intentional. (Live app nests Typewriter inside; see typewriter patterns.)</notes>
|
|
12
|
+
</example>
|
|
13
|
+
|
|
14
|
+
<example title="Card section heading">
|
|
15
|
+
<tsx><![CDATA[
|
|
16
|
+
<Stack rowGap="xs">
|
|
17
|
+
<Title size="6" render={<h2 />}>
|
|
18
|
+
Preferences
|
|
19
|
+
</Title>
|
|
20
|
+
<Text size="s" maxWidth="18rem" tone="muted">
|
|
21
|
+
Manage your account settings and notifications.
|
|
22
|
+
</Text>
|
|
23
|
+
</Stack>
|
|
24
|
+
]]></tsx>
|
|
25
|
+
<notes>From preview-grid `preferences` (+ payout-threshold, notifications, …). Dense card titles use `size="6"` + `h2`.</notes>
|
|
26
|
+
</example>
|
|
27
|
+
|
|
28
|
+
<example title="Empty-state heading">
|
|
29
|
+
<tsx><![CDATA[
|
|
30
|
+
<Title align="center" size="5" render={<h3 />}>
|
|
31
|
+
No Team Members
|
|
32
|
+
</Title>
|
|
33
|
+
]]></tsx>
|
|
34
|
+
<notes>From preview-grid `empty-team`. Centered mid-size heading; pair with muted Text below.</notes>
|
|
35
|
+
</example>
|
|
36
|
+
|
|
37
|
+
<example title="Display metric">
|
|
38
|
+
<tsx><![CDATA[
|
|
39
|
+
<Stack hAlign="center" rowGap="2xs">
|
|
40
|
+
<Title align="center" size="display" lineHeight="s" whiteSpace="nowrap">
|
|
41
|
+
2400
|
|
42
|
+
</Title>
|
|
43
|
+
<Text align="center" size="xs" tone="muted">
|
|
44
|
+
CALORIES/DAY
|
|
45
|
+
</Text>
|
|
46
|
+
</Stack>
|
|
47
|
+
]]></tsx>
|
|
48
|
+
<notes>From preview-grid `daily-activity-goal`. `size="display"` for hero numerals; `whiteSpace="nowrap"` keeps metric on one line.</notes>
|
|
49
|
+
</example>
|
|
50
|
+
|
|
51
|
+
<example title="Balance display">
|
|
52
|
+
<tsx><![CDATA[
|
|
53
|
+
<Stack rowGap="s">
|
|
54
|
+
<Text size="s" tone="muted">
|
|
55
|
+
Claimable Balance
|
|
56
|
+
</Text>
|
|
57
|
+
<Title size="1" lineHeight="s">
|
|
58
|
+
$0.00
|
|
59
|
+
</Title>
|
|
60
|
+
</Stack>
|
|
61
|
+
]]></tsx>
|
|
62
|
+
<notes>From preview-grid `claimable-balance`. Large `size="1"` Title as primary figure — muted label Text above, no heading tag required for non-outline figures.</notes>
|
|
63
|
+
</example>
|
|
64
|
+
|
|
65
|
+
<example title="Theme panel title">
|
|
66
|
+
<tsx><![CDATA[
|
|
67
|
+
<Stack rowGap="s">
|
|
68
|
+
<Title size="4" render={<h3 />}>
|
|
69
|
+
Colors
|
|
70
|
+
</Title>
|
|
71
|
+
<Text size="s" tone="muted">
|
|
72
|
+
Preview of theme voice, contrast, and color rhythm across accents.
|
|
73
|
+
</Text>
|
|
74
|
+
</Stack>
|
|
75
|
+
]]></tsx>
|
|
76
|
+
<notes>From design-kitchen `theme-preview` (+ `base-theme-selector` label scale). Mid panel titles use `size="4"` + `h3`.</notes>
|
|
6
77
|
</example>
|
|
7
78
|
</patterns>
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
<item>Headings and display text with title presets</item>
|
|
5
5
|
<item>Semantic heading tags chosen explicitly through render</item>
|
|
6
6
|
<item>Size and render paired together for most heading use cases</item>
|
|
7
|
-
<item>
|
|
7
|
+
<item>Letter-spacing via `tracking` or text-transform via `transform` — prefer props over CSS on the Title root</item>
|
|
8
|
+
<item>Fluid clamp sizing across title appearance presets (theme `--effect-fluid-typography` or per-instance `fluid`; off → fixed at --font-scale-display / h-* for that size)</item>
|
|
8
9
|
</when_to_use>
|
|
9
10
|
<when_not_to_use>
|
|
10
11
|
<item>Body copy — use Text</item>
|
|
11
12
|
<item>Body or mono family typography</item>
|
|
13
|
+
<item>Inventing CSS `letter-spacing` / `text-transform` / `width: 100%` when `tracking` / `transform` / parent Stack `fullWidth` cover the need</item>
|
|
12
14
|
</when_not_to_use>
|
|
13
15
|
<prop name="align" kind="react">
|
|
14
16
|
<description>Aligns text using logical alignment values.</description>
|
|
@@ -19,6 +21,9 @@
|
|
|
19
21
|
<prop name="color" kind="react">
|
|
20
22
|
<description>Applies a literal color escape hatch.</description>
|
|
21
23
|
</prop>
|
|
24
|
+
<prop name="fluid" kind="react">
|
|
25
|
+
<description>Enables viewport fluid clamp sizing for this instance. Pass false to lock at this size’s --font-scale-display / --font-scale-h* token. Theme --effect-fluid-typography: initial still locks all Title globally.</description>
|
|
26
|
+
</prop>
|
|
22
27
|
<prop name="fontWidth" kind="react">
|
|
23
28
|
<description>Overrides font width as a percentage (100 = normal); maps to `font-stretch` and `wdth`.</description>
|
|
24
29
|
</prop>
|
|
@@ -44,13 +49,13 @@
|
|
|
44
49
|
<description>Enables text selection on the rendered copy.</description>
|
|
45
50
|
</prop>
|
|
46
51
|
<prop name="size" kind="react">
|
|
47
|
-
<description>Selects a heading or display typography preset from the active theme scale. This controls only the visual preset. Semantic heading choice remains owned by `render`, because `Title` keeps a `span` root unless `render` replaces it. Fluid clamp between prev step and this size’s --font-scale-display / --font-scale-h* token is on when --effect-fluid-typography is empty; set the theme effect to initial to lock at that scale token.</description>
|
|
52
|
+
<description>Selects a heading or display typography preset from the active theme scale. This controls only the visual preset. Semantic heading choice remains owned by `render`, because `Title` keeps a `span` root unless `render` replaces it. Fluid clamp between prev step and this size’s --font-scale-display / --font-scale-h* token is on when --effect-fluid-typography is empty and `fluid` is true; set the theme effect to initial or pass `fluid={false}` to lock at that scale token.</description>
|
|
48
53
|
</prop>
|
|
49
54
|
<prop name="tracking" kind="react">
|
|
50
|
-
<description>Sets letter
|
|
55
|
+
<description>Sets letter-spacing on the rendered copy (overrides size preset when set). Prefer this prop over CSS `letter-spacing` / Tailwind tracking utilities on the same Title root.</description>
|
|
51
56
|
</prop>
|
|
52
57
|
<prop name="transform" kind="react">
|
|
53
|
-
<description>Applies
|
|
58
|
+
<description>Applies CSS `text-transform` on the rendered copy via `--vui-title-text-transform` (`uppercase` \| `lowercase` \| `capitalize` \| …). Prefer this prop over CSS `text-transform` on the same Title root.</description>
|
|
54
59
|
</prop>
|
|
55
60
|
<prop name="trim" kind="react">
|
|
56
61
|
<description>Trims text box whitespace at the chosen edge when the browser supports `text-box`. Pass `false` to disable text-box trim.</description>
|
|
@@ -67,58 +72,58 @@
|
|
|
67
72
|
<prop name="whiteSpace" kind="react">
|
|
68
73
|
<description>Controls white-space preservation and wrapping behavior.</description>
|
|
69
74
|
</prop>
|
|
70
|
-
<
|
|
75
|
+
<prop name="align" kind="css">
|
|
71
76
|
<description>Title alignment on the root.</description>
|
|
72
|
-
</
|
|
73
|
-
<
|
|
77
|
+
</prop>
|
|
78
|
+
<prop name="font-family" kind="css">
|
|
74
79
|
<description>Heading font family on the root.</description>
|
|
75
|
-
</
|
|
76
|
-
<
|
|
80
|
+
</prop>
|
|
81
|
+
<prop name="font-opsz" kind="css">
|
|
77
82
|
<description>Optical size axis on the root (variable fonts).</description>
|
|
78
|
-
</
|
|
79
|
-
<
|
|
80
|
-
<description>Heading font size; size prop presets via data attributes. Defaults to the theme scale token for that size; clamp (prev step→token) applies only when --effect-fluid-typography is on.</description>
|
|
81
|
-
</
|
|
82
|
-
<
|
|
83
|
+
</prop>
|
|
84
|
+
<prop name="font-size" kind="css">
|
|
85
|
+
<description>Heading font size; size prop presets via data attributes. Defaults to the theme scale token for that size; clamp (prev step→token) applies only when --effect-fluid-typography is on and `fluid` is true.</description>
|
|
86
|
+
</prop>
|
|
87
|
+
<prop name="font-weight" kind="css">
|
|
83
88
|
<description>Font weight on the root.</description>
|
|
84
|
-
</
|
|
85
|
-
<
|
|
89
|
+
</prop>
|
|
90
|
+
<prop name="font-width" kind="css">
|
|
86
91
|
<description>Font width percentage on the root (font-stretch + wdth).</description>
|
|
87
|
-
</
|
|
88
|
-
<
|
|
89
|
-
<description>Public letter spacing from the `tracking` prop when set.</description>
|
|
90
|
-
</
|
|
91
|
-
<
|
|
92
|
+
</prop>
|
|
93
|
+
<prop name="letter-spacing" kind="css">
|
|
94
|
+
<description>Public letter spacing from the `tracking` prop when set. Prefer that React prop over inventing CSS `letter-spacing` on the Title root.</description>
|
|
95
|
+
</prop>
|
|
96
|
+
<prop name="line-height" kind="css">
|
|
92
97
|
<description>Line height; lineHeight prop presets via data attributes.</description>
|
|
93
|
-
</
|
|
94
|
-
<
|
|
98
|
+
</prop>
|
|
99
|
+
<prop name="literal-color" kind="css">
|
|
95
100
|
<description>Literal color override on the root.</description>
|
|
96
|
-
</
|
|
97
|
-
<
|
|
101
|
+
</prop>
|
|
102
|
+
<prop name="max-width" kind="css">
|
|
98
103
|
<description>Max inline size of the title root.</description>
|
|
99
|
-
</
|
|
100
|
-
<
|
|
104
|
+
</prop>
|
|
105
|
+
<prop name="padding-block-end" kind="css">
|
|
101
106
|
<description>Block-end padding when padding is enabled.</description>
|
|
102
|
-
</
|
|
103
|
-
<
|
|
107
|
+
</prop>
|
|
108
|
+
<prop name="padding-block-start" kind="css">
|
|
104
109
|
<description>Block-start padding when padding is enabled.</description>
|
|
105
|
-
</
|
|
106
|
-
<
|
|
110
|
+
</prop>
|
|
111
|
+
<prop name="padding-inline-end" kind="css">
|
|
107
112
|
<description>Inline-end padding when padding is enabled.</description>
|
|
108
|
-
</
|
|
109
|
-
<
|
|
113
|
+
</prop>
|
|
114
|
+
<prop name="padding-inline-start" kind="css">
|
|
110
115
|
<description>Inline-start padding when padding is enabled.</description>
|
|
111
|
-
</
|
|
112
|
-
<
|
|
116
|
+
</prop>
|
|
117
|
+
<prop name="trim" kind="css">
|
|
113
118
|
<description>Text-box trim mode on the root.</description>
|
|
114
|
-
</
|
|
115
|
-
<
|
|
119
|
+
</prop>
|
|
120
|
+
<prop name="trim-type" kind="css">
|
|
116
121
|
<description>Text-box trim basis on the root.</description>
|
|
117
|
-
</
|
|
118
|
-
<
|
|
119
|
-
<description>Text transform on the root.</description>
|
|
120
|
-
</
|
|
121
|
-
<
|
|
122
|
+
</prop>
|
|
123
|
+
<prop name="text-transform" kind="css">
|
|
124
|
+
<description>Text transform on the root. Prefer the `transform` React prop; set this hook only when theming beyond the prop.</description>
|
|
125
|
+
</prop>
|
|
126
|
+
<prop name="white-space" kind="css">
|
|
122
127
|
<description>White-space behavior on the root.</description>
|
|
123
|
-
</
|
|
128
|
+
</prop>
|
|
124
129
|
</props>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<usage surface="title">
|
|
3
|
-
<do>Headings and display
|
|
4
|
-
<do>
|
|
5
|
-
<do>
|
|
6
|
-
<do>
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
<
|
|
3
|
+
<do>Headings and display type — pair `size` (visual preset) with `render={<h1 />}`…`h6` for outline semantics (default root is `span`)</do>
|
|
4
|
+
<do>Card / panel header: Stack `rowGap="xs"` + Title + muted Text blurb — Surface for card chrome</do>
|
|
5
|
+
<do>Auth / hero cycle: nest Typewriter inside Title (`preserveSpace`, caret props) so display preset + heading tag stay on the parent</do>
|
|
6
|
+
<do>Loading title copy: nest Shimmer inside Title — parent region owns busy semantics</do>
|
|
7
|
+
<do>Truncation: ClampText `render={<Title size=… render={<h* />} />}` — FitText wraps Title when short headlines must fill a constrained width</do>
|
|
8
|
+
<do>Fluid clamp across presets (`fluid` / theme `--effect-fluid-typography`); pass `fluid={false}` inside chrome or dense UI</do>
|
|
9
|
+
<do>Letter-spacing via `tracking`; text-transform via `transform`; width via `maxWidth` or parent Stack `fullWidth`</do>
|
|
10
|
+
<dont>Assuming `size` changes the HTML tag — choose `render` explicitly</dont>
|
|
11
|
+
<dont>Using Title for long body paragraphs — use Text</dont>
|
|
12
|
+
<dont>Inventing CSS `letter-spacing` / `text-transform` / `width: 100%` when props / Stack cover it</dont>
|
|
10
13
|
</usage>
|
|
@@ -1,15 +1,92 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<patterns surface="toast">
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
<!-- Sources: viraui-app/components + design-kitchen preview-support — cleaned (no handlers, no portal/preview chrome). -->
|
|
4
|
+
|
|
5
|
+
<example title="App toast region">
|
|
6
|
+
<tsx><![CDATA[
|
|
7
|
+
const toastManager = Toast.createToastManager();
|
|
8
|
+
|
|
9
|
+
<Toast.Provider toastManager={toastManager}>
|
|
10
|
+
{/* app tree */}
|
|
5
11
|
<Toast.Portal>
|
|
6
|
-
<Toast.Viewport>
|
|
7
|
-
|
|
8
|
-
<Toast.
|
|
9
|
-
|
|
12
|
+
<Toast.Viewport position="bottom-left">
|
|
13
|
+
{toasts.map((toast) => (
|
|
14
|
+
<Toast.Banner key={toast.id} description={toast.description} toast={toast} />
|
|
15
|
+
))}
|
|
10
16
|
</Toast.Viewport>
|
|
11
17
|
</Toast.Portal>
|
|
12
|
-
</Toast.Provider>
|
|
13
|
-
|
|
18
|
+
</Toast.Provider>
|
|
19
|
+
]]></tsx>
|
|
20
|
+
<notes>From `providers/providers`. Non-callable `Toast` namespace: Provider + Portal + Viewport + Banner list. `toasts` from `Toast.useToastManager()` inside the Provider.</notes>
|
|
21
|
+
</example>
|
|
22
|
+
|
|
23
|
+
<example title="Stacked alerts">
|
|
24
|
+
<tsx><![CDATA[
|
|
25
|
+
const stackedManager = Toast.createToastManager();
|
|
26
|
+
|
|
27
|
+
{/* somewhere under Toast.Provider toastManager={stackedManager} */}
|
|
28
|
+
<button type="button" onClick={() => stackedManager.add({ title: 'Order submitted', description: '1.95 shares at market price.' })}>
|
|
29
|
+
Simulate alert
|
|
30
|
+
</button>
|
|
31
|
+
|
|
32
|
+
<Toast.Portal>
|
|
33
|
+
<Toast.Viewport>
|
|
34
|
+
{toasts.map((toast) => (
|
|
35
|
+
<Toast.Banner key={toast.id} description={toast.description} toast={toast} />
|
|
36
|
+
))}
|
|
37
|
+
</Toast.Viewport>
|
|
38
|
+
</Toast.Portal>
|
|
39
|
+
]]></tsx>
|
|
40
|
+
<notes>From preview-grid `activity-feedback` + `preview-toast`. Manager `.add({ title, description })` feeds Banner. Drop portal-container props.</notes>
|
|
41
|
+
</example>
|
|
42
|
+
|
|
43
|
+
<example title="Anchored confirmation">
|
|
44
|
+
<tsx><![CDATA[
|
|
45
|
+
const anchoredManager = Toast.createToastManager();
|
|
46
|
+
const copyLinkRef = React.useRef<HTMLButtonElement>(null);
|
|
47
|
+
|
|
48
|
+
<button
|
|
49
|
+
ref={copyLinkRef}
|
|
50
|
+
type="button"
|
|
51
|
+
onClick={() =>
|
|
52
|
+
anchoredManager.add({
|
|
53
|
+
description: 'Link copied to clipboard.',
|
|
54
|
+
timeout: 1500,
|
|
55
|
+
positionerProps: { anchor: copyLinkRef.current, sideOffset: 8 },
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
Copy
|
|
60
|
+
</button>
|
|
61
|
+
|
|
62
|
+
<Toast.Portal>
|
|
63
|
+
<Toast.Viewport position="anchored">
|
|
64
|
+
{toasts.map((toast) => {
|
|
65
|
+
if (!toast.positionerProps?.anchor) return null;
|
|
66
|
+
return (
|
|
67
|
+
<Toast.Positioner key={toast.id} toast={toast}>
|
|
68
|
+
<Toast.Banner description={toast.description} dismissable={false} toast={toast} />
|
|
69
|
+
</Toast.Positioner>
|
|
70
|
+
);
|
|
71
|
+
})}
|
|
72
|
+
</Toast.Viewport>
|
|
73
|
+
</Toast.Portal>
|
|
74
|
+
]]></tsx>
|
|
75
|
+
<notes>From preview `preview-providers` anchored list + `activity-feedback` Copy. Viewport `position="anchored"` + `Toast.Positioner` wraps Banner.</notes>
|
|
76
|
+
</example>
|
|
77
|
+
|
|
78
|
+
<example title="Banner with undo action">
|
|
79
|
+
<tsx><![CDATA[
|
|
80
|
+
<Toast.Portal>
|
|
81
|
+
<Toast.Viewport>
|
|
82
|
+
{toasts.map((toast) => (
|
|
83
|
+
<Toast.Banner key={toast.id} description={toast.description} toast={toast}>
|
|
84
|
+
<Toast.Action render={<Button variant="destructive" />}>Undo</Toast.Action>
|
|
85
|
+
</Toast.Banner>
|
|
86
|
+
))}
|
|
87
|
+
</Toast.Viewport>
|
|
88
|
+
</Toast.Portal>
|
|
89
|
+
]]></tsx>
|
|
90
|
+
<notes>From Toast stories undo list. Banner children are `Toast.Action` only. Close via manager inside a real handler — omitted here.</notes>
|
|
14
91
|
</example>
|
|
15
92
|
</patterns>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<usage surface="toast">
|
|
3
|
-
<do>
|
|
4
|
-
<do>
|
|
5
|
-
<do>
|
|
6
|
-
<do>
|
|
3
|
+
<do>Mount once: `Toast.createToastManager()` → `Toast.Provider toastManager={…}` around the app tree</do>
|
|
4
|
+
<do>Render region: `Toast.Portal` → `Toast.Viewport` → map `Toast.useToastManager().toasts` to `Toast.Banner`</do>
|
|
5
|
+
<do>Confirm save/delete or short undo: manager `.add({ title, description })` feeds Banner</do>
|
|
6
|
+
<do>Undo / secondary actions: Banner children are `Toast.Action` only — default Button chrome, or `render={<Button …/>}`</do>
|
|
7
|
+
<do>Anchored feedback: Viewport `position="anchored"` + `Toast.Positioner` wrapping Banner; pass `positionerProps.anchor` from `.add`</do>
|
|
8
|
+
<do>Custom portal host (iframe preview, shadow root, or app overlay root) via `container` on `Toast.Portal`</do>
|
|
7
9
|
<dont>Nesting arbitrary components inside Toast.Banner — children must be Toast.Action only</dont>
|
|
10
|
+
<dont>Calling Toast as a component — it is a non-callable namespace (Provider / Portal / Viewport / Banner / Action)</dont>
|
|
11
|
+
<dont>Using toasts for critical validation that blocks the task — use field errors or Dialog</dont>
|
|
8
12
|
<dont>Stacking many simultaneous toasts without a clear limit</dont>
|
|
9
|
-
<dont>Using toasts for critical validation errors that block task completion</dont>
|
|
10
13
|
</usage>
|
|
@@ -1,7 +1,105 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<patterns surface="toggle-button">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<!-- Sources: viraui-app — cleaned (no handlers, no i18n, no studio store). Icon-only; never children. -->
|
|
4
|
+
|
|
5
|
+
<example title="Copy feedback (interpolate)">
|
|
6
|
+
<tsx><![CDATA[
|
|
7
|
+
<ToggleButton
|
|
8
|
+
aria-label="Copy to clipboard"
|
|
9
|
+
restingIcon={<Duplicate aria-hidden />}
|
|
10
|
+
pressedIcon={<CircleCheck aria-hidden color="var(--highlight-green)" />}
|
|
11
|
+
interpolateIcons
|
|
12
|
+
variant="secondary"
|
|
13
|
+
/>
|
|
14
|
+
]]></tsx>
|
|
15
|
+
<notes>From `common/code-block` (+ `editor/export-dialog` preset copy). Temporal pressed state swaps glyph; `interpolateIcons` crossfades. App resets pressed after a timer — omit that from the hint.</notes>
|
|
16
|
+
</example>
|
|
17
|
+
|
|
18
|
+
<example title="Shuffle lock">
|
|
19
|
+
<tsx><![CDATA[
|
|
20
|
+
<Tooltip>
|
|
21
|
+
<Tooltip.Trigger
|
|
22
|
+
render={
|
|
23
|
+
<ToggleButton
|
|
24
|
+
aria-label="Lock in shuffle"
|
|
25
|
+
restingIcon={<LockOpen2 aria-hidden size="1rem" />}
|
|
26
|
+
pressedIcon={<Lock aria-hidden size="1rem" color="var(--global-primary)" />}
|
|
27
|
+
variant="flat"
|
|
28
|
+
pressedVariant="secondary"
|
|
29
|
+
/>
|
|
30
|
+
}
|
|
31
|
+
/>
|
|
32
|
+
<Tooltip.Content>Unlocked in shuffle</Tooltip.Content>
|
|
33
|
+
</Tooltip>
|
|
34
|
+
]]></tsx>
|
|
35
|
+
<notes>From `editor/controls/shuffle-lock-toggle`. Flat resting + `pressedVariant` for locked chrome. Name via `aria-label`; tooltip is optional extra copy.</notes>
|
|
36
|
+
</example>
|
|
37
|
+
|
|
38
|
+
<example title="Mode sync (pressedVariant)">
|
|
39
|
+
<tsx><![CDATA[
|
|
40
|
+
<Tooltip>
|
|
41
|
+
<Tooltip.Trigger
|
|
42
|
+
render={
|
|
43
|
+
<ToggleButton
|
|
44
|
+
aria-label="Sync light and dark"
|
|
45
|
+
size="s"
|
|
46
|
+
restingIcon={<DarkLight aria-hidden size="1rem" />}
|
|
47
|
+
variant="flat"
|
|
48
|
+
pressedVariant="primary"
|
|
49
|
+
/>
|
|
50
|
+
}
|
|
51
|
+
/>
|
|
52
|
+
<Tooltip.Content>Keep light and dark in sync</Tooltip.Content>
|
|
53
|
+
</Tooltip>
|
|
54
|
+
]]></tsx>
|
|
55
|
+
<notes>From `editor/controls/primary-color-select` / `foreground-color` custom fields. Single ToggleButton (not a group) with `pressedVariant="primary"` for sync-on.</notes>
|
|
56
|
+
</example>
|
|
57
|
+
|
|
58
|
+
<example title="Notify mute with Badge">
|
|
59
|
+
<tsx><![CDATA[
|
|
60
|
+
<Badge show color="yellow">
|
|
61
|
+
<ToggleButton
|
|
62
|
+
aria-label="Mute notifications"
|
|
63
|
+
restingIcon={<BellSlash aria-hidden size={16} />}
|
|
64
|
+
pressedIcon={<BellOn aria-hidden size={16} />}
|
|
65
|
+
size="s"
|
|
66
|
+
interpolateIcons
|
|
67
|
+
variant="secondary"
|
|
68
|
+
/>
|
|
69
|
+
</Badge>
|
|
70
|
+
]]></tsx>
|
|
71
|
+
<notes>From `editor/preview-grid/blocks/team-directory`. Badge attention dot wraps ToggleButton; icon pair + `interpolateIcons`. Accessible name on the control (app may use `aria-labelledby` + Tooltip text).</notes>
|
|
72
|
+
</example>
|
|
73
|
+
|
|
74
|
+
<example title="Segmented group child">
|
|
75
|
+
<tsx><![CDATA[
|
|
76
|
+
<ToggleGroup aria-label="Color mode" value={['system']}>
|
|
77
|
+
<ToggleButton
|
|
78
|
+
value="light"
|
|
79
|
+
aria-label="Light"
|
|
80
|
+
restingIcon={<Sun aria-hidden size="1rem" />}
|
|
81
|
+
variant="flat"
|
|
82
|
+
size="s"
|
|
83
|
+
pressedVariant="secondary"
|
|
84
|
+
/>
|
|
85
|
+
<ToggleButton
|
|
86
|
+
value="dark"
|
|
87
|
+
aria-label="Dark"
|
|
88
|
+
restingIcon={<MoonStars aria-hidden size="1rem" />}
|
|
89
|
+
variant="flat"
|
|
90
|
+
size="s"
|
|
91
|
+
pressedVariant="secondary"
|
|
92
|
+
/>
|
|
93
|
+
<ToggleButton
|
|
94
|
+
value="system"
|
|
95
|
+
aria-label="System"
|
|
96
|
+
restingIcon={<DarkLight aria-hidden size="1rem" />}
|
|
97
|
+
variant="flat"
|
|
98
|
+
size="s"
|
|
99
|
+
pressedVariant="secondary"
|
|
100
|
+
/>
|
|
101
|
+
</ToggleGroup>
|
|
102
|
+
]]></tsx>
|
|
103
|
+
<notes>From `common/mode-switcher`. Inside ToggleGroup each child needs `value` + accessible name. Prefer ToggleGroup patterns for full chrome; this shows the per-button shape.</notes>
|
|
6
104
|
</example>
|
|
7
105
|
</patterns>
|
|
@@ -34,28 +34,28 @@
|
|
|
34
34
|
<prop name="variant" kind="react">
|
|
35
35
|
<description>Visual variant while the toggle is not pressed.</description>
|
|
36
36
|
</prop>
|
|
37
|
-
<
|
|
37
|
+
<prop name="background" kind="css">
|
|
38
38
|
<description>Button fill; variant and state selectors preset this.</description>
|
|
39
|
-
</
|
|
40
|
-
<
|
|
39
|
+
</prop>
|
|
40
|
+
<prop name="color" kind="css">
|
|
41
41
|
<description>Button label and icon color.</description>
|
|
42
|
-
</
|
|
43
|
-
<
|
|
42
|
+
</prop>
|
|
43
|
+
<prop name="height" kind="css">
|
|
44
44
|
<description>Button block size; size prop presets via data attributes.</description>
|
|
45
|
-
</
|
|
46
|
-
<
|
|
45
|
+
</prop>
|
|
46
|
+
<prop name="icon-size" kind="css">
|
|
47
47
|
<description>Addon icon size inside the button.</description>
|
|
48
|
-
</
|
|
49
|
-
<
|
|
48
|
+
</prop>
|
|
49
|
+
<prop name="padding-block" kind="css">
|
|
50
50
|
<description>Vertical padding inside the button.</description>
|
|
51
|
-
</
|
|
52
|
-
<
|
|
51
|
+
</prop>
|
|
52
|
+
<prop name="padding-inline" kind="css">
|
|
53
53
|
<description>Horizontal padding inside the button.</description>
|
|
54
|
-
</
|
|
55
|
-
<
|
|
54
|
+
</prop>
|
|
55
|
+
<prop name="radius" kind="css">
|
|
56
56
|
<description>Corner radius; pill sets full radius via data-pill.</description>
|
|
57
|
-
</
|
|
58
|
-
<
|
|
57
|
+
</prop>
|
|
58
|
+
<prop name="spinner-color" kind="css">
|
|
59
59
|
<description>Loading spinner color on the root.</description>
|
|
60
|
-
</
|
|
60
|
+
</prop>
|
|
61
61
|
</props>
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<usage surface="toggle-button">
|
|
3
|
-
<do>Toolbar pin, favorite, or
|
|
3
|
+
<do>Toolbar pin, favorite, mute, or lock toggles identified only by icon</do>
|
|
4
4
|
<do>Compact on/off controls that share IconButton size, variant, and loading model</do>
|
|
5
|
-
<do>Two-state actions where pressed state should swap the visible glyph
|
|
6
|
-
<do>
|
|
7
|
-
<
|
|
5
|
+
<do>Two-state actions where pressed state should swap the visible glyph via `restingIcon` / `pressedIcon`</do>
|
|
6
|
+
<do>Temporal pressed feedback (e.g. copy) with optional `interpolateIcons` crossfade</do>
|
|
7
|
+
<do>Segmented toolbars: nest ToggleButtons with `value` inside ToggleGroup; label each control and the group</do>
|
|
8
|
+
<do>Optional chrome: wrap with Tooltip.Trigger / Badge — keep the accessible name on the ToggleButton</do>
|
|
9
|
+
<dont>Using IconButton for persistent or temporal pressed toolbar state</dont>
|
|
8
10
|
<dont>Using Switch for compact icon-only toolbar toggles</dont>
|
|
9
|
-
<dont>Passing icon or render — ToggleButton owns icon swap and Toggle render wiring
|
|
11
|
+
<dont>Passing `icon` or `render` — ToggleButton owns icon swap and Toggle render wiring; use `restingIcon` / `pressedIcon`</dont>
|
|
12
|
+
<dont>Omitting `value` on ToggleButton children inside a ToggleGroup</dont>
|
|
13
|
+
<dont>Omitting both `aria-label` and `aria-labelledby`</dont>
|
|
10
14
|
</usage>
|
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<patterns surface="toggle-group">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
<!-- Sources: viraui-app — cleaned (no handlers, no i18n, no theme store). Compound: ToggleGroup + ToggleButton children with value. -->
|
|
4
|
+
|
|
5
|
+
<example title="Mode switcher chrome">
|
|
6
|
+
<tsx><![CDATA[
|
|
7
|
+
<Surface border="all" radius="m" vPadding="2xs" hPadding="2xs">
|
|
8
|
+
<ToggleGroup aria-label="Color mode" value={['system']}>
|
|
9
|
+
<ToggleButton
|
|
10
|
+
value="light"
|
|
11
|
+
aria-label="Light"
|
|
12
|
+
restingIcon={<Sun aria-hidden size="1rem" />}
|
|
13
|
+
variant="flat"
|
|
14
|
+
size="s"
|
|
15
|
+
pressedVariant="secondary"
|
|
16
|
+
/>
|
|
17
|
+
<ToggleButton
|
|
18
|
+
value="dark"
|
|
19
|
+
aria-label="Dark"
|
|
20
|
+
restingIcon={<MoonStars aria-hidden size="1rem" />}
|
|
21
|
+
variant="flat"
|
|
22
|
+
size="s"
|
|
23
|
+
pressedVariant="secondary"
|
|
24
|
+
/>
|
|
25
|
+
<ToggleButton
|
|
26
|
+
value="system"
|
|
27
|
+
aria-label="System"
|
|
28
|
+
restingIcon={<DarkLight aria-hidden size="1rem" />}
|
|
29
|
+
variant="flat"
|
|
30
|
+
size="s"
|
|
31
|
+
pressedVariant="secondary"
|
|
32
|
+
/>
|
|
33
|
+
</ToggleGroup>
|
|
34
|
+
</Surface>
|
|
35
|
+
]]></tsx>
|
|
36
|
+
<notes>From `common/mode-switcher`. ToggleGroup selection is `string[]` (`value` / `defaultValue` / `onValueChange`). Label the group with `aria-label`. Surface tight padding is chrome — group Stack owns item gap (`2xs`). Exclusive mode: one selected value in the array.</notes>
|
|
8
37
|
</example>
|
|
9
38
|
</patterns>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<usage surface="toggle-group">
|
|
3
|
-
<do>Segmented icon toolbars such as text alignment or
|
|
4
|
-
<do>Single- or multi-select pressed states across related ToggleButton items</do>
|
|
5
|
-
<do>
|
|
6
|
-
<
|
|
3
|
+
<do>Segmented icon toolbars such as text alignment, formatting, or mode switchers</do>
|
|
4
|
+
<do>Single- or multi-select pressed states across related ToggleButton items (`value` / `defaultValue` as `string[]`)</do>
|
|
5
|
+
<do>Compose only ToggleButton children — each child needs a `value` plus `aria-label` / `aria-labelledby`</do>
|
|
6
|
+
<do>Label the group root with `aria-label` or `aria-labelledby`</do>
|
|
7
|
+
<do>Optional Surface chrome around the group for bordered toolbar shells — Stack gap is owned by ToggleGroup</do>
|
|
8
|
+
<dont>Omitting `value` on ToggleButton children inside a group</dont>
|
|
7
9
|
<dont>Using Switch for icon-only toolbar toggle sets</dont>
|
|
8
|
-
<dont>
|
|
10
|
+
<dont>Using ToggleGroup for tabbed panel navigation — use Tabs</dont>
|
|
11
|
+
<dont>Using ToggleGroup for a lone one-off toggle — use ToggleButton alone</dont>
|
|
12
|
+
<dont>Embedding Surface chrome inside the component — wrap demos or app chrome at the consumer</dont>
|
|
9
13
|
</usage>
|