Popconfirm
One short question next to the action it protects, for quick choices that are easy to undo.
Preview
Mirrored is the same English content laid out right to left: it separates a mirroring bug from a translation one.
Installation
Add the component
npx ritla add popconfirmAlso works with shadcn:
npx shadcn@latest add @ritla/popconfirmDependencies it brings
@base-ui/react@phosphor-icons/reactOr copy by hand
Installing by hand copies the component's source into your project. The source comes with a Ritla UI license, so the CLI is the short way to the same files.
Usage
import { Button } from "@/components/ui/button";import { Popconfirm, PopconfirmContent, PopconfirmTrigger } from "@/components/ui/popconfirm";<Popconfirm> <PopconfirmTrigger render={<Button variant="outline" />}>Make default</PopconfirmTrigger> <PopconfirmContent title="Set as default account?" okText="Set default" onConfirm={setDefault} /></Popconfirm>Examples
Danger
tone="danger" for removing something that can be added back: Confirm turns red, the icon becomes a warning, and focus starts on Cancel so Enter never removes anything by accident.
Placement, without icon or description
placement="bottom" when there is no room above the trigger; it also flips on its own. icon={false} and no description leave the question alone.
API reference
Popconfirm
| Prop | Type | Default | Description |
|---|---|---|---|
open / defaultOpen | boolean | None | To control it from code. |
onOpenChange | (open, details) => void | None | When it opens or closes. |
PopconfirmTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | None | The visible control: <Button … />. |
PopconfirmContent
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | None | Figma's Title: the question, short, ending with a question mark. Names the dialog. |
description | ReactNode | None | Figma's Show description: one line on what happens next. |
icon | boolean | true | Figma's Show icon: Info for Default, a warning for Danger. |
tone | "default" | "danger" | "default" | Figma's Tone; Danger turns Confirm red. |
placement | "top" | "bottom" | "top" | Figma's Placement. Flips when there isn't room. |
okText | ReactNode | "Confirm" / «تأكيد» | The Confirm button: name it after the action (Remove, Set default). |
cancelText | ReactNode | "Cancel" / «إلغاء» | The Cancel button: closes it and does nothing. |
onConfirm | () => void | None | On Confirm, then it closes. |
onCancel | () => void | None | On Cancel, then it closes. Esc and a click outside close it without calling either. |
Accessibility
Keyboard
Keys are written for left-to-right. In right-to-left the arrow keys swap: the one pointing toward the reading direction moves forward.
| Key | Action |
|---|---|
| EnterSpace | On the trigger: opens it and moves focus to Confirm, or to Cancel when the tone is Danger. |
| TabShift+Tab | Between the two buttons. Tabbing out closes it. |
| Esc | Closes it and returns focus to the trigger. |
ARIA
- A non-modal dialog (
role="dialog") named by the question and described by its second line. - The icon is decorative: the words and the Confirm label carry the tone, never the colour alone.
- For anything that moves money or cannot be undone, use a Dialog.
- It needs a pointer and room around the trigger: on phones, use a Drawer with the same question and buttons.
Arabic and RTL notes
Mirrors
- The icon and the text move to the right.
- The buttons sit at the inline end: Confirm at the left end, Cancel beside it.
Does not mirror
- The info and warning icons.
- The arrow stays centred on the trigger; Top and Bottom don't change.
- Numerals
- Numbers in the question follow the numerals setting.
- Arabic typography
- The question
body-14Medium, the descriptionbody-14. - Mixed-direction text
- It carries the trigger's direction and language into the portal, and the default button labels with them. Isolate names with
<bdi>, so a Latin name keeps its order inside an Arabic question.
Checks it passes
The Ritla checks this component satisfies by construction. Used as documented, it does not bring these defects onto your page.
- Clipped text: content wider than its box with overflow hidden and no ellipsis
- Fixed-pixel-width container whose Arabic text exceeds the space
- Arabic text falling back past the declared font family (measured, declared, or a webfont that failed to load)
- letter-spacing applied to Arabic text (breaks the connected script)