Alert dialog
Ein Bestätigungsdialog für destruktive oder wichtige Aktionen, der auf asynchrone Arbeit wartet und auf Smartphones zum Bottom Sheet wird.
pnpm dlx shadcn@latest add https://hextaui.com/r/alert-dialog.jsonFügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.
Füge die Theme-Tokens zu deinem globalen CSS hinzu, falls du das noch nicht getan hast.
Installiere die Abhängigkeiten.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnKopiere den folgenden Code und füge ihn in dein Projekt ein.
components/ui/alert-dialog.tsx components/ui/sheet.tsx components/ui/button.tsx Passe die Importpfade an dein Projekt-Setup an.
Asynchrone Aktion
Gib aus dem onClick von <AlertDialogAction /> ein Promise zurück. Der Button zeigt einen Spinner, und der Dialog lässt sich erst schließen, wenn das Promise abgeschlossen ist. Er schließt sich bei Erfolg und bleibt bei einer Ablehnung offen, damit man es erneut versuchen kann.
Media
<AlertDialogMedia /> platziert ein Icon auf dem Desktop neben dem Titel und auf Smartphones darüber. Verwende variant="destructive" für destruktive Aktionen.
Klein
size="sm" zentriert den Inhalt und ordnet die Buttons nebeneinander an, für kurze Fragen.
Losgelöste Trigger
Erstelle ein Handle mit createAlertDialogHandle(), um einen Dialog für viele Trigger zu teilen. Jeder Trigger übergibt sein eigenes payload, das der Dialog über eine Render-Funktion liest.
Kontrolliert
Übergib open und onOpenChange, um ihn ohne Trigger aus dem Code zu öffnen. Der Fokus landet trotzdem auf Cancel.
Verschachtelt
Ein Dialog, der aus einem anderen heraus geöffnet wird, legt sich darüber. Der übergeordnete skaliert zurück, solange der untergeordnete offen ist, und kommt beim Schließen wieder nach vorn.
Langer Inhalt
Inhalt, der höher als der Bildschirm ist, scrollt im Dialog, während die Seite gesperrt bleibt.
Rechts nach links
Übergib dir auch an den Content, da er in einem Portal außerhalb deines RTL-Containers gerendert wird. Die Pfeiltasten im Footer folgen der Leserichtung.
| Taste | Aktion |
|---|---|
| EnterSpace | Am Trigger: öffnet den Dialog und setzt den Fokus auf Cancel. |
| TabShift+Tab | Bewegt den Fokus zwischen den Bedienelementen. Der Fokus bleibt im Dialog. |
| ←→↑↓ | Wechselt zwischen den Footer-Buttons und springt am Ende wieder an den Anfang. Links und rechts folgen der Leserichtung. |
| Esc | Schließt den Dialog und gibt den Fokus an den Trigger zurück. Wird ignoriert, solange eine asynchrone Aktion läuft. |
- Der Content hat
role="alertdialog", wird durch seinen Titel beschriftet und durch seine Beschreibung beschrieben. - Der Fokus startet auf
<AlertDialogCancel />, der am wenigsten destruktiven Option. ÜbergibinitialFocus, um das zu ändern. - Ein Klick auf den Backdrop schließt ihn nicht, sodass eine Entscheidung nie versehentlich verworfen wird. Setze
disablePointerDismissal={false}, um das zu erlauben. - Auf Smartphones wird er zu einem Bottom Sheet, das sich zum Abbrechen nach unten wischen lässt. Solange eine Aktion aussteht, sind Wischen, Esc und Cancel blockiert, und die Buttons bleiben fokussierbar.
- Bei reduzierter Bewegung wird eingeblendet statt skaliert.
Basiert über <Sheet /> auf dem Base UI Drawer. Jeder Teil akzeptiert die Props der Primitive oder des Elements, das er umschließt.
| Prop | Typ | Standard |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChangeWird bei Schließvorgängen, die durch eine ausstehende Aktion blockiert sind, nicht aufgerufen. | (open: boolean, details) => void | – |
onOpenChangeCompleteWird nach der Öffnen- oder Schließen-Animation aufgerufen. | (open: boolean) => void | – |
disablePointerDismissalHält den Dialog bei Klicks auf den Backdrop offen. | boolean | true |
handleVerbindet losgelöste Trigger. | AlertDialogHandle<Payload> | – |
actionsRefDen Dialog imperativ schließen oder unmounten. | RefObject<{ close, unmount }> | – |
children | ReactNode | ({ payload }) => ReactNode | – |
| Prop | Typ | Standard |
|---|---|---|
handle | AlertDialogHandle<Payload> | – |
payloadWird an die Render-Funktion des Dialogs übergeben. | Payload | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-trigger" | Trigger in CSS ansprechen. |
data-popup-open | Vorhanden, solange sein Dialog geöffnet ist. |
| Prop | Typ | Standard |
|---|---|---|
size | "default" | "sm" | "default" |
initialFocus | boolean | RefObject | (openType) => HTMLElement | boolean | Cancel button |
finalFocus | boolean | RefObject | (closeType) => HTMLElement | boolean | The trigger |
dirSetze es, wenn der Dialog von rechts nach links laufen soll. | "ltr" | "rtl" | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-content" | Den Dialog in CSS ansprechen. |
data-size | Die aktuelle Größe. |
data-open | Vorhanden, solange geöffnet. |
data-starting-style | Vorhanden, während der Dialog eingeblendet wird. |
data-ending-style | Vorhanden, während der Dialog ausgeblendet wird. |
data-nested-drawer-open | Vorhanden, solange darüber ein verschachtelter Dialog geöffnet ist. |
data-swiping | Vorhanden, solange er auf einem Smartphone gewischt wird. |
--nested-drawers | Wie viele Dialoge über diesem geöffnet sind. |
Eine <div>, die Media, Titel und Beschreibung stapelt.
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-header" | Den Header in CSS ansprechen. |
| Prop | Typ | Standard |
|---|---|---|
variant | "default" | "destructive" | "default" |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-media" | Das Media in CSS ansprechen. |
| Prop | Typ | Standard |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <h2> |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-title" | Den Titel in CSS ansprechen. |
| Prop | Typ | Standard |
|---|---|---|
renderVerwende render={<div />}, wenn er mehrere Absätze enthält. | ReactElement | (props, state) => ReactElement | <p> |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-description" | Die Beschreibung in CSS ansprechen. |
Eine <div> für die Buttons. Auf Smartphones werden die Buttons in voller Breite gestapelt, und die Pfeiltasten wechseln zwischen ihnen.
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-footer" | Den Footer in CSS ansprechen. |
Eine <Button />, die den Dialog beim Klicken schließt. Sie akzeptiert alle Button-Props.
| Prop | Typ | Standard |
|---|---|---|
onClickGib ein Promise zurück, um einen Spinner anzuzeigen und den Dialog bis zu dessen Abschluss offen zu halten. Rufe event.preventDefault() auf, um ihn offen zu halten. | (event) => void | PromiseLike<unknown> | – |
variant | ButtonVariant | "default" |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-action" | Actions in CSS ansprechen. |
| Prop | Typ | Standard |
|---|---|---|
variant | ButtonVariant | "outline" |
size | ButtonSize | – |
disabledEbenfalls deaktiviert, solange eine Aktion aussteht. | boolean | – |
| Attribut | Beschreibung |
|---|---|
data-slot="alert-dialog-cancel" | Den Cancel-Button in CSS ansprechen. Er erhält den anfänglichen Fokus. |
data-disabled | Vorhanden, solange deaktiviert. |
<AlertDialogContent /> rendert bereits beides. Verwende sie nur, wenn du ein eigenes Popup zusammensetzt.
| Prop | Typ | Standard |
|---|---|---|
keepMountedHält den Dialog im geschlossenen Zustand im DOM, wenn es am Portal gesetzt ist. | boolean | false |
Gibt ein Handle zurück, das <AlertDialogTrigger />-Elemente an beliebiger Stelle der Seite mit einem <AlertDialog /> verbindet. Typisiere das Payload per Generic: createAlertDialogHandle<{ name: string }>().
- ButtonButtons in allen Varianten und Größen, mit eingebautem Lade-, Erfolgs- und Fehlerablauf, der den Spinner bei schnellen Anfragen überspringt.
- SheetEin Panel, das von jeder Kante hereingleitet, mit Wischen zum Schließen, Scroll-Sperre und gestapelter Verschachtelung.
- CommandEine durchsuchbare Liste von Aktionen, inline oder als ⌘K-Palette, mit Seiten, Tastenkürzeln und hervorgehobenen Treffern.
- Context menuEin Menü mit Aktionen per Rechtsklick oder langem Drücken, mit Untermenüs, Checkbox- und Radio-Einträgen sowie Halte-Feedback auf Touch-Geräten.
- DialogEin Fenster über der Seite für Formulare und fokussierte Aufgaben, mit fixiertem Header und Footer, Verschachtelung und einem wischbaren Bottom Sheet auf Smartphones.
- DrawerEin Panel, das von jeder Kante hereingleitet und deinem Finger folgt, mit Snap-Punkten, einem funktionierenden Griff und verschachtelten Drawern, die sich stapeln.
In Blocks verwendet
Blocks, die auf Alert dialog aufbauen.
- API keysDie API-Schlüssel-Seite eines KI-Produkts, wie in den Konsolen von OpenAI und Anthropic. Schlüssel mit eingeschränkten Berechtigungen und Ablaufdatum erstellen, das Secret einmal sehen mit einem Kopieren, das sich bestätigt, mit Rückgängig widerrufen, direkt umbenennen, mit Übergangsfrist rotieren und die Nutzung pro Schlüssel sehen.
- BillingPlan & Nutzung für ein KI-Produkt, im Stil von Cursor, Claude und Vercel. Eine nach Modell aufgeteilte Nutzungsanzeige, die das Ende des Zyklus hochrechnet und warnt, bevor die Credits ausgehen, ein tägliches Diagramm zum Scrubben, ein Ausgabenlimit mit Warnungen, die du auf der Anzeige in der Vorschau siehst, Planwechsel mit exakter Anteilsberechnung, ein Kartenformular mit echter Validierung und Rechnungen als PDF-Download.
- NotificationsDer Bereich „Benachrichtigungen“ in den Einstellungen eines KI-Produkts. Ein Raster aus Kanal und Ereignis mit Toggles für Zeile, Spalte und alle, Ruhezeiten mit einer Live-Zeile zur nächsten Ruhephase, ein E-Mail-Digest, echte Testsendungen für Desktop, E-Mail, Push und Slack, Umgang mit Browser-Berechtigungen und ein Slack-Verbindungsablauf. Passt in jeden Settings-Bereich.
- SecuritySitzungen und Sicherheit für ein KI-Produkt. Aktive Geräte mit Abmelden, bei dem Zeilen animiert verschwinden, eine Passwortänderung mit Live-Stärkeanzeige, Zwei-Faktor-Einrichtung mit echtem QR-Code, einer 6-stelligen Prüfung und herunterladbaren Wiederherstellungscodes, Passkeys über WebAuthn und Kontolöschung hinter einer getippten Bestätigung.