PlPopconfirm
A question asked where it was raised, rather than in the middle of the page. The row's own delete button, answered against the row.
import { PlPopconfirm } from 'plass-ui';
<PlPopconfirm
title="Delete this row?"
description="It cannot be undone."
confirmLabel="Delete"
onConfirm={() => remove(row)}
trigger={<PlButton color="danger">Delete</PlButton>}
/>;import 'package:plass_ui/plass_ui.dart';
PlPopconfirm(
open: asking,
onOpenChanged: (bool next) => setState(() => asking = next),
title: const Text('Delete this row?'),
confirmLabel: const Text('Delete'),
onConfirm: () => remove(row),
trigger: PlButton(
color: PlassColor.danger,
onPressed: () => setState(() => asking = true),
child: const Text('Delete'),
),
);Props
| Prop | Type | Default | Description |
|---|---|---|---|
| trigger * | ReactElement | — | What opens it. The element keeps everything it already had |
| title | ReactNode | — | The question, as the heading that names the popup |
| description | ReactNode | — | A line under it. Say what happens |
| confirmLabel | ReactNode | 'Confirm' | The word on the button that answers yes |
| cancelLabel | ReactNode | 'Cancel' | The word on the button that answers no |
| onConfirm | () => void | Promise<unknown> | — | What confirming does. A promise is waited for — the popup closes only if it resolves, and a rejection is caught and goes no further |
| onCancel | () => void | — | What cancelling does, beyond closing |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'danger' | The family the confirming button takes |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | The size of the popup and its two buttons |
| sideshared | 'top' | 'right' | 'bottom' | 'left' | 'top' | Which edge of the trigger it opens against |
| alignshared | 'start' | 'center' | 'end' | 'center' | Where it sits along that edge |
| width | number | string | 280 | How wide the sheet may get |
| open | boolean | — | The popup is open. Use with onOpenChange for a controlled one |
| defaultOpen | boolean | — | Whether it starts open, for an uncontrolled one |
| onOpenChange | (open: boolean) => void | — | Called when it opens or closes |
| Prop | Type | Default | Description |
|---|---|---|---|
| open * | bool | — | Whether the popup is up. Controlled, like everything stateful here |
| trigger * | Widget | — | What opens it. The element keeps everything it already had |
| onOpenChanged | ValueChanged<bool>? | — | Called when it opens or closes |
| title | Widget? | — | The question, as the heading that names the popup |
| description | Widget? | — | A line under it. Say what happens |
| confirmLabel | Widget | Text('Confirm') | The word on the button that answers yes |
| cancelLabel | Widget | Text('Cancel') | The word on the button that answers no |
| onConfirm | FutureOr<void> Function()? | — | What confirming does. A promise is waited for — the popup closes only if it resolves, and a rejection is caught and goes no further |
| onCancel | VoidCallback? | — | What cancelling does, beyond closing |
| colorshared | PlassColor | PlassColor.danger | The family the confirming button takes |
| sizeshared | PlassSize | PlassSize.md | The size of the popup and its two buttons |
| sideshared | PlassSide | PlassSide.top | Which edge of the trigger it opens against |
| alignshared | PlassAlign | PlassAlign.center | Where it sits along that edge |
| width | double | 280 | How wide the sheet may get |
open is controlled, like everything stateful in this package. There is no uncontrolled form, and no defaultOpen. onConfirm returns a FutureOr<void>, which is the Dart shape of "a promise is waited for": a plain callback closes at once, a Future holds the question up until it completes.
The two buttons sit in a Wrap rather than a Row, so a translated pair of labels that does not fit the sheet stacks instead of overflowing.
Popconfirm or confirm dialog
What differs is how much each one interrupts.
PlConfirmProvider | Takes the page away. For the question that deserves that, deleting an account, discarding an hour's work |
PlPopconfirm | Appears against the thing it is about. The rest of the table stays readable, and Escape puts the reader back exactly where they were |
The rule of thumb is what happens if they answer by accident. If the answer is "they can undo it", this is the one.
color defaults to danger here and to primary on a PlButton, and that is not an inconsistency: nobody reaches for a popconfirm to ask whether to save.
Examples
A confirm that takes time
onConfirm may return a promise. The button shows its loading state until it settles, and the popup closes only if it resolves. A failed request leaves the question on screen instead of pretending. Escape is ignored while it is running: a request in flight is not something to abandon halfway.
A rejection is caught and goes no further. Keeping the question up is the whole of what this component owes a failure; what the failure means is yours, and
onConfirmis where to report it from, a toast, usually.
side and align
It opens above the trigger by default, which is where it is least likely to cover the next row down. side and align are PlPopover's own.
<PlPopconfirm side="right" align="start" … />Accessibility
- It is a
PlPopover, so the popup is arole="dialog"named by itstitleand described by itsdescription, the focus moves into it, and it returns to the trigger when it closes. - The focus lands on the confirming button, which is the other way round from
PlConfirmProviderand is deliberate: a popconfirm is opened by the button it is asking about, so the reader has already said what they want once. The modal is for the question that has to be argued with. - There is no close button. The two answers are the two buttons, and a third way out that means neither would be a third answer to a question with two.
- Name the buttons for what they do. "Delete" and "Cancel", not "Yes" and "No".