-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathAlertDialog.doc.mjs
More file actions
232 lines (229 loc) · 8.52 KB
/
Copy pathAlertDialog.doc.mjs
File metadata and controls
232 lines (229 loc) · 8.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// Copyright (c) Meta Platforms, Inc. and affiliates.
/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
export const docs = {
name: 'AlertDialog',
displayName: 'Alert Dialog',
group: 'Dialog',
category: 'Overlay',
isHiddenFromOverview: true,
keywords: [
'alert',
'alertdialog',
'confirm',
'confirmation',
'destructive',
'delete',
'modal',
'dialog',
'imperative',
],
usage: {
description:
'AlertDialog asks the user to confirm a destructive or irreversible action before it happens. Use it for things like deleting content, revoking access, or discarding unsaved changes.\n\nIt implements the WAI-ARIA APG [Alert Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): `role="alertdialog"`, a title linked by `aria-labelledby`, a consequence description linked by `aria-describedby`, focus moved into the dialog on open and returned to the trigger on close, and no dismissal by clicking outside. Escape cancels.\n\nAt widths above 640px, AlertDialog keeps its requested width and horizontal Cancel/destructive actions. At 640px and below, the surface fills the viewport with token gutters, the destructive action appears above Cancel, and complete labels wrap. Geometry follows available width, not pointer or hover capability. The body scrolls when block space is constrained.\n\nFor cases where you want to show an alert without managing open state, use the `useImperativeAlertDialog` hook: call `alert.show(options)` and render `alert.element` in your tree.',
bestPractices: [
{
guidance: true,
description:
'Make the action button label specific: "Delete project" is better than "OK" or "Confirm".',
},
{
guidance: true,
description:
'Describe what will happen in the description so the user knows the consequences before confirming.',
},
{
guidance: true,
description:
'Keep the cancel button first: it takes initial focus, so the least destructive choice is the one already selected when the dialog opens.',
},
{
guidance: true,
description:
'Use complete action labels. At 640px and below, the destructive action appears above Cancel and both labels wrap instead of truncating, regardless of pointer type.',
},
{
guidance: false,
description:
'Use AlertDialog for non-destructive actions; use a standard Dialog instead.',
},
{
guidance: false,
description:
'Rely on color alone to signal danger; the action label itself should say what will happen.',
},
{
guidance: false,
description:
'Close the dialog from onAction before the work finishes; hold it open with isActionLoading and call onOpenChange(false) when the action settles.',
},
],
anatomy: [
{
name: 'Title',
required: true,
description:
'The question being asked. Renders as a level-2 heading and labels the dialog via aria-labelledby.',
},
{
name: 'Description',
required: true,
description:
'What will happen if the user confirms. Linked to the dialog via aria-describedby.',
},
{
name: 'Cancel button',
required: true,
description:
'Ghost button that dismisses without acting. Takes initial focus, and Escape does the same thing.',
},
{
name: 'Action button',
required: true,
description:
'The confirming action. Destructive by default; shows a spinner while isActionLoading is set.',
},
{
name: 'Backdrop',
required: true,
description:
'Overlay behind the dialog that blocks page interaction. Clicking it does not dismiss.',
},
],
},
// Intentionally a contained isInline preview, not playground.overlay: the
// component stays visible on load and knobs stay live, whereas a real
// showModal() overlay makes the page inert — see ComponentPlaygroundConfig.overlay
// in docs-types.ts (#3657).
playground: {
defaults: {
isOpen: true,
isInline: true,
onOpenChange: undefined,
title: 'Delete item?',
description:
'This action cannot be undone. The item and all its data will be permanently removed.',
actionLabel: 'Delete',
},
},
description:
'A modal dialog that asks the user to confirm a destructive action.',
props: [
{
name: 'isOpen',
type: 'boolean',
required: true,
description: 'Whether the dialog is open.',
},
{
name: 'onOpenChange',
type: '(isOpen: boolean) => unknown',
required: true,
description: 'Visibility change callback.',
},
{
name: 'title',
type: 'string',
required: true,
description: 'Dialog title. Linked via aria-labelledby.',
},
{
name: 'description',
type: 'string',
required: true,
description: 'Consequence description. Linked via aria-describedby.',
},
{
name: 'actionLabel',
type: 'string',
required: true,
description: 'Action button label.',
},
{
name: 'onAction',
type: '() => unknown',
required: true,
description: 'Called when action button is clicked. Does NOT auto-close.',
},
{
name: 'cancelLabel',
type: 'string',
default: "'Cancel'",
description: 'Cancel button label.',
},
{
name: 'actionVariant',
type: 'ButtonVariant',
default: "'destructive'",
description: 'Action button variant.',
},
{
name: 'isActionLoading',
type: 'boolean',
description: 'Shows loading spinner on the action button.',
},
{
name: 'width',
type: 'number | string',
default: '400',
description:
'Requested dialog width above 640px. At 640px and below, the dialog fills available width with token gutters regardless of pointer type.',
},
{
name: 'isInline',
type: 'boolean',
default: 'false',
description:
'Renders alert dialog content inline without modal behavior. For documentation previews and showcases only. Not being a modal, the inline path renders role="group" instead of role="alertdialog".',
},
],
components: [{name: 'useImperativeAlertDialog'}],
theming: {
targets: [{className: 'astryx-alert-dialog'}],
},
};
/** @type {import('@astryxdesign/cli/authoring').ComponentTranslationDoc} */
export const docsDense = {
description:
'Confirms destructive/irreversible action before it happens (delete, revoke access, discard unsaved changes).',
usage: {
description:
'AlertDialog confirms destructive/irreversible action (delete, revoke access, discard changes). Implements WAI-ARIA APG Alert Dialog pattern (https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): role="alertdialog", aria-labelledby title, aria-describedby description, focus into dialog on open + back to trigger on close, no outside-click dismissal, Escape cancels. >640px keeps requested width + horizontal actions. <=640px fills w/ token gutters, puts destructive action above Cancel, and wraps labels regardless of pointer/hover capability. Body scrolls when height constrained. To show w/o managing open state, use useImperativeAlertDialog hook: call alert.show(options) + render alert.element in tree.',
bestPractices: [
{
guidance: true,
description:
'Make action button label specific: "Delete project" > "OK"/"Confirm".',
},
{
guidance: true,
description:
'Describe consequences in description so user knows outcome before confirming.',
},
{
guidance: true,
description:
'Keep cancel first: it takes initial focus, so least destructive choice is preselected.',
},
{
guidance: true,
description:
'Use complete action labels; <=640px puts the destructive action above Cancel and allows wrapping regardless of pointer type.',
},
{
guidance: false,
description:
'Use AlertDialog for non-destructive actions; use standard Dialog instead.',
},
{
guidance: false,
description:
'Rely on color alone for danger; the action label should say what happens.',
},
{
guidance: false,
description:
'Close from onAction before work finishes; hold open w/ isActionLoading, call onOpenChange(false) when it settles.',
},
],
},
};