@utilitywarehouse/hearth-react 0.28.6 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -20
- package/SKILL.md +355 -0
- package/dist/{chunk-O7RBVBMN.cjs → chunk-LWHIBSW2.cjs} +2 -2
- package/dist/{chunk-O7RBVBMN.cjs.map → chunk-LWHIBSW2.cjs.map} +1 -1
- package/dist/{chunk-JRVYOIXR.js → chunk-MIVYZGEV.js} +2 -2
- package/dist/components/CardAccordion/CardAccordion.context.d.ts.map +1 -1
- package/dist/components/Combobox/Combobox.cjs +1 -1
- package/dist/components/Combobox/Combobox.js +1 -1
- package/dist/components/ExpandableCard/ExpandableCard.cjs +1 -1
- package/dist/components/ExpandableCard/ExpandableCard.js +1 -1
- package/dist/helpers/get-classname-styles.d.ts.map +1 -1
- package/dist/helpers/logger.d.ts.map +1 -1
- package/dist/helpers/merge-ids.d.ts.map +1 -1
- package/dist/hooks/use-ids.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +18 -12
- package/public/llms/components/accordion.md +321 -0
- package/public/llms/components/alert.md +217 -0
- package/public/llms/components/avatar.md +112 -0
- package/public/llms/components/badge.md +158 -0
- package/public/llms/components/body-text.md +200 -0
- package/public/llms/components/box.md +148 -0
- package/public/llms/components/breadcrumbs.md +97 -0
- package/public/llms/components/button.md +595 -0
- package/public/llms/components/card-accordion.md +277 -0
- package/public/llms/components/card.md +985 -0
- package/public/llms/components/checkbox-group.md +193 -0
- package/public/llms/components/checkbox-tile.md +116 -0
- package/public/llms/components/checkbox.md +108 -0
- package/public/llms/components/combobox.md +360 -0
- package/public/llms/components/container.md +162 -0
- package/public/llms/components/currency-input.md +85 -0
- package/public/llms/components/date-input.md +90 -0
- package/public/llms/components/date-picker.md +159 -0
- package/public/llms/components/description-list.md +149 -0
- package/public/llms/components/detail-text.md +89 -0
- package/public/llms/components/divider.md +88 -0
- package/public/llms/components/em.md +43 -0
- package/public/llms/components/expandable-card.md +231 -0
- package/public/llms/components/flex.md +197 -0
- package/public/llms/components/grid.md +244 -0
- package/public/llms/components/heading.md +65 -0
- package/public/llms/components/helper-text.md +27 -0
- package/public/llms/components/highlight-banner.md +94 -0
- package/public/llms/components/icon-button.md +516 -0
- package/public/llms/components/icon-container.md +247 -0
- package/public/llms/components/inline-link.md +190 -0
- package/public/llms/components/label.md +28 -0
- package/public/llms/components/link.md +236 -0
- package/public/llms/components/list.md +715 -0
- package/public/llms/components/menu.md +270 -0
- package/public/llms/components/modal.md +328 -0
- package/public/llms/components/pagination.md +138 -0
- package/public/llms/components/password-input.md +93 -0
- package/public/llms/components/progress-bar.md +139 -0
- package/public/llms/components/progress-stepper.md +147 -0
- package/public/llms/components/radio-group.md +487 -0
- package/public/llms/components/search-input.md +132 -0
- package/public/llms/components/section-header.md +82 -0
- package/public/llms/components/select.md +148 -0
- package/public/llms/components/skeleton.md +282 -0
- package/public/llms/components/spinner.md +59 -0
- package/public/llms/components/strong.md +49 -0
- package/public/llms/components/switch.md +106 -0
- package/public/llms/components/table.md +230 -0
- package/public/llms/components/tabs.md +320 -0
- package/public/llms/components/text-area.md +141 -0
- package/public/llms/components/text-input.md +228 -0
- package/public/llms/components/toast.md +323 -0
- package/public/llms/components/toggle-button-card.md +513 -0
- package/public/llms/components/tooltip.md +188 -0
- package/public/llms/components/unstyled-icon-button.md +175 -0
- package/public/llms/components/validation-text.md +29 -0
- package/public/llms/components/verification-input.md +96 -0
- package/public/llms/docs/changelog.md +1430 -0
- package/public/llms/docs/common-props/align-self.md +90 -0
- package/public/llms/docs/common-props/border.md +308 -0
- package/public/llms/docs/common-props/colour.md +221 -0
- package/public/llms/docs/common-props/flex-items.md +91 -0
- package/public/llms/docs/common-props/gap.md +111 -0
- package/public/llms/docs/common-props/grid-items.md +96 -0
- package/public/llms/docs/common-props/margin.md +105 -0
- package/public/llms/docs/common-props/opacity.md +100 -0
- package/public/llms/docs/common-props/order.md +90 -0
- package/public/llms/docs/common-props/overflow.md +89 -0
- package/public/llms/docs/common-props/padding.md +102 -0
- package/public/llms/docs/common-props/position.md +92 -0
- package/public/llms/docs/common-props/size.md +93 -0
- package/public/llms/docs/common-props/spacing.md +97 -0
- package/public/llms/docs/common-props/text.md +35 -0
- package/public/llms/docs/common-props/z-index.md +88 -0
- package/public/llms/docs/design-tokens.md +72 -0
- package/public/llms/docs/getting-started.md +117 -0
- package/public/llms/docs/layout.md +135 -0
- package/public/llms/docs/migrating.md +302 -0
- package/public/llms/docs/responsive-design/breakpoints.md +119 -0
- package/public/llms/docs/responsive-design/media-queries.md +89 -0
- package/public/llms/docs/responsive-design/responsive-props.md +37 -0
- package/public/llms.txt +97 -0
- package/scripts/init-ai.js +142 -0
- package/styles.css +2 -2
- /package/dist/{chunk-JRVYOIXR.js.map → chunk-MIVYZGEV.js.map} +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# TextInput
|
|
2
|
+
|
|
3
|
+
`TextInput` is an interactive field that allows users to enter text and data.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
<TextInput {...args} />
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
- [Alternatives](#alternatives)
|
|
10
|
+
- [Label](#label)
|
|
11
|
+
- [Required](#required)
|
|
12
|
+
- [Disabled and Read-only](#disabled-and-read-only)
|
|
13
|
+
- [Validation](#validation)
|
|
14
|
+
- [Prefix and Suffix](#prefix-and-suffix)
|
|
15
|
+
- [Grouping inputs](#grouping-inputs)
|
|
16
|
+
- [API](#api)
|
|
17
|
+
|
|
18
|
+
## Alternatives
|
|
19
|
+
|
|
20
|
+
- PasswordInput - For entering
|
|
21
|
+
passwords
|
|
22
|
+
- SearchInput - For search
|
|
23
|
+
- CurrencyInput - For money
|
|
24
|
+
- VerificationInput - For one-time
|
|
25
|
+
passwords
|
|
26
|
+
- DateInput - For entering dates
|
|
27
|
+
|
|
28
|
+
## Label
|
|
29
|
+
|
|
30
|
+
A label is required, this should be clear and descriptive to guide the user.
|
|
31
|
+
|
|
32
|
+
The `hideLabel` prop will visually hide the label but keep it available for screen readers.
|
|
33
|
+
|
|
34
|
+
## Required
|
|
35
|
+
|
|
36
|
+
In it's default state the `TextInput` is optional, and is indicated as such
|
|
37
|
+
with the `(optional)` text following the label.
|
|
38
|
+
|
|
39
|
+
When using online forms, most users assume all fields are required by default,
|
|
40
|
+
so the `TextInput` draws attention to when it is optional. Please make sure
|
|
41
|
+
that when the input field is required for successful completion of the form,
|
|
42
|
+
that you apply the `required` prop and appropriate validation is included.
|
|
43
|
+
|
|
44
|
+
You may also need to set the `novalidate` attribute to prevent the browser from
|
|
45
|
+
displaying its own validation errors.
|
|
46
|
+
|
|
47
|
+
## Disabled and Read-only
|
|
48
|
+
|
|
49
|
+
Read-only inputs cannot be edited, but remain focusable, and should only be
|
|
50
|
+
used when presenting already submitted information. They differ from
|
|
51
|
+
disabled inputs, as there may be actions a user can take to activate a disabled
|
|
52
|
+
input, but read-only fields should stay undeditable in the same view.
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<Flex direction="column" gap="400">
|
|
56
|
+
<TextInput {...args} label="Disabled" disabled helperText="Please do something before this" />
|
|
57
|
+
<TextInput
|
|
58
|
+
{...args}
|
|
59
|
+
label="Read only"
|
|
60
|
+
readOnly
|
|
61
|
+
value="Uneditable previously provided information"
|
|
62
|
+
/>
|
|
63
|
+
</Flex>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Validation
|
|
67
|
+
|
|
68
|
+
The input `validationStatus` can be set to either `"valid"` or `"invalid"` to
|
|
69
|
+
indicate the status. This status must be accompanied by the `validationText` to
|
|
70
|
+
explain the reason for the status.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<Flex direction="column" gap="400">
|
|
74
|
+
<TextInput
|
|
75
|
+
{...args}
|
|
76
|
+
label="Email"
|
|
77
|
+
type="email"
|
|
78
|
+
defaultValue="rphoenix@uw.co.uk"
|
|
79
|
+
validationStatus="valid"
|
|
80
|
+
validationText="Valid email address"
|
|
81
|
+
required
|
|
82
|
+
/>
|
|
83
|
+
<TextInput
|
|
84
|
+
{...args}
|
|
85
|
+
label="Email"
|
|
86
|
+
type="email"
|
|
87
|
+
defaultValue="rphoenix@geemail."
|
|
88
|
+
validationStatus="invalid"
|
|
89
|
+
validationText="Please enter a valid email address"
|
|
90
|
+
required
|
|
91
|
+
/>
|
|
92
|
+
</Flex>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
You can set the `validationText` according to what the `validationStatus` is:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
const validationStatus = isValid ? "valid" : isInvalid ? "invalid" : undefined
|
|
99
|
+
const validationText = isValid ? "Your input is valid" : isInvalid ? "Your input is invalid" : undefined
|
|
100
|
+
|
|
101
|
+
[...]
|
|
102
|
+
|
|
103
|
+
<TextInput
|
|
104
|
+
label="Name"
|
|
105
|
+
required
|
|
106
|
+
validationStatus={validationStatus}
|
|
107
|
+
validationText={validationText}
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Be aware that you probably want to set `noValidate` on your form to prevent
|
|
112
|
+
the browser from displaying its own validation messages.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<form noValidate>
|
|
116
|
+
<TextInput
|
|
117
|
+
label="Name"
|
|
118
|
+
required
|
|
119
|
+
validationStatus="invalid"
|
|
120
|
+
validationText="Please enter your name"
|
|
121
|
+
/>
|
|
122
|
+
</form>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Prefix and Suffix
|
|
126
|
+
|
|
127
|
+
To include a prefix or suffix in the `TextInput` you need to wrap the content
|
|
128
|
+
in the `InputSlot` component. You can then set the `placement` prop on the
|
|
129
|
+
`InputSlot` component to display it as either a `prefix` or a `suffix`.
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<Flex direction="column" gap="400">
|
|
133
|
+
<TextInput {...args}>
|
|
134
|
+
<InputSlot placement="prefix">
|
|
135
|
+
<BodyText size="md" weight="semibold">
|
|
136
|
+
£
|
|
137
|
+
</BodyText>
|
|
138
|
+
</InputSlot>
|
|
139
|
+
</TextInput>
|
|
140
|
+
<TextInput {...args}>
|
|
141
|
+
<InputSlot placement="suffix">
|
|
142
|
+
<BodyText size="md" weight="semibold">
|
|
143
|
+
kWh
|
|
144
|
+
</BodyText>
|
|
145
|
+
</InputSlot>
|
|
146
|
+
</TextInput>
|
|
147
|
+
</Flex>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
You can do the same with icons.
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
<TextInput {...args}>
|
|
154
|
+
<InputSlot placement="prefix">
|
|
155
|
+
<EmailMediumIcon />
|
|
156
|
+
</InputSlot>
|
|
157
|
+
</TextInput>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Grouping inputs
|
|
161
|
+
|
|
162
|
+
When grouping inputs you should
|
|
163
|
+
[use the `fieldset` and `legend` elements](https://accessibility.blog.gov.uk/2016/07/22/using-the-fieldset-and-legend-elements/).
|
|
164
|
+
This will ensure the group title is properly associated with child input
|
|
165
|
+
elements. Make sure you place the `legend` element as the first child of the
|
|
166
|
+
`fieldset` otherwise the relationship is broken. If this is not possible, you
|
|
167
|
+
can use `aria-label` or `aria-labelledby` to create the relationship.
|
|
168
|
+
|
|
169
|
+
If you are also including supporting text, then this should be associated with
|
|
170
|
+
each individual input, rather than with the grouping fieldset.
|
|
171
|
+
|
|
172
|
+
Please take the time to test what you build with a screen reader.
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<Flex asChild direction="column">
|
|
176
|
+
<fieldset>
|
|
177
|
+
<legend>
|
|
178
|
+
<Heading as="h3" size="lg" marginBottom="200">
|
|
179
|
+
Grouping Inputs
|
|
180
|
+
</Heading>
|
|
181
|
+
</legend>
|
|
182
|
+
<BodyText size="md" marginBottom="250" id="supporting-info">
|
|
183
|
+
Supporting information
|
|
184
|
+
</BodyText>
|
|
185
|
+
<Card variant="subtle" direction="column" gap="250">
|
|
186
|
+
<TextInput label="First name" required aria-describedby="supporting-info" />
|
|
187
|
+
<TextInput label="Last name" required aria-describedby="supporting-info" />
|
|
188
|
+
<TextInput
|
|
189
|
+
label="Email"
|
|
190
|
+
helperText="this is the helper text"
|
|
191
|
+
aria-describedby="supporting-info"
|
|
192
|
+
>
|
|
193
|
+
<InputSlot placement="prefix">
|
|
194
|
+
<EmailMediumIcon />
|
|
195
|
+
</InputSlot>
|
|
196
|
+
</TextInput>
|
|
197
|
+
</Card>
|
|
198
|
+
</fieldset>
|
|
199
|
+
</Flex>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## API
|
|
203
|
+
|
|
204
|
+
This component is based on the `input` element and supports the following common props:
|
|
205
|
+
|
|
206
|
+
- Margin
|
|
207
|
+
|
|
208
|
+
| Prop | Type | Default | Description |
|
|
209
|
+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------- |
|
|
210
|
+
| `label` | `string` | — | The label for the form field, describing its purpose. |
|
|
211
|
+
| `defaultValue` | `string \| number` | — | The initial value of the input when rendered. |
|
|
212
|
+
| `type` | `"number" \| "search" \| "text" \| "email" \| "password" \| "tel" \| "url"` | — | |
|
|
213
|
+
| `value` | `string \| number` | — | The controlled value of the input. Must be used with an `onChange` handler. |
|
|
214
|
+
| `labelId` | `string` | — | |
|
|
215
|
+
| `helperTextId` | `string` | — | |
|
|
216
|
+
| `validationTextId` | `string` | — | |
|
|
217
|
+
| `hideLabel` | `boolean` | — | Visually hide the label. |
|
|
218
|
+
| `labelVariant` | `"body" \| "heading"` | — | Change the label variant |
|
|
219
|
+
| `helperText` | `string` | — | Optional helper text to provide additional context or instructions. |
|
|
220
|
+
| `validationText` | `string` | — | Text to display when the `validationStatus` is set. |
|
|
221
|
+
| `validationStatus` | `"valid" \| "invalid"` | — | Indicates the validation status. |
|
|
222
|
+
| `margin` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
223
|
+
| `marginTop` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
224
|
+
| `marginRight` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
225
|
+
| `marginBottom` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
226
|
+
| `marginLeft` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
227
|
+
| `marginX` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
228
|
+
| `marginY` | `Responsive<"auto" \| "0" \| "25" \| "50" \| "75" \| "100" \| "150" \| "175" \| "200" \| "250" \| "300" \| "350" \| "400" \| "500" \| "600" \| "700" \| "800" \| "900" \| "1000" \| `var(--h-${string})`>` | — | |
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# Toast
|
|
2
|
+
|
|
3
|
+
A `Toast` is a brief, non-intrusive message that appears temporarily to provide feedback on an action or notify users of important information. Toasts automatically dismiss after a set duration or can be dismissed manually.
|
|
4
|
+
|
|
5
|
+
- [Usage](#usage)
|
|
6
|
+
- [Icon](#icon)
|
|
7
|
+
- [Dismiss toast](#dismiss-toast)
|
|
8
|
+
- [Actions](#actions)
|
|
9
|
+
- [Custom duration](#custom-duration)
|
|
10
|
+
- [Accessibility](#accessibility)
|
|
11
|
+
- [Sensitivity](#sensitivity)
|
|
12
|
+
- [Keyboard interactions](#keyboard-interactions)
|
|
13
|
+
- [Duplicate toasts](#duplicate-toasts)
|
|
14
|
+
- [API](#api)
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
<div>
|
|
18
|
+
<Button
|
|
19
|
+
onClick={() => {
|
|
20
|
+
setOpen(false);
|
|
21
|
+
window.clearTimeout(timerRef.current);
|
|
22
|
+
timerRef.current = window.setTimeout(() => {
|
|
23
|
+
setOpen(true);
|
|
24
|
+
}, 100);
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
Show Toast
|
|
28
|
+
</Button>
|
|
29
|
+
<Toast open={open} onOpenChange={setOpen} icon={<TickCircleMediumIcon />} {...args}>
|
|
30
|
+
<ToastActionLink href="#" altText="Visit #">
|
|
31
|
+
Link
|
|
32
|
+
</ToastActionLink>
|
|
33
|
+
</Toast>
|
|
34
|
+
</div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
When using toasts you must first wrap your usage in a provider. It usually
|
|
40
|
+
makes sense to do this at the root of the application.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { ToastProvider } from '@utilitywarehouse/hearth-react';
|
|
44
|
+
|
|
45
|
+
[...]
|
|
46
|
+
|
|
47
|
+
<ToastProvider>
|
|
48
|
+
{children}
|
|
49
|
+
</ToastProvider>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You can then render your toast:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<Toast description="Toast description" />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Icon
|
|
59
|
+
|
|
60
|
+
Include an icon using the `icon` prop:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { Toast } from '@utilitywarehouse/hearth-react';
|
|
64
|
+
import { TickCircleMediumIcon } from '@utilitywarehouse/hearth-react-icons';
|
|
65
|
+
|
|
66
|
+
[...]
|
|
67
|
+
|
|
68
|
+
<Toast
|
|
69
|
+
description='With icon'
|
|
70
|
+
icon={<TickCircleMediumIcon />}
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Dismiss toast
|
|
75
|
+
|
|
76
|
+
A dismiss button can be included.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
<Toast description="Show dismiss button" showDismissButton />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Users can also swipe down on any toast to dismiss it immediately.
|
|
83
|
+
|
|
84
|
+
## Actions
|
|
85
|
+
|
|
86
|
+
You can include an `action` using the `ToastActionLink` or `ToastActionButton`
|
|
87
|
+
components as children. Only use one per toast.
|
|
88
|
+
|
|
89
|
+
The action should be safe to ignore so that users are not expected to complete
|
|
90
|
+
tasks with unexpected side effects as a result of a time limit. You can direct
|
|
91
|
+
the user to a permanent place in your application where they can action it. Use
|
|
92
|
+
foreground type to announce immediately and increase the duration to give the
|
|
93
|
+
user ample time.
|
|
94
|
+
|
|
95
|
+
When obtaining a user response is necessary, consider using an `Alert` instead.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
<Toast
|
|
99
|
+
type="foreground"
|
|
100
|
+
duration={10000}
|
|
101
|
+
description="You can change your details anytime"
|
|
102
|
+
>
|
|
103
|
+
<ToastActionLink
|
|
104
|
+
href="/account-settings"
|
|
105
|
+
altText="Visit account settings to change your details"
|
|
106
|
+
>
|
|
107
|
+
Account settings
|
|
108
|
+
</ToastActionLink>
|
|
109
|
+
</Toast>
|
|
110
|
+
|
|
111
|
+
[...]
|
|
112
|
+
|
|
113
|
+
<Toast
|
|
114
|
+
type="foreground"
|
|
115
|
+
duration={10000}
|
|
116
|
+
description="Settings updated"
|
|
117
|
+
>
|
|
118
|
+
<ToastActionButton altText="Go to settings to undo">Undo</ToastActionButton>
|
|
119
|
+
</Toast>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<div>
|
|
124
|
+
<Flex gap="400">
|
|
125
|
+
<Button
|
|
126
|
+
onClick={() => {
|
|
127
|
+
setOpenLinkActionToast(false);
|
|
128
|
+
window.clearTimeout(linkActionTimerRef.current);
|
|
129
|
+
linkActionTimerRef.current = window.setTimeout(() => {
|
|
130
|
+
setOpenLinkActionToast(true);
|
|
131
|
+
}, 100);
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
Show Link Action Toast
|
|
135
|
+
</Button>
|
|
136
|
+
<Button
|
|
137
|
+
onClick={() => {
|
|
138
|
+
setOpenButtonActionToast(false);
|
|
139
|
+
window.clearTimeout(buttonActionTimerRef.current);
|
|
140
|
+
buttonActionTimerRef.current = window.setTimeout(() => {
|
|
141
|
+
setOpenButtonActionToast(true);
|
|
142
|
+
}, 100);
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
145
|
+
Show Button Action Toast
|
|
146
|
+
</Button>
|
|
147
|
+
</Flex>
|
|
148
|
+
<Toast
|
|
149
|
+
type="foreground"
|
|
150
|
+
duration={10000}
|
|
151
|
+
description="You can change your details anytime"
|
|
152
|
+
open={openLinkActionToast}
|
|
153
|
+
onOpenChange={setOpenLinkActionToast}
|
|
154
|
+
>
|
|
155
|
+
<ToastActionLink
|
|
156
|
+
href="/account-settings"
|
|
157
|
+
altText="Visit account settings to change your details"
|
|
158
|
+
>
|
|
159
|
+
Account settings
|
|
160
|
+
</ToastActionLink>
|
|
161
|
+
</Toast>
|
|
162
|
+
<Toast
|
|
163
|
+
type="foreground"
|
|
164
|
+
duration={10000}
|
|
165
|
+
description="Settings updated"
|
|
166
|
+
open={openButtonActionToast}
|
|
167
|
+
onOpenChange={setOpenButtonActionToast}
|
|
168
|
+
>
|
|
169
|
+
<ToastActionButton altText="Go to settings to undo">Undo</ToastActionButton>
|
|
170
|
+
</Toast>
|
|
171
|
+
</div>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Custom duration
|
|
175
|
+
|
|
176
|
+
The default duration of 5 seconds is set on the `ToastProvider`, you
|
|
177
|
+
can override this on the provider, or setting this on the individual toast will
|
|
178
|
+
override the global default.
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<Toast duration={10000} description="Custom toast duration of 10 seconds" />
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Accessibility
|
|
185
|
+
|
|
186
|
+
Adheres to the [aria-live requirements](https://www.w3.org/TR/wai-aria/#aria-live)
|
|
187
|
+
|
|
188
|
+
### Sensitivity
|
|
189
|
+
|
|
190
|
+
You can control the sensitivity of the toast for screen readers, using the `type` prop.
|
|
191
|
+
|
|
192
|
+
For toasts that are the result of a user action, choose `foreground`. Toasts
|
|
193
|
+
generated from background tasks should use `background`. The default type is
|
|
194
|
+
`foreground`.
|
|
195
|
+
|
|
196
|
+
Foreground toasts are announced immediately. Assistive technologies may choose
|
|
197
|
+
to clear previously queued messages when a foreground toast appears. Try to
|
|
198
|
+
avoid stacking distinct foreground toasts at the same time.
|
|
199
|
+
|
|
200
|
+
Background toasts are announced at the next graceful opportunity, for example,
|
|
201
|
+
when the screen reader has finished reading its current sentence. They do not
|
|
202
|
+
clear queued messages so overusing them can be perceived as a laggy user
|
|
203
|
+
experience for screen reader users when used in response to a user interaction.
|
|
204
|
+
|
|
205
|
+
### Keyboard interactions
|
|
206
|
+
|
|
207
|
+
<Flex direction="column" gap="200" className="sb-unstyled">
|
|
208
|
+
<Flex>
|
|
209
|
+
<Box width="300px">
|
|
210
|
+
<BodyText as="span" weight="bold">
|
|
211
|
+
Key
|
|
212
|
+
</BodyText>
|
|
213
|
+
</Box>
|
|
214
|
+
<BodyText as="span" weight="bold">
|
|
215
|
+
Description
|
|
216
|
+
</BodyText>
|
|
217
|
+
</Flex>
|
|
218
|
+
<Divider />
|
|
219
|
+
{[
|
|
220
|
+
{
|
|
221
|
+
key: 'F8',
|
|
222
|
+
description: 'Focuses toasts viewport.',
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
key: 'Tab',
|
|
226
|
+
description: 'Moves focus to the next focusable element.',
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
key: 'Shift+Tab',
|
|
230
|
+
description: 'Moves focus to the previous focusable element.',
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
key: 'Space',
|
|
234
|
+
description:
|
|
235
|
+
'When focus is on a Toast action component or the Toast dismiss button, closes the toast.',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
key: 'Enter',
|
|
239
|
+
description:
|
|
240
|
+
'When focus is on a Toast action component or the Toast dismiss button, closes the toast.',
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
key: 'Esc',
|
|
244
|
+
description: 'When focus is on a Toast, closes the toast.',
|
|
245
|
+
},
|
|
246
|
+
].map((kbi, i) => (
|
|
247
|
+
<>
|
|
248
|
+
<Flex>
|
|
249
|
+
<Box width="300px">
|
|
250
|
+
<kbd>{kbi.key}</kbd>
|
|
251
|
+
</Box>
|
|
252
|
+
<BodyText as="span">{kbi.description}</BodyText>
|
|
253
|
+
</Flex>
|
|
254
|
+
{i < 5 ? <Divider /> : null}
|
|
255
|
+
</>
|
|
256
|
+
))}
|
|
257
|
+
</Flex>
|
|
258
|
+
|
|
259
|
+
## Duplicate toasts
|
|
260
|
+
|
|
261
|
+
When a toast must appear every time a user clicks a button, use state to render
|
|
262
|
+
multiple instances of the same toast. Toasts will stack vertically with the
|
|
263
|
+
newest appearing at the bottom.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
const [savedCount, setSavedCount] = React.useState(0);
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<div>
|
|
270
|
+
<Button onClick={() => setSavedCount(count => count + 1)}>Save</Button>
|
|
271
|
+
|
|
272
|
+
{Array.from({ length: savedCount }).map((_, index) => (
|
|
273
|
+
<Toast key={index} description={`Saved! (${index})`} showDismissButton />
|
|
274
|
+
))}
|
|
275
|
+
</div>
|
|
276
|
+
);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### ToastProvider
|
|
280
|
+
|
|
281
|
+
This component is based on [Radix UI's Toast primitive](https://www.radix-ui.com/primitives/docs/components/toast).
|
|
282
|
+
|
|
283
|
+
| Prop | Type | Default | Description |
|
|
284
|
+
| ---------------- | ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
285
|
+
| `viewportLabel` | `string` | — | |
|
|
286
|
+
| `viewportHotkey` | `string[]` | — | |
|
|
287
|
+
| `label` | `string` | — | An author-localized label for each toast. Used to help screen reader users associate the interruption with a toast. @defaultValue 'Notification' |
|
|
288
|
+
| `duration` | `number` | `5000` | Time in milliseconds that each toast should remain visible for. @defaultValue 5000 |
|
|
289
|
+
|
|
290
|
+
### Toast
|
|
291
|
+
|
|
292
|
+
This component is based on [Radix UI's Toast primitive](https://www.radix-ui.com/primitives/docs/components/toast).
|
|
293
|
+
|
|
294
|
+
| Prop | Type | Default | Description |
|
|
295
|
+
| ------------------- | ---------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- |
|
|
296
|
+
| `open` | `boolean` | — | |
|
|
297
|
+
| `onPause` | `(() => void)` | — | |
|
|
298
|
+
| `type` | `"foreground" \| "background"` | — | |
|
|
299
|
+
| `duration` | `number` | — | Time in milliseconds that toast should remain visible for. Overrides value given to `ToastProvider`. |
|
|
300
|
+
| `onEscapeKeyDown` | `((event: KeyboardEvent) => void)` | — | |
|
|
301
|
+
| `onResume` | `(() => void)` | — | |
|
|
302
|
+
| `onSwipeStart` | `((event: SwipeEvent) => void)` | — | |
|
|
303
|
+
| `onSwipeMove` | `((event: SwipeEvent) => void)` | — | |
|
|
304
|
+
| `onSwipeCancel` | `((event: SwipeEvent) => void)` | — | |
|
|
305
|
+
| `onSwipeEnd` | `((event: SwipeEvent) => void)` | — | |
|
|
306
|
+
| `defaultOpen` | `boolean` | — | |
|
|
307
|
+
| `onOpenChange` | `((open: boolean) => void)` | — | |
|
|
308
|
+
| `description` | `ReactNode` | — | |
|
|
309
|
+
| `icon` | `ReactNode` | — | |
|
|
310
|
+
| `showDismissButton` | `boolean` | — | |
|
|
311
|
+
|
|
312
|
+
### ToastActionLink
|
|
313
|
+
|
|
314
|
+
This component is based on the `a` element and [Radix UI's Toast primitive](https://www.radix-ui.com/primitives/docs/components/toast).
|
|
315
|
+
|
|
316
|
+
| Prop | Type | Default | Description |
|
|
317
|
+
| --------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
318
|
+
| `asChild` | `boolean` | — | |
|
|
319
|
+
| `altText` | `string` | — | A short description for an alternate way to carry out the action. For screen reader users who will not be able to navigate to the button easily/quickly. @example <ToastAction altText="Goto account settings to upgrade">Upgrade</ToastAction> @example <ToastAction altText="Undo (Alt+U)">Undo</ToastAction> |
|
|
320
|
+
|
|
321
|
+
### ToastActionButton
|
|
322
|
+
|
|
323
|
+
This component is based on the `button` element and [Radix UI's Toast primitive](https://www.radix-ui.com/primitives/docs/components/toast).
|