Actions
Result Dialog
A modal report of an action's outcome in one of daisyUI's colors, with one OK button and an optional automatic close.
| Class name | Type | Description |
|---|---|---|
result-dialogplf:result-dialog | Component | On a Modal dialog, beside modal |
result-dialog-iconplf:result-dialog-icon | Part | The round icon box, where a color draws its icon |
result-dialog-svgplf:result-dialog-svg | Part | Your own SVG in the box, in place of the color's icon; an icon class there doesn't need it |
result-dialog-titleplf:result-dialog-title | Part | The dialog's heading |
result-dialog-descriptionplf:result-dialog-description | Part | Muted text under the title |
result-dialog-footerplf:result-dialog-footer | Part | The OK button's row |
result-dialog-contentplf:result-dialog-content | Part | The scrolling content the script adds for an automatic close |
result-dialog-countdownplf:result-dialog-countdown | Part | The time-left line the script adds |
result-dialog-borderplf:result-dialog-border | Part | The countdown's SVG the script adds |
result-dialog-border-pathplf:result-dialog-border-path | Part | The line that traces the border |
result-dialog-successplf:result-dialog-success | Color | A completed action; its check draws itself on each opening |
result-dialog-errorplf:result-dialog-error | Color | A failed action |
result-dialog-warningplf:result-dialog-warning | Color | A result that needs attention |
result-dialog-infoplf:result-dialog-info | Color | A neutral notice |
Default
Result Dialog reports an outcome and runs no action itself; to ask before an action, use Alert Dialog.
<button class="btn btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-default">Save changes</button>
<dialog class="modal result-dialog result-dialog-success" data-plf-modal data-plf-result-dialog id="result-dialog-default" aria-describedby="result-dialog-default-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Changes saved</h2>
<p class="result-dialog-description" id="result-dialog-default-description">Your profile is up to date.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog><button class="plf:btn plf:btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-default">Save changes</button>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-success" data-plf-modal data-plf-result-dialog id="result-dialog-default" aria-describedby="result-dialog-default-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Changes saved</h2>
<p class="plf:result-dialog-description" id="result-dialog-default-description">Your profile is up to date.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react';
export function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>Save changes</Button>
<ResultDialog color="success" open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Changes saved</ResultDialogTitle>
<ResultDialogDescription>Your profile is up to date.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react/prefixed';
export function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>Save changes</Button>
<ResultDialog color="success" open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Changes saved</ResultDialogTitle>
<ResultDialogDescription>Your profile is up to date.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}<div class="flex flex-wrap gap-2">
<button class="btn btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-error">Error</button>
<button class="btn btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-warning">Warning</button>
<button class="btn btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-info">Info</button>
</div>
<dialog class="modal result-dialog result-dialog-error" data-plf-modal data-plf-result-dialog id="result-dialog-error" aria-describedby="result-dialog-error-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Could not save changes</h2>
<p class="result-dialog-description" id="result-dialog-error-description">Check your connection and try again.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<dialog class="modal result-dialog result-dialog-warning" data-plf-modal data-plf-result-dialog id="result-dialog-warning" aria-describedby="result-dialog-warning-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Saved with warnings</h2>
<p class="result-dialog-description" id="result-dialog-warning-description">Two images were too large and were skipped.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<dialog class="modal result-dialog result-dialog-info" data-plf-modal data-plf-result-dialog id="result-dialog-info" aria-describedby="result-dialog-info-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Export started</h2>
<p class="result-dialog-description" id="result-dialog-info-description">The file will be ready in a few minutes.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog><div class="plf:flex plf:flex-wrap plf:gap-2">
<button class="plf:btn plf:btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-error">Error</button>
<button class="plf:btn plf:btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-warning">Warning</button>
<button class="plf:btn plf:btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-info">Info</button>
</div>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-error" data-plf-modal data-plf-result-dialog id="result-dialog-error" aria-describedby="result-dialog-error-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Could not save changes</h2>
<p class="plf:result-dialog-description" id="result-dialog-error-description">Check your connection and try again.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-warning" data-plf-modal data-plf-result-dialog id="result-dialog-warning" aria-describedby="result-dialog-warning-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Saved with warnings</h2>
<p class="plf:result-dialog-description" id="result-dialog-warning-description">Two images were too large and were skipped.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-info" data-plf-modal data-plf-result-dialog id="result-dialog-info" aria-describedby="result-dialog-info-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Export started</h2>
<p class="plf:result-dialog-description" id="result-dialog-info-description">The file will be ready in a few minutes.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react';
export function Example() {
const [open, setOpen] = useState<'error' | 'warning' | 'info' | null>(null);
return (
<>
<div className="flex flex-wrap gap-2">
<Button variant="outline" onClick={() => setOpen('error')}>Error</Button>
<Button variant="outline" onClick={() => setOpen('warning')}>Warning</Button>
<Button variant="outline" onClick={() => setOpen('info')}>Info</Button>
</div>
<ResultDialog color="error" open={open === 'error'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Could not save changes</ResultDialogTitle>
<ResultDialogDescription>Check your connection and try again.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
<ResultDialog color="warning" open={open === 'warning'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Saved with warnings</ResultDialogTitle>
<ResultDialogDescription>Two images were too large and were skipped.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
<ResultDialog color="info" open={open === 'info'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Export started</ResultDialogTitle>
<ResultDialogDescription>The file will be ready in a few minutes.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react/prefixed';
export function Example() {
const [open, setOpen] = useState<'error' | 'warning' | 'info' | null>(null);
return (
<>
<div className="plf:flex plf:flex-wrap plf:gap-2">
<Button variant="outline" onClick={() => setOpen('error')}>Error</Button>
<Button variant="outline" onClick={() => setOpen('warning')}>Warning</Button>
<Button variant="outline" onClick={() => setOpen('info')}>Info</Button>
</div>
<ResultDialog color="error" open={open === 'error'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Could not save changes</ResultDialogTitle>
<ResultDialogDescription>Check your connection and try again.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
<ResultDialog color="warning" open={open === 'warning'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Saved with warnings</ResultDialogTitle>
<ResultDialogDescription>Two images were too large and were skipped.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
<ResultDialog color="info" open={open === 'info'} onOpenChange={() => setOpen(null)}>
<ResultDialogIcon />
<ResultDialogTitle>Export started</ResultDialogTitle>
<ResultDialogDescription>The file will be ready in a few minutes.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}Automatic close
Choose a duration long enough to read the content, and keep errors open until OK.
<button class="btn btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-auto">Publish draft</button>
<dialog class="modal result-dialog result-dialog-success" data-plf-modal data-plf-result-dialog data-plf-auto-close="5000" id="result-dialog-auto" aria-describedby="result-dialog-auto-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Draft published</h2>
<p class="result-dialog-description" id="result-dialog-auto-description">This message closes on its own.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog><button class="plf:btn plf:btn-outline" data-plf-trigger="modal:open" data-plf-target="result-dialog-auto">Publish draft</button>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-success" data-plf-modal data-plf-result-dialog data-plf-auto-close="5000" id="result-dialog-auto" aria-describedby="result-dialog-auto-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Draft published</h2>
<p class="plf:result-dialog-description" id="result-dialog-auto-description">This message closes on its own.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react';
export function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>Publish draft</Button>
<ResultDialog color="success" duration={5000} open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Draft published</ResultDialogTitle>
<ResultDialogDescription>This message closes on its own.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}'use client';
import { useState } from 'react';
import { Button, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react/prefixed';
export function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>Publish draft</Button>
<ResultDialog color="success" duration={5000} open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Draft published</ResultDialogTitle>
<ResultDialogDescription>This message closes on its own.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}After a request
Open it from your code once a request finishes, such as a form submit, with PLF.Modal.getOrCreateInstance(dialog).open(button); focus returns to that button when it closes.
<form class="flex flex-col gap-4 max-w-sm" id="result-dialog-form">
<div class="field">
<label class="field-label" for="result-dialog-form-email">Email</label>
<input class="input" id="result-dialog-form-email" name="email" type="email" autocomplete="email" value="jordan@example.com">
</div>
<button class="btn btn-primary self-start">
<span class="btn-label">Update email</span>
<span class="btn-loading">
<span class="btn-icon btn-icon-loading"></span>
Saving…
</span>
</button>
</form>
<dialog class="modal result-dialog result-dialog-success" data-plf-modal data-plf-result-dialog id="result-dialog-saved" aria-describedby="result-dialog-saved-description">
<span class="result-dialog-icon"></span>
<h2 class="result-dialog-title">Email updated</h2>
<p class="result-dialog-description" id="result-dialog-saved-description">We sent a confirmation link to your new address.</p>
<div class="result-dialog-footer">
<button class="btn btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<script>
const form = document.getElementById('result-dialog-form');
form.addEventListener('submit', async event => {
event.preventDefault();
const response = await PLF.Button.loading(event.submitter, fetch('/account/email', { method: 'POST', body: new FormData(form) }));
if (response.ok) PLF.Modal.getOrCreateInstance(document.getElementById('result-dialog-saved')).open(event.submitter);
});
</script><form class="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" id="result-dialog-form">
<div class="plf:field">
<label class="plf:field-label" for="result-dialog-form-email">Email</label>
<input class="plf:input" id="result-dialog-form-email" name="email" type="email" autocomplete="email" value="jordan@example.com">
</div>
<button class="plf:btn plf:btn-primary plf:self-start">
<span class="plf:btn-label">Update email</span>
<span class="plf:btn-loading">
<span class="plf:btn-icon plf:btn-icon-loading"></span>
Saving…
</span>
</button>
</form>
<dialog class="plf:modal plf:result-dialog plf:result-dialog-success" data-plf-modal data-plf-result-dialog id="result-dialog-saved" aria-describedby="result-dialog-saved-description">
<span class="plf:result-dialog-icon"></span>
<h2 class="plf:result-dialog-title">Email updated</h2>
<p class="plf:result-dialog-description" id="result-dialog-saved-description">We sent a confirmation link to your new address.</p>
<div class="plf:result-dialog-footer">
<button class="plf:btn plf:btn-primary" data-plf-trigger="modal:close">OK</button>
</div>
</dialog>
<script>
const form = document.getElementById('result-dialog-form');
form.addEventListener('submit', async event => {
event.preventDefault();
const response = await PLF.Button.loading(event.submitter, fetch('/account/email', { method: 'POST', body: new FormData(form) }));
if (response.ok) PLF.Modal.getOrCreateInstance(document.getElementById('result-dialog-saved')).open(event.submitter);
});
</script>'use client';
import { useState, type FormEvent } from 'react';
import { Button, Field, Input, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react';
export function Example() {
const [saving, setSaving] = useState(false);
const [open, setOpen] = useState(false);
async function save(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setSaving(true);
try {
const response = await fetch('/account/email', { method: 'POST', body: new FormData(event.currentTarget) });
if (response.ok) setOpen(true);
} finally {
setSaving(false);
}
}
return (
<>
<form className="flex flex-col gap-4 max-w-sm" onSubmit={save}>
<Field label="Email">
<Input name="email" type="email" autoComplete="email" defaultValue="jordan@example.com" />
</Field>
<Button color="primary" className="self-start" loading={saving} loadingText="Saving…">Update email</Button>
</form>
<ResultDialog color="success" open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Email updated</ResultDialogTitle>
<ResultDialogDescription>We sent a confirmation link to your new address.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}'use client';
import { useState, type FormEvent } from 'react';
import { Button, Field, Input, ResultDialog, ResultDialogAction, ResultDialogDescription, ResultDialogFooter, ResultDialogIcon, ResultDialogTitle } from '@pelatform/react/prefixed';
export function Example() {
const [saving, setSaving] = useState(false);
const [open, setOpen] = useState(false);
async function save(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setSaving(true);
try {
const response = await fetch('/account/email', { method: 'POST', body: new FormData(event.currentTarget) });
if (response.ok) setOpen(true);
} finally {
setSaving(false);
}
}
return (
<>
<form className="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" onSubmit={save}>
<Field label="Email">
<Input name="email" type="email" autoComplete="email" defaultValue="jordan@example.com" />
</Field>
<Button color="primary" className="plf:self-start" loading={saving} loadingText="Saving…">Update email</Button>
</form>
<ResultDialog color="success" open={open} onOpenChange={setOpen}>
<ResultDialogIcon />
<ResultDialogTitle>Email updated</ResultDialogTitle>
<ResultDialogDescription>We sent a confirmation link to your new address.</ResultDialogDescription>
<ResultDialogFooter>
<ResultDialogAction>OK</ResultDialogAction>
</ResultDialogFooter>
</ResultDialog>
</>
);
}JavaScript
Result Dialog needs JavaScript. The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/button.min.css">
<link rel="stylesheet" href="components/form.min.css">
<link rel="stylesheet" href="components/modal.min.css">
<link rel="stylesheet" href="components/result-dialog.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/modal.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/button.prefixed.min.css">
<link rel="stylesheet" href="components/form.prefixed.min.css">
<link rel="stylesheet" href="components/modal.prefixed.min.css">
<link rel="stylesheet" href="components/result-dialog.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/modal.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>From a script, PLF.Dialog.fire() shows any outcome with SweetAlert’s options, on a dialog it creates: see Dialogs from JavaScript.
Hooks
| Attribute | Purpose |
|---|---|
data-plf-result-dialog |
Marks a Modal dialog as a result dialog, with one OK button |
data-plf-auto-close |
Optional duration in milliseconds, from 1000 to 2147483647, read on each opening; a line traces the border and the dialog closes when it completes. Hover and focus pause it; OK and Escape close it at any time |
Methods and events
Result Dialog uses the Modal methods, events and keyboard; an automatic close fires them with reason: "api".
React
ResultDialog from @pelatform/react renders this dialog on a Modal: the application opens it with open and closes it in onOpenChange, and each part is a component of its own.
| Prop | Values | Default |
|---|---|---|
open |
true while the dialog is open |
Required |
onOpenChange |
(open, reason), called when the dialog asks to close: trigger (OK), keyboard (Escape) or timer (the automatic close); keep open to stay open |
None |
color |
success, error, warning, info |
None |
duration |
Milliseconds before an automatic close, at least 1000; a line traces the border, and hover and focus pause it |
None |
The parts:
| Part | Element |
|---|---|
ResultDialogIcon |
A span with result-dialog-icon: empty, the color’s icon; an Icon inside takes its place |
ResultDialogTitle |
An h2 with result-dialog-title, or another heading with level, which names the dialog |
ResultDialogDescription |
A p with result-dialog-description, which describes the dialog |
ResultDialogFooter |
A div with result-dialog-footer |
ResultDialogAction |
The OK button: a Button, primary unless given another color, which closes with trigger |
Other props are the element’s own, className and ref included. To show a result from your code without this markup, use useDialog().
CSS variables
The surface, padding, radius and backdrop come from the Modal variables.
| Variable | Default |
|---|---|
--plf-result-dialog-width |
24rem, capped to the viewport |
--plf-result-dialog-icon-bg |
The color’s background; --plf-color-surface-muted without a color |
--plf-result-dialog-icon-color |
The color’s text; --plf-color-text without a color |
--plf-result-dialog-progress-color |
The color, for the automatic-close line; --plf-color-primary without a color |