@ui-sdk/vue 0.0.0-stage → 0.1.0-beta.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/LICENSE +202 -0
- package/README.md +10 -2
- package/dist/accordion.d.ts +561 -0
- package/dist/accordion.js +24 -0
- package/dist/agent.d.ts +2 -0
- package/dist/agent.js +7 -0
- package/dist/alert-dialog.d.ts +231 -0
- package/dist/alert-dialog.js +33 -0
- package/dist/async-options.d.ts +18 -0
- package/dist/async-options.js +40 -0
- package/dist/autocomplete.d.ts +384 -0
- package/dist/autocomplete.js +344 -0
- package/dist/avatar.d.ts +40 -0
- package/dist/avatar.js +28 -0
- package/dist/button.d.ts +52 -0
- package/dist/button.js +43 -0
- package/dist/calendar-context.d.ts +10 -0
- package/dist/calendar-context.js +7 -0
- package/dist/calendar.d.ts +311 -0
- package/dist/calendar.js +349 -0
- package/dist/carousel.d.ts +236 -0
- package/dist/carousel.js +204 -0
- package/dist/checkbox.d.ts +211 -0
- package/dist/checkbox.js +151 -0
- package/dist/children.d.ts +41 -0
- package/dist/children.js +135 -0
- package/dist/collapsible.d.ts +54 -0
- package/dist/collapsible.js +18 -0
- package/dist/color-picker.d.ts +187 -0
- package/dist/color-picker.js +158 -0
- package/dist/color.d.ts +2 -0
- package/dist/color.js +21 -0
- package/dist/combobox.d.ts +517 -0
- package/dist/combobox.js +531 -0
- package/dist/command.d.ts +322 -0
- package/dist/command.js +345 -0
- package/dist/controller-target.d.ts +49 -0
- package/dist/controller-target.js +112 -0
- package/dist/create-parts.d.ts +126 -0
- package/dist/create-parts.js +206 -0
- package/dist/date-input.d.ts +133 -0
- package/dist/date-input.js +31 -0
- package/dist/date-picker.d.ts +328 -0
- package/dist/date-picker.js +354 -0
- package/dist/date.d.ts +2 -0
- package/dist/date.js +59 -0
- package/dist/dialog-parts.d.ts +259 -0
- package/dist/dialog-parts.js +300 -0
- package/dist/dialog.d.ts +251 -0
- package/dist/dialog.js +25 -0
- package/dist/drawer.d.ts +304 -0
- package/dist/drawer.js +373 -0
- package/dist/editor-context.d.ts +4 -0
- package/dist/editor-context.js +5 -0
- package/dist/field-context.d.ts +26 -0
- package/dist/field-context.js +44 -0
- package/dist/field.d.ts +154 -0
- package/dist/field.js +240 -0
- package/dist/file-input.d.ts +212 -0
- package/dist/file-input.js +255 -0
- package/dist/form-inputs.d.ts +16 -0
- package/dist/form-inputs.js +25 -0
- package/dist/gesture.d.ts +1 -0
- package/dist/gesture.js +15 -0
- package/dist/history.d.ts +2 -0
- package/dist/history.js +11 -0
- package/dist/hover-card.d.ts +137 -0
- package/dist/hover-card.js +153 -0
- package/dist/image-cropper.d.ts +74 -0
- package/dist/image-cropper.js +36 -0
- package/dist/image.d.ts +2 -0
- package/dist/image.js +5 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +60 -0
- package/dist/input.d.ts +120 -0
- package/dist/input.js +73 -0
- package/dist/item-icon.d.ts +34 -0
- package/dist/item-icon.js +63 -0
- package/dist/label.d.ts +16 -0
- package/dist/label.js +8 -0
- package/dist/lifecycle.d.ts +11 -0
- package/dist/lifecycle.js +91 -0
- package/dist/list-items.d.ts +38 -0
- package/dist/list-items.js +59 -0
- package/dist/list-text.d.ts +7 -0
- package/dist/list-text.js +15 -0
- package/dist/listbox.d.ts +273 -0
- package/dist/listbox.js +126 -0
- package/dist/menu.d.ts +678 -0
- package/dist/menu.js +607 -0
- package/dist/menubar-context.d.ts +5 -0
- package/dist/menubar-context.js +5 -0
- package/dist/menubar.d.ts +61 -0
- package/dist/menubar.js +48 -0
- package/dist/meter.d.ts +41 -0
- package/dist/meter.js +37 -0
- package/dist/navigation-menu.d.ts +228 -0
- package/dist/navigation-menu.js +195 -0
- package/dist/number-input.d.ts +176 -0
- package/dist/number-input.js +231 -0
- package/dist/number.d.ts +2 -0
- package/dist/number.js +39 -0
- package/dist/nuxt/entries.json +977 -0
- package/dist/nuxt/module.d.ts +18 -0
- package/dist/nuxt/module.js +31 -0
- package/dist/nuxt/registrations.d.ts +22 -0
- package/dist/nuxt/registrations.js +22 -0
- package/dist/observe.d.ts +2 -0
- package/dist/observe.js +7 -0
- package/dist/otp-input.d.ts +142 -0
- package/dist/otp-input.js +130 -0
- package/dist/overlays.d.ts +40 -0
- package/dist/overlays.js +118 -0
- package/dist/pagination.d.ts +201 -0
- package/dist/pagination.js +146 -0
- package/dist/password-input.d.ts +144 -0
- package/dist/password-input.js +134 -0
- package/dist/popover.d.ts +211 -0
- package/dist/popover.js +258 -0
- package/dist/popup.d.ts +60 -0
- package/dist/popup.js +89 -0
- package/dist/preferences.d.ts +44 -0
- package/dist/preferences.js +102 -0
- package/dist/primitive.d.ts +2 -0
- package/dist/primitive.js +11 -0
- package/dist/progress.d.ts +41 -0
- package/dist/progress.js +37 -0
- package/dist/radio.d.ts +164 -0
- package/dist/radio.js +145 -0
- package/dist/rating.d.ts +149 -0
- package/dist/rating.js +146 -0
- package/dist/renderless.d.ts +4 -0
- package/dist/renderless.js +28 -0
- package/dist/resizable.d.ts +54 -0
- package/dist/resizable.js +22 -0
- package/dist/scroll-area.d.ts +72 -0
- package/dist/scroll-area.js +77 -0
- package/dist/segmented-control.d.ts +151 -0
- package/dist/segmented-control.js +110 -0
- package/dist/segmented-input.d.ts +76 -0
- package/dist/segmented-input.js +115 -0
- package/dist/select.d.ts +458 -0
- package/dist/select.js +468 -0
- package/dist/separator.d.ts +14 -0
- package/dist/separator.js +8 -0
- package/dist/shortcuts.d.ts +32 -0
- package/dist/shortcuts.js +56 -0
- package/dist/slider.d.ts +65 -0
- package/dist/slider.js +194 -0
- package/dist/switch.d.ts +103 -0
- package/dist/switch.js +71 -0
- package/dist/tabs.d.ts +338 -0
- package/dist/tabs.js +27 -0
- package/dist/text-control.d.ts +89 -0
- package/dist/text-control.js +51 -0
- package/dist/text-match.d.ts +2 -0
- package/dist/text-match.js +7 -0
- package/dist/textarea.d.ts +106 -0
- package/dist/textarea.js +68 -0
- package/dist/time-input.d.ts +131 -0
- package/dist/time-input.js +32 -0
- package/dist/timeline.d.ts +81 -0
- package/dist/timeline.js +30 -0
- package/dist/toast-parts.d.ts +203 -0
- package/dist/toast-parts.js +270 -0
- package/dist/toast.d.ts +2 -0
- package/dist/toast.js +21 -0
- package/dist/toggle-props.d.ts +22 -0
- package/dist/toggle-props.js +14 -0
- package/dist/toggle.d.ts +199 -0
- package/dist/toggle.js +129 -0
- package/dist/token-input.d.ts +136 -0
- package/dist/token-input.js +214 -0
- package/dist/toolbar-context.d.ts +7 -0
- package/dist/toolbar-context.js +20 -0
- package/dist/toolbar.d.ts +120 -0
- package/dist/toolbar.js +77 -0
- package/dist/tooltip.d.ts +160 -0
- package/dist/tooltip.js +224 -0
- package/dist/tree.d.ts +300 -0
- package/dist/tree.js +209 -0
- package/dist/trigger-menu.d.ts +452 -0
- package/dist/trigger-menu.js +254 -0
- package/dist/use-primitive.d.ts +132 -0
- package/dist/use-primitive.js +462 -0
- package/dist/waterfall.d.ts +201 -0
- package/dist/waterfall.js +171 -0
- package/docs/README.md +89 -0
- package/docs/agents.md +1523 -0
- package/docs/components/accordion.md +1369 -0
- package/docs/components/alert-dialog.md +799 -0
- package/docs/components/autocomplete.md +1857 -0
- package/docs/components/avatar.md +272 -0
- package/docs/components/button.md +435 -0
- package/docs/components/calendar.md +1589 -0
- package/docs/components/carousel.md +1171 -0
- package/docs/components/checkbox.md +1008 -0
- package/docs/components/collapsible.md +536 -0
- package/docs/components/color-picker.md +706 -0
- package/docs/components/combobox.md +3504 -0
- package/docs/components/command.md +1481 -0
- package/docs/components/date-input.md +536 -0
- package/docs/components/date-picker.md +1244 -0
- package/docs/components/dialog.md +1397 -0
- package/docs/components/drawer.md +1166 -0
- package/docs/components/field.md +538 -0
- package/docs/components/file-input.md +611 -0
- package/docs/components/hover-card.md +505 -0
- package/docs/components/image-cropper.md +556 -0
- package/docs/components/input.md +306 -0
- package/docs/components/label.md +203 -0
- package/docs/components/listbox.md +1004 -0
- package/docs/components/menu.md +1229 -0
- package/docs/components/menubar.md +443 -0
- package/docs/components/meter.md +315 -0
- package/docs/components/navigation-menu.md +1523 -0
- package/docs/components/number-input.md +1029 -0
- package/docs/components/otp-input.md +512 -0
- package/docs/components/pagination.md +613 -0
- package/docs/components/password-input.md +649 -0
- package/docs/components/popover.md +1448 -0
- package/docs/components/preferences.md +208 -0
- package/docs/components/progress.md +423 -0
- package/docs/components/radio.md +785 -0
- package/docs/components/rating.md +416 -0
- package/docs/components/resizable.md +910 -0
- package/docs/components/scroll-area.md +915 -0
- package/docs/components/segmented-control.md +435 -0
- package/docs/components/select.md +2015 -0
- package/docs/components/separator.md +229 -0
- package/docs/components/slider.md +1084 -0
- package/docs/components/switch.md +565 -0
- package/docs/components/tabs.md +944 -0
- package/docs/components/textarea.md +299 -0
- package/docs/components/time-input.md +224 -0
- package/docs/components/timeline.md +654 -0
- package/docs/components/toast.md +1224 -0
- package/docs/components/toggle.md +500 -0
- package/docs/components/token-input.md +953 -0
- package/docs/components/toolbar.md +739 -0
- package/docs/components/tooltip.md +818 -0
- package/docs/components/tree.md +1306 -0
- package/docs/components/trigger-menu.md +1223 -0
- package/docs/components/waterfall.md +717 -0
- package/docs/controllers.md +71 -0
- package/docs/core.md +8027 -0
- package/docs/custom-parts.md +89 -0
- package/docs/first-component.md +83 -0
- package/docs/forms.md +122 -0
- package/docs/installation.md +72 -0
- package/docs/introduction.md +32 -0
- package/docs/lists-and-menus.md +122 -0
- package/docs/llms.txt +1502 -0
- package/docs/parts-and-composition.md +85 -0
- package/docs/popups.md +108 -0
- package/docs/rendering.md +56 -0
- package/docs/server-rendering.md +180 -0
- package/docs/state-and-events.md +100 -0
- package/docs/styling-and-animation.md +148 -0
- package/docs/utilities/async-options.md +348 -0
- package/docs/utilities/shortcuts.md +159 -0
- package/package.json +352 -3
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
# Alert Dialog
|
|
2
|
+
|
|
3
|
+
Ask someone to confirm an action before you continue.
|
|
4
|
+
|
|
5
|
+
Use an alert dialog when someone needs to answer a question before an action continues, such as deleting a project.
|
|
6
|
+
|
|
7
|
+
```vue title="basic.vue"
|
|
8
|
+
<script setup lang="ts">
|
|
9
|
+
import {
|
|
10
|
+
AlertDialog,
|
|
11
|
+
AlertDialogBackdrop,
|
|
12
|
+
AlertDialogClose,
|
|
13
|
+
AlertDialogContent,
|
|
14
|
+
AlertDialogDescription,
|
|
15
|
+
AlertDialogTitle,
|
|
16
|
+
AlertDialogTrigger,
|
|
17
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<AlertDialog>
|
|
22
|
+
<AlertDialogTrigger>Delete Project</AlertDialogTrigger>
|
|
23
|
+
<AlertDialogBackdrop />
|
|
24
|
+
<AlertDialogContent>
|
|
25
|
+
<div data-slot="stack">
|
|
26
|
+
<AlertDialogTitle>Delete this project?</AlertDialogTitle>
|
|
27
|
+
<AlertDialogDescription>
|
|
28
|
+
This permanently deletes the project, its files and its deployment
|
|
29
|
+
history for everyone on your team.
|
|
30
|
+
</AlertDialogDescription>
|
|
31
|
+
</div>
|
|
32
|
+
<div data-slot="row">
|
|
33
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
34
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
35
|
+
>Delete</AlertDialogClose
|
|
36
|
+
>
|
|
37
|
+
</div>
|
|
38
|
+
</AlertDialogContent>
|
|
39
|
+
</AlertDialog>
|
|
40
|
+
</template>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Open the dialog with Enter to start on Cancel. Tab stays inside, clicking outside leaves it open, and Escape closes it and returns focus to the trigger.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @ui-sdk/vue @ui-sdk/core
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Composition
|
|
52
|
+
|
|
53
|
+
Use the following composition to build an `AlertDialog`:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
AlertDialog
|
|
57
|
+
├── AlertDialogTrigger
|
|
58
|
+
├── AlertDialogBackdrop
|
|
59
|
+
└── AlertDialogContent
|
|
60
|
+
├── AlertDialogTitle
|
|
61
|
+
├── AlertDialogDescription
|
|
62
|
+
├── AlertDialogClose
|
|
63
|
+
└── AlertDialogClose
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Put the question in `AlertDialogTitle`, explain what happens in `AlertDialogDescription`, and use `AlertDialogClose` for each answer. Add `AlertDialogBackdrop` to dim the page.
|
|
67
|
+
|
|
68
|
+
A Close part reports its `value` when it closes. `value="confirm"` is the agreeing answer that the [confirm helper](#confirm) recognizes.
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
Import the parts and put them together:
|
|
73
|
+
|
|
74
|
+
```vue
|
|
75
|
+
<script setup lang="ts">
|
|
76
|
+
import {
|
|
77
|
+
AlertDialog,
|
|
78
|
+
AlertDialogClose,
|
|
79
|
+
AlertDialogContent,
|
|
80
|
+
AlertDialogDescription,
|
|
81
|
+
AlertDialogTitle,
|
|
82
|
+
AlertDialogTrigger,
|
|
83
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
<AlertDialog>
|
|
88
|
+
<AlertDialogTrigger>Delete Project</AlertDialogTrigger>
|
|
89
|
+
<AlertDialogContent>
|
|
90
|
+
<AlertDialogTitle>Delete this project?</AlertDialogTitle>
|
|
91
|
+
<AlertDialogDescription
|
|
92
|
+
>The project and its files will be deleted for
|
|
93
|
+
everyone.</AlertDialogDescription
|
|
94
|
+
>
|
|
95
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
96
|
+
<AlertDialogClose value="confirm">Delete</AlertDialogClose>
|
|
97
|
+
</AlertDialogContent>
|
|
98
|
+
</AlertDialog>
|
|
99
|
+
</template>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Build Your Own
|
|
103
|
+
|
|
104
|
+
`@ui-sdk/vue/alert-dialog` comes with a ready-made Alert Dialog. If you'd like to build your own, with your own names, start from the `alertDialog` primitive in `@ui-sdk/core`:
|
|
105
|
+
|
|
106
|
+
```ts title="confirm.ts"
|
|
107
|
+
import { alertDialog } from "@ui-sdk/core/alert-dialog"
|
|
108
|
+
import { createParts } from "@ui-sdk/vue/primitive"
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
Root: Confirm,
|
|
112
|
+
Trigger: ConfirmTrigger,
|
|
113
|
+
Backdrop: ConfirmBackdrop,
|
|
114
|
+
Content: ConfirmContent,
|
|
115
|
+
Title: ConfirmTitle,
|
|
116
|
+
Description: ConfirmDescription,
|
|
117
|
+
Close: ConfirmClose,
|
|
118
|
+
} = createParts(alertDialog, {
|
|
119
|
+
trigger: "button",
|
|
120
|
+
backdrop: "div",
|
|
121
|
+
content: "div",
|
|
122
|
+
title: "h2",
|
|
123
|
+
description: "p",
|
|
124
|
+
close: "button",
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
Confirm,
|
|
129
|
+
ConfirmBackdrop,
|
|
130
|
+
ConfirmClose,
|
|
131
|
+
ConfirmContent,
|
|
132
|
+
ConfirmDescription,
|
|
133
|
+
ConfirmTitle,
|
|
134
|
+
ConfirmTrigger,
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```vue
|
|
139
|
+
<template>
|
|
140
|
+
<Confirm>
|
|
141
|
+
<ConfirmTrigger>Delete Project</ConfirmTrigger>
|
|
142
|
+
<ConfirmBackdrop />
|
|
143
|
+
<ConfirmContent>
|
|
144
|
+
<ConfirmTitle>Delete this project?</ConfirmTitle>
|
|
145
|
+
<ConfirmDescription
|
|
146
|
+
>This permanently deletes the project.</ConfirmDescription
|
|
147
|
+
>
|
|
148
|
+
<ConfirmClose>Cancel</ConfirmClose>
|
|
149
|
+
<ConfirmClose value="confirm">Delete</ConfirmClose>
|
|
150
|
+
</ConfirmContent>
|
|
151
|
+
</Confirm>
|
|
152
|
+
</template>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Each part keeps the behavior, state and data attributes of its ready-made counterpart: the content opens in the top layer, traps focus and makes the page inert. See [Rendering](../rendering.md) and [Custom Parts](../custom-parts.md) for more.
|
|
156
|
+
|
|
157
|
+
## Controlled
|
|
158
|
+
|
|
159
|
+
Use `v-model:open` when your app needs to read or control whether the dialog is open. [State and Events](../state-and-events.md) explains controlled state and canceling a change.
|
|
160
|
+
|
|
161
|
+
```vue title="controlled.vue"
|
|
162
|
+
<script setup lang="ts">
|
|
163
|
+
import {
|
|
164
|
+
AlertDialog,
|
|
165
|
+
AlertDialogBackdrop,
|
|
166
|
+
AlertDialogClose,
|
|
167
|
+
AlertDialogContent,
|
|
168
|
+
AlertDialogDescription,
|
|
169
|
+
AlertDialogTitle,
|
|
170
|
+
AlertDialogTrigger,
|
|
171
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
172
|
+
import { ref } from "vue"
|
|
173
|
+
|
|
174
|
+
const open = ref(false)
|
|
175
|
+
</script>
|
|
176
|
+
|
|
177
|
+
<template>
|
|
178
|
+
<div data-slot="stack">
|
|
179
|
+
<AlertDialog v-model:open="open">
|
|
180
|
+
<AlertDialogTrigger>Review Changes</AlertDialogTrigger>
|
|
181
|
+
<AlertDialogBackdrop />
|
|
182
|
+
<AlertDialogContent>
|
|
183
|
+
<div data-slot="stack">
|
|
184
|
+
<AlertDialogTitle>Discard unsaved changes?</AlertDialogTitle>
|
|
185
|
+
<AlertDialogDescription
|
|
186
|
+
>Your edits will be lost if you leave without
|
|
187
|
+
saving.</AlertDialogDescription
|
|
188
|
+
>
|
|
189
|
+
</div>
|
|
190
|
+
<div data-slot="row">
|
|
191
|
+
<AlertDialogClose>Keep Editing</AlertDialogClose>
|
|
192
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
193
|
+
>Discard</AlertDialogClose
|
|
194
|
+
>
|
|
195
|
+
</div>
|
|
196
|
+
</AlertDialogContent>
|
|
197
|
+
</AlertDialog>
|
|
198
|
+
</div>
|
|
199
|
+
</template>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Choose Review Changes, then Keep Editing or Discard.
|
|
203
|
+
|
|
204
|
+
## Shortcut
|
|
205
|
+
|
|
206
|
+
Give the trigger a `shortcut` to open the dialog from the keyboard, and put `AlertDialogShortcut` inside it to show the keys. [Dialog](./dialog.md#keyboard-shortcut) covers the shortcut syntax.
|
|
207
|
+
|
|
208
|
+
```vue title="shortcut.vue"
|
|
209
|
+
<script setup lang="ts">
|
|
210
|
+
import {
|
|
211
|
+
AlertDialog,
|
|
212
|
+
AlertDialogBackdrop,
|
|
213
|
+
AlertDialogClose,
|
|
214
|
+
AlertDialogContent,
|
|
215
|
+
AlertDialogDescription,
|
|
216
|
+
AlertDialogShortcut,
|
|
217
|
+
AlertDialogTitle,
|
|
218
|
+
AlertDialogTrigger,
|
|
219
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
<template>
|
|
223
|
+
<AlertDialog>
|
|
224
|
+
<AlertDialogTrigger shortcut="mod+shift+h">
|
|
225
|
+
Clear History
|
|
226
|
+
<AlertDialogShortcut />
|
|
227
|
+
</AlertDialogTrigger>
|
|
228
|
+
<AlertDialogBackdrop />
|
|
229
|
+
<AlertDialogContent>
|
|
230
|
+
<div data-slot="stack">
|
|
231
|
+
<AlertDialogTitle>Clear your history?</AlertDialogTitle>
|
|
232
|
+
<AlertDialogDescription>
|
|
233
|
+
Recent searches and visited pages are removed from this device.
|
|
234
|
+
</AlertDialogDescription>
|
|
235
|
+
</div>
|
|
236
|
+
<div data-slot="row">
|
|
237
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
238
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
239
|
+
>Clear</AlertDialogClose
|
|
240
|
+
>
|
|
241
|
+
</div>
|
|
242
|
+
</AlertDialogContent>
|
|
243
|
+
</AlertDialog>
|
|
244
|
+
</template>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Press Cmd+Shift+H (Ctrl+Shift+H on Windows and Linux) to open the dialog without clicking.
|
|
248
|
+
|
|
249
|
+
## Animation
|
|
250
|
+
|
|
251
|
+
The content has `data-starting-style` while it opens and `data-ending-style` while it closes. Transition from those states, and the dialog stays mounted until the exit finishes:
|
|
252
|
+
|
|
253
|
+
```css
|
|
254
|
+
[data-slot="alert-dialog-content"] {
|
|
255
|
+
transition:
|
|
256
|
+
opacity 0.2s,
|
|
257
|
+
translate 0.25s cubic-bezier(0.22, 1, 0.36, 1),
|
|
258
|
+
scale 0.25s cubic-bezier(0.22, 1, 0.36, 1);
|
|
259
|
+
|
|
260
|
+
&:is([data-starting-style], [data-ending-style]) {
|
|
261
|
+
opacity: 0;
|
|
262
|
+
translate: 0 16px;
|
|
263
|
+
scale: 0.96;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
&[data-ending-style] {
|
|
267
|
+
transition-duration: 0.15s;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
```vue title="animation.vue"
|
|
273
|
+
<script setup lang="ts">
|
|
274
|
+
import {
|
|
275
|
+
AlertDialog,
|
|
276
|
+
AlertDialogBackdrop,
|
|
277
|
+
AlertDialogClose,
|
|
278
|
+
AlertDialogContent,
|
|
279
|
+
AlertDialogDescription,
|
|
280
|
+
AlertDialogTitle,
|
|
281
|
+
AlertDialogTrigger,
|
|
282
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
283
|
+
</script>
|
|
284
|
+
|
|
285
|
+
<template>
|
|
286
|
+
<AlertDialog>
|
|
287
|
+
<AlertDialogTrigger>Leave Workspace</AlertDialogTrigger>
|
|
288
|
+
<AlertDialogBackdrop />
|
|
289
|
+
<AlertDialogContent>
|
|
290
|
+
<div data-slot="stack">
|
|
291
|
+
<AlertDialogTitle>Leave this workspace?</AlertDialogTitle>
|
|
292
|
+
<AlertDialogDescription>
|
|
293
|
+
You'll lose access to its projects until someone invites you again.
|
|
294
|
+
</AlertDialogDescription>
|
|
295
|
+
</div>
|
|
296
|
+
<div data-slot="row">
|
|
297
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
298
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
299
|
+
>Leave</AlertDialogClose
|
|
300
|
+
>
|
|
301
|
+
</div>
|
|
302
|
+
</AlertDialogContent>
|
|
303
|
+
</AlertDialog>
|
|
304
|
+
</template>
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Open and close the dialog. It slides up and fades in, and slides down and fades out before it unmounts.
|
|
308
|
+
|
|
309
|
+
## Nested
|
|
310
|
+
|
|
311
|
+
An alert dialog opened inside another joins its stack, such as a second confirmation before something can't be undone. Escape closes the topmost one and returns focus to its trigger. The dialog underneath gets `data-nested-open`, so you can show which layer is active. To close both once the last question is answered, control the outer dialog with `v-model:open` and close it when the inner one's `@open-change` reports `returnValue` `"confirm"`.
|
|
312
|
+
|
|
313
|
+
```vue title="nested.vue"
|
|
314
|
+
<script setup lang="ts">
|
|
315
|
+
import {
|
|
316
|
+
AlertDialog,
|
|
317
|
+
AlertDialogBackdrop,
|
|
318
|
+
AlertDialogClose,
|
|
319
|
+
AlertDialogContent,
|
|
320
|
+
AlertDialogDescription,
|
|
321
|
+
AlertDialogTitle,
|
|
322
|
+
AlertDialogTrigger,
|
|
323
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
324
|
+
import { ref } from "vue"
|
|
325
|
+
|
|
326
|
+
const open = ref(false)
|
|
327
|
+
|
|
328
|
+
function onNestedOpenChange(
|
|
329
|
+
nested: boolean,
|
|
330
|
+
details: { returnValue?: string }
|
|
331
|
+
) {
|
|
332
|
+
if (!nested && details.returnValue === "confirm") {
|
|
333
|
+
open.value = false
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
</script>
|
|
337
|
+
|
|
338
|
+
<template>
|
|
339
|
+
<AlertDialog v-model:open="open">
|
|
340
|
+
<AlertDialogTrigger>Delete Workspace</AlertDialogTrigger>
|
|
341
|
+
<AlertDialogBackdrop />
|
|
342
|
+
<AlertDialogContent>
|
|
343
|
+
<div data-slot="stack">
|
|
344
|
+
<AlertDialogTitle>Delete this workspace?</AlertDialogTitle>
|
|
345
|
+
<AlertDialogDescription>
|
|
346
|
+
All 12 projects and their deployments will be deleted for everyone on
|
|
347
|
+
your team.
|
|
348
|
+
</AlertDialogDescription>
|
|
349
|
+
</div>
|
|
350
|
+
<div data-slot="row">
|
|
351
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
352
|
+
<AlertDialog @open-change="onNestedOpenChange">
|
|
353
|
+
<AlertDialogTrigger data-variant="solid">Delete</AlertDialogTrigger>
|
|
354
|
+
<AlertDialogBackdrop />
|
|
355
|
+
<AlertDialogContent>
|
|
356
|
+
<div data-slot="stack">
|
|
357
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
358
|
+
<AlertDialogDescription
|
|
359
|
+
>There's no way to get the workspace
|
|
360
|
+
back.</AlertDialogDescription
|
|
361
|
+
>
|
|
362
|
+
</div>
|
|
363
|
+
<div data-slot="row">
|
|
364
|
+
<AlertDialogClose>Go Back</AlertDialogClose>
|
|
365
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
366
|
+
>Delete Workspace</AlertDialogClose
|
|
367
|
+
>
|
|
368
|
+
</div>
|
|
369
|
+
</AlertDialogContent>
|
|
370
|
+
</AlertDialog>
|
|
371
|
+
</div>
|
|
372
|
+
</AlertDialogContent>
|
|
373
|
+
</AlertDialog>
|
|
374
|
+
</template>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Choose Delete Workspace, then Delete. Press Escape to step back to the first question, or choose Delete Workspace to close both.
|
|
378
|
+
|
|
379
|
+
## Async Action
|
|
380
|
+
|
|
381
|
+
An `@action` handler on a Close part runs before it closes the dialog. Vue passes its return value to the part. Return a Promise to keep the dialog open until the work finishes. A resolved Promise closes it with the reason `action`; a rejection keeps it open and puts the error in that part's state.
|
|
382
|
+
|
|
383
|
+
```vue title="async-action.vue"
|
|
384
|
+
<script setup lang="ts">
|
|
385
|
+
import {
|
|
386
|
+
AlertDialog,
|
|
387
|
+
AlertDialogBackdrop,
|
|
388
|
+
AlertDialogClose,
|
|
389
|
+
AlertDialogContent,
|
|
390
|
+
AlertDialogDescription,
|
|
391
|
+
AlertDialogTitle,
|
|
392
|
+
AlertDialogTrigger,
|
|
393
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
394
|
+
|
|
395
|
+
let attempts = 0
|
|
396
|
+
|
|
397
|
+
async function deleteProject() {
|
|
398
|
+
await new Promise((resolve) => setTimeout(resolve, 1200))
|
|
399
|
+
if (attempts++ === 0) {
|
|
400
|
+
throw new Error("Couldn't delete the project.")
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
</script>
|
|
404
|
+
|
|
405
|
+
<template>
|
|
406
|
+
<div data-slot="stack">
|
|
407
|
+
<AlertDialog pending-announcement="Deleting project">
|
|
408
|
+
<AlertDialogTrigger>Delete Project</AlertDialogTrigger>
|
|
409
|
+
<AlertDialogBackdrop />
|
|
410
|
+
<AlertDialogContent>
|
|
411
|
+
<div data-slot="stack">
|
|
412
|
+
<AlertDialogTitle>Delete project?</AlertDialogTitle>
|
|
413
|
+
<AlertDialogDescription>
|
|
414
|
+
This permanently deletes the project, its files and its deployment
|
|
415
|
+
history for everyone on your team.
|
|
416
|
+
</AlertDialogDescription>
|
|
417
|
+
</div>
|
|
418
|
+
<AlertDialogClose data-variant="solid" value="confirm" @action="deleteProject">
|
|
419
|
+
<template #render="{ props, state }">
|
|
420
|
+
<div data-slot="stack">
|
|
421
|
+
<p data-slot="hint" role="alert">
|
|
422
|
+
{{ state.error instanceof Error ? state.error.message : "" }}
|
|
423
|
+
</p>
|
|
424
|
+
<div data-slot="row">
|
|
425
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
426
|
+
<button v-bind="props">
|
|
427
|
+
{{
|
|
428
|
+
state.pending
|
|
429
|
+
? "Deleting…"
|
|
430
|
+
: state.error
|
|
431
|
+
? "Try Again"
|
|
432
|
+
: "Delete"
|
|
433
|
+
}}
|
|
434
|
+
</button>
|
|
435
|
+
</div>
|
|
436
|
+
</div>
|
|
437
|
+
</template>
|
|
438
|
+
</AlertDialogClose>
|
|
439
|
+
</AlertDialogContent>
|
|
440
|
+
</AlertDialog>
|
|
441
|
+
</div>
|
|
442
|
+
</template>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Choose Delete Project, then Delete. The first attempt fails so you can try again. While Deleting… is shown, Cancel and Escape leave the dialog open. A successful retry closes it.
|
|
446
|
+
|
|
447
|
+
While the action runs, its button stays focusable and gets `data-pending`, `aria-busy`, and `aria-disabled`. Other Close parts and dismissals cannot close the dialog until it settles. `@dismiss-attempt` reports refused dismissals; a controller can still close it.
|
|
448
|
+
|
|
449
|
+
The root's `pending-announcement` sets what screen readers hear after a second of waiting. The error clears on the next attempt or when the dialog opens again. The action also receives `{ source }` after its event argument; [Changes After an Await](./button.md#changes-after-an-await) explains when to use it.
|
|
450
|
+
|
|
451
|
+
## Confirm From Anywhere
|
|
452
|
+
|
|
453
|
+
The shared `confirm()` asks a question without any dialog markup. Render `OverlayHost` from `@ui-sdk/vue/overlays` once near the root of your app, and it shows each question as an alert dialog. `confirm()` resolves `true` when someone agrees. [Confirm Options](#confirm-options) lists what you can pass.
|
|
454
|
+
|
|
455
|
+
```vue title="confirm-anywhere.vue"
|
|
456
|
+
<script setup lang="ts">
|
|
457
|
+
import { confirm } from "@ui-sdk/vue/alert-dialog"
|
|
458
|
+
import { OverlayHost } from "@ui-sdk/vue/overlays"
|
|
459
|
+
import { useLog } from "./log"
|
|
460
|
+
|
|
461
|
+
const log = useLog()
|
|
462
|
+
|
|
463
|
+
async function archive() {
|
|
464
|
+
const yes = await confirm({
|
|
465
|
+
title: "Archive this project?",
|
|
466
|
+
description: "It moves to Archived, and you can restore it anytime.",
|
|
467
|
+
confirmLabel: "Archive",
|
|
468
|
+
})
|
|
469
|
+
log(yes ? "Archived the project" : "Kept the project")
|
|
470
|
+
}
|
|
471
|
+
</script>
|
|
472
|
+
|
|
473
|
+
<template>
|
|
474
|
+
<button type="button" @click="archive">Archive Project</button>
|
|
475
|
+
<OverlayHost />
|
|
476
|
+
</template>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
Choose Archive Project, then Archive or Cancel. The console shows the answer.
|
|
480
|
+
|
|
481
|
+
## Confirm
|
|
482
|
+
|
|
483
|
+
Use `createConfirm<Payload>()` to ask a question from an event handler and await the answer. Create it in `<script setup>`, then pass its `controller` to your alert dialog. Use a typed content alias, such as `AlertDialogContent<{ name: string }>`, to read the question's data from `state.payload` in its default slot.
|
|
484
|
+
|
|
485
|
+
`await confirm({ name })` resolves `true` when the Close part with `value="confirm"` closes the dialog. Cancel, Escape, and other answers resolve `false`. This lets several rows share one dialog:
|
|
486
|
+
|
|
487
|
+
```vue title="confirm.vue"
|
|
488
|
+
<script setup lang="ts">
|
|
489
|
+
import {
|
|
490
|
+
AlertDialog,
|
|
491
|
+
AlertDialogBackdrop,
|
|
492
|
+
AlertDialogClose,
|
|
493
|
+
AlertDialogContent,
|
|
494
|
+
AlertDialogDescription,
|
|
495
|
+
AlertDialogTitle,
|
|
496
|
+
createConfirm,
|
|
497
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
498
|
+
import { ref, useTemplateRef } from "vue"
|
|
499
|
+
|
|
500
|
+
const confirm = createConfirm<{ name: string }>()
|
|
501
|
+
const ProjectAlertDialogContent = AlertDialogContent<{ name: string }>
|
|
502
|
+
const projects = ref(["Acme", "Globex", "Initech"])
|
|
503
|
+
const reset = useTemplateRef<HTMLButtonElement>("reset")
|
|
504
|
+
|
|
505
|
+
async function remove(name: string, button: HTMLButtonElement) {
|
|
506
|
+
if (!(await confirm({ name }))) {
|
|
507
|
+
return
|
|
508
|
+
}
|
|
509
|
+
const row = button.closest("li")
|
|
510
|
+
const next = (
|
|
511
|
+
row?.nextElementSibling ?? row?.previousElementSibling
|
|
512
|
+
)?.querySelector("button")
|
|
513
|
+
const target = next ?? reset.value
|
|
514
|
+
target?.focus()
|
|
515
|
+
projects.value = projects.value.filter((project) => project !== name)
|
|
516
|
+
}
|
|
517
|
+
</script>
|
|
518
|
+
|
|
519
|
+
<template>
|
|
520
|
+
<div data-slot="stack">
|
|
521
|
+
<div data-slot="controls">
|
|
522
|
+
<button ref="reset" type="button" @click="projects = ['Acme', 'Globex', 'Initech']">
|
|
523
|
+
Reset Projects
|
|
524
|
+
</button>
|
|
525
|
+
</div>
|
|
526
|
+
<ul data-slot="list" aria-label="Projects">
|
|
527
|
+
<li v-for="name in projects" :key="name" data-slot="row">
|
|
528
|
+
{{ name }}
|
|
529
|
+
<button
|
|
530
|
+
type="button"
|
|
531
|
+
data-size="sm"
|
|
532
|
+
:aria-label="`Delete ${name}`"
|
|
533
|
+
@click="remove(name, $event.currentTarget as HTMLButtonElement)"
|
|
534
|
+
>
|
|
535
|
+
Delete
|
|
536
|
+
</button>
|
|
537
|
+
</li>
|
|
538
|
+
<li v-if="projects.length === 0" data-slot="row">
|
|
539
|
+
All projects deleted.
|
|
540
|
+
</li>
|
|
541
|
+
</ul>
|
|
542
|
+
<AlertDialog :controller="confirm.controller">
|
|
543
|
+
<AlertDialogBackdrop />
|
|
544
|
+
<ProjectAlertDialogContent v-slot="{ state }">
|
|
545
|
+
<div data-slot="stack">
|
|
546
|
+
<AlertDialogTitle>Delete {{ state.payload?.name }}?</AlertDialogTitle>
|
|
547
|
+
<AlertDialogDescription>
|
|
548
|
+
The project and its files will be deleted for everyone on your team.
|
|
549
|
+
</AlertDialogDescription>
|
|
550
|
+
</div>
|
|
551
|
+
<div data-slot="row">
|
|
552
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
553
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
554
|
+
>Delete</AlertDialogClose
|
|
555
|
+
>
|
|
556
|
+
</div>
|
|
557
|
+
</ProjectAlertDialogContent>
|
|
558
|
+
</AlertDialog>
|
|
559
|
+
</div>
|
|
560
|
+
</template>
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
Delete a project. Cancel or Escape keeps it; Delete removes it and focuses a neighboring row's button. Reset Projects brings the list back.
|
|
564
|
+
|
|
565
|
+
When the action removes the button that opened the dialog, choose a useful place for focus to go. This example focuses a neighboring row, or Reset Projects when the list is empty.
|
|
566
|
+
|
|
567
|
+
## Queued Questions
|
|
568
|
+
|
|
569
|
+
Calls to the same confirm function wait their turn. You can ask two questions at once; the second appears only after the first has an answer.
|
|
570
|
+
|
|
571
|
+
```vue title="queue.vue"
|
|
572
|
+
<script setup lang="ts">
|
|
573
|
+
import {
|
|
574
|
+
AlertDialog,
|
|
575
|
+
AlertDialogBackdrop,
|
|
576
|
+
AlertDialogClose,
|
|
577
|
+
AlertDialogContent,
|
|
578
|
+
AlertDialogDescription,
|
|
579
|
+
AlertDialogTitle,
|
|
580
|
+
createConfirm,
|
|
581
|
+
} from "@ui-sdk/vue/alert-dialog"
|
|
582
|
+
import { useLog } from "./log"
|
|
583
|
+
|
|
584
|
+
const confirm = createConfirm<{ name: string }>()
|
|
585
|
+
const ProjectAlertDialogContent = AlertDialogContent<{ name: string }>
|
|
586
|
+
const log = useLog()
|
|
587
|
+
|
|
588
|
+
async function review() {
|
|
589
|
+
const acme = confirm({ name: "Acme" })
|
|
590
|
+
const globex = confirm({ name: "Globex" })
|
|
591
|
+
const [first, second] = await Promise.all([acme, globex])
|
|
592
|
+
log(`Acme: ${first ? "confirmed" : "canceled"}`)
|
|
593
|
+
log(`Globex: ${second ? "confirmed" : "canceled"}`)
|
|
594
|
+
}
|
|
595
|
+
</script>
|
|
596
|
+
|
|
597
|
+
<template>
|
|
598
|
+
<div data-slot="stack">
|
|
599
|
+
<button type="button" @click="review">Review Two Projects</button>
|
|
600
|
+
<AlertDialog :controller="confirm.controller">
|
|
601
|
+
<AlertDialogBackdrop />
|
|
602
|
+
<ProjectAlertDialogContent v-slot="{ state }">
|
|
603
|
+
<div data-slot="stack">
|
|
604
|
+
<AlertDialogTitle
|
|
605
|
+
>Archive {{ state.payload?.name }}?</AlertDialogTitle
|
|
606
|
+
>
|
|
607
|
+
<AlertDialogDescription>
|
|
608
|
+
Archived projects leave the active list. You can restore them later.
|
|
609
|
+
</AlertDialogDescription>
|
|
610
|
+
</div>
|
|
611
|
+
<div data-slot="row">
|
|
612
|
+
<AlertDialogClose>Cancel</AlertDialogClose>
|
|
613
|
+
<AlertDialogClose data-variant="solid" value="confirm"
|
|
614
|
+
>Archive</AlertDialogClose
|
|
615
|
+
>
|
|
616
|
+
</div>
|
|
617
|
+
</ProjectAlertDialogContent>
|
|
618
|
+
</AlertDialog>
|
|
619
|
+
</div>
|
|
620
|
+
</template>
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
Choose Review Two Projects. Answer the Acme question, then the Globex question. The console shows both answers once the second one is in.
|
|
624
|
+
|
|
625
|
+
## Styling
|
|
626
|
+
|
|
627
|
+
Each part has a `data-slot`, such as `alert-dialog-content`, and shows its state through the attributes listed under [Data Attributes](#data-attributes). [Styling and Animation](../styling-and-animation.md) covers state attributes and entry and exit transitions.
|
|
628
|
+
|
|
629
|
+
### AlertDialogContent
|
|
630
|
+
- `--dialog-stack`: How many dialogs are open above this one, nested inside it. 0 for the topmost.
|
|
631
|
+
- `--keyboard-inset`: How many pixels of the page the on-screen keyboard covers, 0 without one.
|
|
632
|
+
- `--visual-viewport-width`: The width of the part of the page you can see.
|
|
633
|
+
- `--visual-viewport-height`: The height of the part of the page you can see, above the keyboard.
|
|
634
|
+
- `--visual-viewport-top`: How far the part of the page you can see is scrolled from the top of the layout, as when the keyboard pushes it up.
|
|
635
|
+
|
|
636
|
+
## Data Attributes
|
|
637
|
+
|
|
638
|
+
### AlertDialogTrigger
|
|
639
|
+
`[data-slot="alert-dialog-trigger"]`
|
|
640
|
+
|
|
641
|
+
- `data-closed`: Present while the dialog is closed, including while it animates out.
|
|
642
|
+
- `data-disabled`: Present when the trigger is disabled.
|
|
643
|
+
- `data-open`: Present while the dialog is open. On a trigger, while it's open from that trigger.
|
|
644
|
+
|
|
645
|
+
### AlertDialogBackdrop
|
|
646
|
+
`[data-slot="alert-dialog-backdrop"]`
|
|
647
|
+
|
|
648
|
+
- `data-closed`: Present while the dialog is closed, including while it animates out.
|
|
649
|
+
- `data-open`: Present while the dialog is open. On a trigger, while it's open from that trigger.
|
|
650
|
+
- `data-starting-style`: Present for the first frame. Style the state you animate from.
|
|
651
|
+
- `data-ending-style`: Present while the dialog animates out. Style the state you animate to.
|
|
652
|
+
|
|
653
|
+
### AlertDialogContent
|
|
654
|
+
`[data-slot="alert-dialog-content"]`
|
|
655
|
+
|
|
656
|
+
- `data-closed`: Present while the dialog is closed, including while it animates out.
|
|
657
|
+
- `data-open`: Present while the dialog is open. On a trigger, while it's open from that trigger.
|
|
658
|
+
- `data-starting-style`: Present for the first frame. Style the state you animate from.
|
|
659
|
+
- `data-ending-style`: Present while the dialog animates out. Style the state you animate to.
|
|
660
|
+
- `data-keyboard`: Present while the on-screen keyboard covers part of the page.
|
|
661
|
+
|
|
662
|
+
### AlertDialogClose
|
|
663
|
+
`[data-slot="alert-dialog-close"]`
|
|
664
|
+
|
|
665
|
+
- `data-pending`: Present on a Close part while its action runs.
|
|
666
|
+
|
|
667
|
+
## API Reference
|
|
668
|
+
|
|
669
|
+
Alert Dialog shares [Dialog's](./dialog.md) options, except `modal`, `close-on-outside-press`, and `presentation`. It is always modal, never closes on an outside press, and does not present as a sheet.
|
|
670
|
+
|
|
671
|
+
### AlertDialog
|
|
672
|
+
|
|
673
|
+
- `container?` (`DocumentFragment | Element | null`): Renders the popup into this element instead of in place, like a container inside a shadow root or an iframe. On web components, a CSS selector. Nested popups stay inside their parent.
|
|
674
|
+
- `open?` (`boolean`): Whether the dialog is open. Pass it to control the dialog.
|
|
675
|
+
- `defaultOpen?` (`boolean`): Whether the dialog starts open, when uncontrolled. Focus moves into it once it's on the page.
|
|
676
|
+
- `@open-change-complete` (`((open: boolean) => void)`): Runs once the dialog has finished opening or closing, after any animation.
|
|
677
|
+
- `dismissible?` (`boolean`): Whether Escape, an outside press and Android's back gesture can close the dialog. Close parts, triggers and the controller always can. Pass `false` while a form has unsaved changes, and ask in `@dismiss-attempt`.
|
|
678
|
+
- `@dismiss-attempt` (`((details: DialogDismissAttemptDetails) => void)`): Runs when a dismissal was refused, because `dismissible` is false, an outside press doesn't close it, or a Close part's action is running. Ask "Discard changes?" here.
|
|
679
|
+
- `persistentElements?` (`(string | Element)[] | (() => Element[])`): Elements that stay usable while the dialog makes the page inert, like a chat launcher or a password manager's button. Elements, CSS selectors, or a function that returns elements, read when the dialog opens. Presses on them never close it.
|
|
680
|
+
- `pendingAnnouncement?` (`string`): What screen readers hear once a Close part's action has been running for a second, so a slow action doesn't pass in silence. Set it in the page's language. An empty string says nothing.
|
|
681
|
+
- `debug?` (`boolean`): Logs every state change with its reason to the console, in development builds.
|
|
682
|
+
- `@open-change` (`((open: boolean, details: DialogOpenChangeDetails<AlertDialogOpenChangeReason>) => void)`): Runs when the alert dialog wants to open or close. `details.reason` says why, `details.cancel()` stops it, and `details.returnValue` is the `value` of the Close part that closed it.
|
|
683
|
+
- `@payload-change` (`((payload: unknown, details: ChangeDetails<AlertDialogPayloadChangeReason>) => void)`): Runs when a trigger or a controller with another payload opens the alert dialog, before `@open-change`, or a controller's `open({ payload })` gives the open one another payload. `details.cancel()` keeps the previous payload.
|
|
684
|
+
- `controller?` (`PopupController<any, AlertDialogOpenChangeReason, {}, any, DialogPayloadChangeReason>`): Opens, closes and inspects the alert dialog from anywhere. Create one with `createAlertDialogController()` or `createConfirm()`.
|
|
685
|
+
|
|
686
|
+
### AlertDialogTrigger
|
|
687
|
+
|
|
688
|
+
- `disabled?` (`boolean`): Stops the trigger from opening the dialog. A native button can't be focused or pressed, unless `focusableWhenDisabled` is set.
|
|
689
|
+
- `focusableWhenDisabled?` (`boolean`): Keeps a disabled trigger in the tab order with `aria-disabled` instead of the native attribute, so it can host a tooltip that says why. Presses still do nothing.
|
|
690
|
+
- `payload?` (`unknown`): Data for the content to render when this trigger opens the dialog, like the row it belongs to.
|
|
691
|
+
- `shortcut?` (`string`): A keyboard shortcut that presses the trigger, like `"mod+k"`. `mod` is Command on Apple platforms and Control elsewhere. Sets `aria-keyshortcuts`, and a Shortcut part inside shows it. A modal dialog pauses the page's shortcuts while it's open.
|
|
692
|
+
- `controller?` (`PopupController<any, AlertDialogOpenChangeReason, {}, any, DialogPayloadChangeReason>`): Connects a trigger outside the alert dialog to the alert dialog with this controller.
|
|
693
|
+
|
|
694
|
+
### AlertDialogBackdrop
|
|
695
|
+
|
|
696
|
+
Dims the page behind the dialog. Renders a `div` and accepts its attributes and the `render` slot.
|
|
697
|
+
|
|
698
|
+
### AlertDialogContent
|
|
699
|
+
|
|
700
|
+
- `container?` (`DocumentFragment | Element | null`): Renders the popup into this element instead of in place, like a container inside a shadow root or an iframe. On web components, a CSS selector. Nested popups stay inside their parent.
|
|
701
|
+
- `initialFocus?` (`DialogInitialFocus`): Where focus goes when the dialog opens. Opening with touch focuses the dialog itself, so no on-screen keyboard appears.
|
|
702
|
+
- `finalFocus?` (`PopupFocusTarget`): Where focus goes when the dialog closes while focus is inside it.
|
|
703
|
+
- `keepMounted?` (`boolean`): Whether the dialog stays in the page, hidden, while closed. For animation libraries that drive the exit from state.
|
|
704
|
+
|
|
705
|
+
### AlertDialogTitle
|
|
706
|
+
|
|
707
|
+
The question. Renders an `h2`, and the content uses it as its accessible name.
|
|
708
|
+
|
|
709
|
+
### AlertDialogDescription
|
|
710
|
+
|
|
711
|
+
What happens if you agree. Renders a `p`, and the content uses it as its accessible description.
|
|
712
|
+
|
|
713
|
+
### AlertDialogClose
|
|
714
|
+
|
|
715
|
+
- `value?` (`string`): Reported as `returnValue` in `@open-change` and by the controller's `open()`. `createConfirm()` resolves `true` for `"confirm"`.
|
|
716
|
+
- `action?` (`((event: Event | undefined, details: ActionDetails) => unknown)`): Runs when the part is pressed, before the dialog closes. A returned Promise keeps the dialog open while it runs: the part gets `data-pending`, `aria-busy` and `aria-disabled`, screen readers hear the dialog's `pendingAnnouncement` after a second, and nothing but the controller closes the dialog. It closes with reason `"action"` once the Promise resolves. A rejection keeps it open and puts the reason in the part's `error` state until the next press, or until the dialog opens again. `details.source` says how the part was pressed, for changes made after an `await`.
|
|
717
|
+
|
|
718
|
+
### AlertDialogShortcut
|
|
719
|
+
|
|
720
|
+
- `shortcut?` (`string`): The keys to show. Inside a trigger, its `shortcut`.
|
|
721
|
+
|
|
722
|
+
### Confirm Options
|
|
723
|
+
|
|
724
|
+
The shared `confirm()` function uses these options when an `OverlayHost` renders the question. See [Toasts and Confirms](../popups.md#toasts-and-confirms) for the host setup. With your own dialog, `createConfirm<Payload>()` accepts the payload you choose instead.
|
|
725
|
+
|
|
726
|
+
- `title` (`string`): The question, like "Delete this project?".
|
|
727
|
+
- `description?` (`string`): What agreeing does.
|
|
728
|
+
- `confirmLabel?` (`string`): The agreeing button's text.
|
|
729
|
+
- `cancelLabel?` (`string`): The other button's text.
|
|
730
|
+
|
|
731
|
+
### State
|
|
732
|
+
|
|
733
|
+
`AlertDialogContent`:
|
|
734
|
+
|
|
735
|
+
- `open` (`boolean`): Whether the dialog is open. False while it animates out.
|
|
736
|
+
- `modal` (`boolean | "trap-focus"`): The `modal` setting. Always true for an alert dialog.
|
|
737
|
+
- `nested` (`boolean`): Whether the dialog was opened from inside another dialog.
|
|
738
|
+
- `nestedOpen` (`boolean`): Whether a dialog opened from inside this one is open.
|
|
739
|
+
- `stack` (`number`): How many dialogs are open above this one, nested inside it.
|
|
740
|
+
- `payload` (`Payload | undefined`): The payload of the last open, from the trigger that opened it or a controller, typed as the controller's `Payload`.
|
|
741
|
+
- `pending` (`boolean`): Whether a Close part's action is running.
|
|
742
|
+
- `presentation` (`"dialog"`): Always `"dialog"`: an alert dialog never presents as a sheet.
|
|
743
|
+
|
|
744
|
+
`AlertDialogClose`:
|
|
745
|
+
|
|
746
|
+
- `pending` (`boolean`): Whether this part's action is running.
|
|
747
|
+
- `error` (`unknown`): Why this part's last action failed, until it's pressed again or the dialog opens again.
|
|
748
|
+
|
|
749
|
+
`AlertDialogShortcut`:
|
|
750
|
+
|
|
751
|
+
- `text` (`string`): The shortcut formatted for this platform: `⌘K` on Apple platforms and `Ctrl+K` elsewhere. Empty without one.
|
|
752
|
+
|
|
753
|
+
### Reasons
|
|
754
|
+
|
|
755
|
+
- `trigger-press` (`MouseEvent | KeyboardEvent | TouchEvent`): Click, tap, Enter or Space on the part that opens, closes or toggles. Arrow keys that open a menu or submenu count too. A tap on a combobox's input that opens a sheet reports its `touchend`.
|
|
756
|
+
- `close-press` (`MouseEvent | KeyboardEvent | SubmitEvent`): A Close part was pressed, or a form with `method="dialog"` was submitted.
|
|
757
|
+
- `escape-key` (`KeyboardEvent`): Escape, or a submenu's close key (ArrowLeft in left-to-right layouts).
|
|
758
|
+
- `parent-close` (`none`): The parent layer closed.
|
|
759
|
+
- `back` (`Event`): Going back: the Android back button or gesture, or Backspace in an empty command input, which returns to the previous page.
|
|
760
|
+
- `action` (`MouseEvent | KeyboardEvent`): A Close part's `action` finished.
|
|
761
|
+
- `shortcut` (`KeyboardEvent`): A keyboard shortcut, like a trigger's `shortcut`.
|
|
762
|
+
- `imperative` (`none`): A controller or `api` call, or a property set on a web component.
|
|
763
|
+
|
|
764
|
+
`@payload-change` receives `(payload, details)` before `@open-change` when the dialog opens with another payload. Calling `controller.open({ payload })` on an open dialog updates the payload with the reason `imperative`.
|
|
765
|
+
|
|
766
|
+
- `trigger-press` (`MouseEvent | KeyboardEvent | TouchEvent`): Click, tap, Enter or Space on the part that opens, closes or toggles. Arrow keys that open a menu or submenu count too. A tap on a combobox's input that opens a sheet reports its `touchend`.
|
|
767
|
+
- `shortcut` (`KeyboardEvent`): A keyboard shortcut, like a trigger's `shortcut`.
|
|
768
|
+
- `imperative` (`none`): A controller or `api` call, or a property set on a web component.
|
|
769
|
+
|
|
770
|
+
### Controller
|
|
771
|
+
|
|
772
|
+
Use `createAlertDialogController<Payload, Result>()` for direct control. `createConfirm<Payload>()` returns a confirm function with its own `controller`.
|
|
773
|
+
|
|
774
|
+
- `isOpen()` (`() => boolean`): Whether it's open. False as soon as it starts closing, while it still animates out.
|
|
775
|
+
- `setOpen(open, options?)` (`(open: boolean, options?: PopupChangeOptions<AlertDialogOpenChangeReason> | undefined) => boolean`): Opens or closes it. Returns false when the change was canceled or it was already open or closed.
|
|
776
|
+
- `open(options?)` (`(options?: (PopupChangeOptions<DialogPayloadChangeReason> & { payload?: Payload | undefined; anchor?: Anchor | undefined; signal?: AbortSignal | undefined; }) | undefined) => Promise<...>`): Opens it, and resolves once it closes, with why, how and any return value. Resolves exactly once and never rejects: on the next close from any source, when `signal` aborts, or with reason `"unmount"` when the component leaves the page.
|
|
777
|
+
- `close(options?)` (`(options?: (PopupChangeOptions<AlertDialogOpenChangeReason> & { returnValue?: Result | undefined; }) | undefined) => boolean`): Closes it. `returnValue` is passed to the promise `open()` returned. Returns false when the close was canceled or it was already closed.
|
|
778
|
+
- `toggle(options?)` (`(options?: PopupChangeOptions<AlertDialogOpenChangeReason> | undefined) => boolean`): Opens it when it's closed, and closes it when it's open. Returns false when the change was canceled.
|
|
779
|
+
- `getPayload()` (`() => Payload | undefined`): The payload of the last open, from a controller or the trigger that opened it.
|
|
780
|
+
- `focus()` (`() => void`): Moves focus to the trigger that opened it last, or the first trigger.
|
|
781
|
+
|
|
782
|
+
## Accessibility
|
|
783
|
+
|
|
784
|
+
Give the dialog a title and a description, and put the least destructive answer first. It follows the [WAI-ARIA alert dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/).
|
|
785
|
+
|
|
786
|
+
The dialog uses the `alertdialog` role and keeps the rest of the page inert while it's open. Screen readers announce its title and description. Opening it focuses the first Close part, so put Cancel first. A touch open focuses the content instead, so no on-screen keyboard appears. Escape closes the dialog, but pressing outside never does. [Dialog](./dialog.md#focus) covers other initial and final focus targets.
|
|
787
|
+
|
|
788
|
+
These behaviors are covered by automated tests:
|
|
789
|
+
|
|
790
|
+
**Alert dialog**
|
|
791
|
+
|
|
792
|
+
- Opens with focus on the least destructive action.
|
|
793
|
+
- Is described by its message.
|
|
794
|
+
- An outside press keeps it open.
|
|
795
|
+
- Escape closes it and returns focus to the trigger.
|
|
796
|
+
- Tab cycles between its actions.
|
|
797
|
+
- The action reports and closes.
|
|
798
|
+
|
|
799
|
+
Runs in React, Vue and web components.
|