AlertDialog
Use CAlertDialog when a consequential action needs an immediate explicit decision. It requires a visible title, concise description, Cancel control, and Action control. Use CAlert for persistent feedback and CDialog for general modal content, forms, or more than two decisions.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class AlertDialogGlance(Component):
template = """
<c-CAlertDialog id="glance-delete">
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs" intent="danger">Delete project</c-CButton>
</c-fill>
<c-fill name="title">Delete this project?</c-fill>
<c-fill name="description">This permanently removes all project data.</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline">Keep project</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs" intent="danger">Delete</c-CButton>
</c-fill>
</c-CAlertDialog>
"""
preview = AlertDialogGlance()
preview # noqa: B018
<c-CAlertDialog id="delete-project">
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs" intent="danger">Delete project</c-CButton>
</c-fill>
<c-fill name="title">Delete this project?</c-fill>
<c-fill name="description">This permanently removes all project data.</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline">Keep project</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs" intent="danger">Delete</c-CButton>
</c-fill>
</c-CAlertDialog>
Choose the right interruption
AlertDialog is intentionally narrow. The native surface has role="alertdialog", a required name and description, and exactly two owned decision regions. Outside presses never close it. Escape acts like Cancel when close_on_escape=True.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class BlockingError(Component):
template = """
<c-CAlertDialog id="sync-error" size="md">
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs" variant="outline">Show sync error</c-CButton>
</c-fill>
<c-fill name="title">Changes could not be synchronized</c-fill>
<c-fill name="description">
Reconnect before continuing so this draft is not overwritten.
</c-fill>
<c-fill name="default">
Your local draft remains available in this browser.
</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline">Review draft</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs">Retry connection</c-CButton>
</c-fill>
</c-CAlertDialog>
"""
preview = BlockingError()
preview # noqa: B018
Control asynchronous decisions
A supplied client open Boolean is authoritative. onOpenChange requests the next state; accept it when application work is ready. Cancel and Action both use reason="action"; inspect detail.returnValue for "cancel" or "action".
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class ControlledArchive(Component):
template = """
<section x-data="{open: false, pending: false, result: 'No decision yet'}">
<c-CAlertDialog
id="archive-record"
$c-props="{
open,
onOpenChange: (next, detail) => {
if (detail.returnValue === 'action') {
pending = true;
result = 'Archiving...';
setTimeout(() => {
pending = false;
open = false;
result = 'Record archived';
}, 500);
} else {
open = next;
if (!next) result = 'Archive cancelled';
}
}
}"
>
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs">Archive record</c-CButton>
</c-fill>
<c-fill name="title">Archive this record?</c-fill>
<c-fill name="description">It will leave the active workspace.</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline" $c-props="{disabled: pending}">Cancel</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs" $c-props="{loading: pending}">Archive</c-CButton>
</c-fill>
</c-CAlertDialog>
<p aria-live="polite" x-text="result"></p>
</section>
"""
preview = ControlledArchive()
preview # noqa: B018
<c-CAlertDialog
$c-props="{
open: confirming,
onOpenChange: (open, detail) => {
if (detail.returnValue === 'action') archiveThenClose()
else confirming = open
}
}"
>
...
</c-CAlertDialog>
Omit or supply null for the client open prop to release control while preserving the effective state.
Compose native Buttons safely
CButton already owns type="button"; pass only *_attrs to it. A native Button must consume both the attribute mapping and adjacent type field.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class NativeAlertButtons(Component):
template = """
<c-CAlertDialog id="leave-editor">
<c-fill name="activator" data="{activator_attrs, activator_type}">
<button c-type="activator_type" c-bind="activator_attrs">Leave editor</button>
</c-fill>
<c-fill name="title">Leave the editor?</c-fill>
<c-fill name="description">Changes since the last save will be lost.</c-fill>
<c-fill name="cancel" data="{cancel_attrs, cancel_type}">
<button c-type="cancel_type" c-bind="cancel_attrs">Stay</button>
</c-fill>
<c-fill name="action" data="{action_attrs, action_type}">
<button c-type="action_type" c-bind="action_attrs">Leave</button>
</c-fill>
</c-CAlertDialog>
"""
preview = NativeAlertButtons()
preview # noqa: B018
<c-fill name="cancel" data="{cancel_attrs, cancel_type}">
<button c-type="cancel_type" c-bind="cancel_attrs">Stay</button>
</c-fill>
Native click handlers run before the component open-change request. This lets the application perform or schedule domain work without a duplicate custom confirm event.
Focus and accessibility
Cancel receives initial focus so the destructive choice is never the default. Tab and Shift+Tab remain inside the modal. Closing restores the connected activator unless application code deliberately moved focus elsewhere. The required title and description become the exact aria-labelledby and aria-describedby targets.
Size and customization
Sizes are sm, md, and lg; sm is the default. Full-screen workflows belong to Dialog. AlertDialog shares Dialog layout behavior while exposing family-specific variables.
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class AlertDialogSizes(Component):
class Kwargs:
pass
class Slots:
pass
template = """
<c-CGroup gap="md" wrap>
<c-for each="size in sizes">
<c-CAlertDialog c-size="size">
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs" variant="outline">Open {{ size }}</c-CButton>
</c-fill>
<c-fill name="title">{{ size }} decision surface</c-fill>
<c-fill name="description">Compare the responsive width for this size.</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline">Cancel</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs">Continue</c-CButton>
</c-fill>
</c-CAlertDialog>
</c-for>
</c-CGroup>
"""
def template_data(self, kwargs: Kwargs, slots: Slots) -> dict[str, object]: # noqa: ARG002
return {"sizes": ("sm", "md", "lg")}
preview = AlertDialogSizes()
preview # noqa: B018
Show code
import citry_ui
from citry import Component, citry
citry.register_library(citry_ui)
class CustomizedAlertDialog(Component):
template = """
<c-CAlertDialog
id="custom-archive"
class_="archive-alert"
c-style="{
'--cui-alert-dialog-radius': '1.25rem',
'--cui-alert-dialog-inline-size': '30rem',
'--cui-alert-dialog-border-color': '#8b5cf6'
}"
>
<c-fill name="activator" data="{activator_attrs}">
<c-CButton c-attrs="activator_attrs" variant="outline">Archive workspace</c-CButton>
</c-fill>
<c-fill name="title">Archive this workspace?</c-fill>
<c-fill name="description">Collaborators will lose active access.</c-fill>
<c-fill name="cancel" data="{cancel_attrs}">
<c-CButton c-attrs="cancel_attrs" variant="outline">Keep active</c-CButton>
</c-fill>
<c-fill name="action" data="{action_attrs}">
<c-CButton c-attrs="action_attrs">Archive</c-CButton>
</c-fill>
</c-CAlertDialog>
"""
preview = CustomizedAlertDialog()
preview # noqa: B018
.archive-alert {
--cui-alert-dialog-radius: 1.25rem;
--cui-alert-dialog-inline-size: 30rem;
--cui-alert-dialog-border-color: #8b5cf6;
}
See api.yml for the exhaustive inputs, callbacks, variables, attributes, selectors, slots, and public interfaces.
API reference
Inputs
CAlertDialog server inputs
Server inputs are passed in a template through <c-CAlertDialog ... /> or in Python through CAlertDialog(...).
| Input | Type | Default | Effect |
|---|---|---|---|
id | str | None | generated | Sets native Dialog identity and title, description, and activator relationships. |
open | bool | False | Sets the server-visible initial modal state. |
close_on_escape | bool | True | Permits Escape and platform cancel requests. |
size | "sm" | "md" | "lg" (CAlertDialogSize) | "sm" | Sets bounded decision-surface width. |
scroll | "body" | "dialog" (CAlertDialogScroll) | "body" | Chooses the overflow owner. |
class_ | CClassValue | None (CClassValue) | None | Adds native Dialog classes. |
style | CStyleValue | None (CStyleValue) | None | Adds native Dialog inline styles. |
attrs | Mapping[str, object] | None | None | Adds trusted native Dialog attributes without replacing owned modal semantics. |
CAlertDialog client inputs
Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CAlertDialog />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
open | boolean | null | undefined | Releases control and preserves effective state. | Controls modal visibility while supplied as a Boolean. |
closeOnEscape | boolean | undefined | Uses the server fallback. | Controls Escape and platform cancel behavior. |
size | "sm" | "md" | "lg" | undefined | Uses the server fallback. | Controls data-size and width. |
scroll | "body" | "dialog" | undefined | Uses the server fallback. | Controls data-scroll and overflow. |
onOpenChange | ((open, detail) => void) | undefined | No component callback. | Receives trigger, Escape, action, and native close requests. |
Slots
Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.
CAlertDialog slots
| Slot | Required | Data | Fallback |
|---|---|---|---|
activator | no | {activator_attrs, activator_type} (CAlertDialogActivatorSlotData) | No activator. |
title | yes | {} (CAlertDialogTitleSlotData) | none |
description | yes | {} (CAlertDialogDescriptionSlotData) | none |
default | no | {} (CAlertDialogDefaultSlotData) | Supplemental body omitted. |
cancel | yes | {cancel_attrs, cancel_type} (CAlertDialogCancelSlotData) | none |
action | yes | {action_attrs, action_type} (CAlertDialogActionSlotData) | none |
Events
Component events are callback inputs supplied through $c-props. Native browser events remain available through Alpine @... attributes.
CAlertDialog events
| Event | Signature | Trigger and timing | Detail | Controlled and cancellation behavior |
|---|---|---|---|---|
onOpenChange | (requestedOpen: boolean, detail: CAlertDialogOpenChangeDetail) => void (CAlertDialogOpenChangeDetail) | An owned trigger, Escape, explicit decision, or external native close requests a different visible state. | {reason: "trigger" | "escape" | "action" | "native", controlled: boolean, source: Element | EventTarget | null, returnValue: string} (CAlertDialogOpenChangeDetail) | Uncontrolled requests commit before notification. Controlled requests wait for the owner. Cancel and Action return cancel and action respectively. |
Methods
-
CSS
CSS variables to theme the components. Set them on an ancestor or the component itself.
CAlertDialog CSS variables
Apply these variables to CAlertDialog or one of its ancestors.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-alert-dialog-backdrop | color | Modal backdrop. | rgb(15 23 42 / 58%) |
--cui-alert-dialog-background | color | Surface background. | Canvas |
--cui-alert-dialog-foreground | color | Surface text. | CanvasText |
--cui-alert-dialog-border-color | color | Surface boundary. | Subtle CanvasText mix. |
--cui-alert-dialog-radius | length | Surface radius. | 0.875rem |
--cui-alert-dialog-shadow | shadow | Surface elevation. | 0 1.5rem 4rem rgb(15 23 42 / 28%) |
--cui-alert-dialog-inline-size | length | Preferred responsive width. | Size derived; 26rem at sm. |
--cui-alert-dialog-max-block-size | length | Maximum surface height. | calc(100dvb - 2rem) |
--cui-alert-dialog-padding | length | Surface region padding. | 1.25rem |
--cui-alert-dialog-gap | length | Gap between regions. | 1rem |
Attributes
HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.
CAlertDialog attributes
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Native AlertDialog | alertdialog | Exposes the urgent modal decision role. |
aria-modal | Native AlertDialog | true | Matches native showModal modality. |
aria-labelledby | Native AlertDialog | IDREF | References the required title. |
aria-describedby | Native AlertDialog | IDREF | References the required alert message. |
data-open | Native AlertDialog | present-or-absent | Mirrors effective native open state. |
data-size | Native AlertDialog | "sm" | "md" | "lg" | Mirrors effective responsive size. |
data-scroll | Native AlertDialog | "body" | "dialog" | Mirrors effective overflow mode. |
Selectors
Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.
CAlertDialog selectors
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="alert-dialog"] | Native Dialog | Stable modal root and attrs destination. |
[data-citry-ui-part="surface"] | Surface | Visual decision surface. |
[data-citry-ui-part="header"] | Header | Title layout. |
[data-citry-ui-part="title"] | Title | Required accessible name. |
[data-citry-ui-part="description"] | Description | Required alert message. |
[data-citry-ui-part="body"] | Body | Optional supplemental content. |
[data-citry-ui-part="actions"] | Actions | Required Cancel and Action controls. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] |
CAlertDialogSize | Literal["sm", "md", "lg"] |
CAlertDialogScroll | Literal["body", "dialog"] |
CAlertDialogActivatorSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
activator_attrs | dict[str, object] | - | Owned trigger relationships and marker. |
activator_type | Literal["button"] | - | Form-safe native Button type. |
CAlertDialogTitleSlotData
Empty dataclass: {}.
CAlertDialogDescriptionSlotData
Empty dataclass: {}.
CAlertDialogDefaultSlotData
Empty dataclass: {}.
CAlertDialogCancelSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
cancel_attrs | dict[str, object] | - | Owned close marker, cancel return value, and autofocus. |
cancel_type | Literal["button"] | - | Form-safe native Button type. |
CAlertDialogActionSlotData
| Field | Type | Default | Meaning |
|---|---|---|---|
action_attrs | dict[str, object] | - | Owned close marker and action return value. |
action_type | Literal["button"] | - | Form-safe native Button type. |
CAlertDialogOpenChangeDetail
| Field | Type | Default | Meaning |
|---|---|---|---|
reason | "trigger" | "escape" | "action" | "native" | - | Request origin. |
controlled | boolean | - | Whether client open currently owns state. |
source | Element | EventTarget | null | - | Browser source associated with the request. |
returnValue | string | - | cancel, action, or an empty string. |
Translation keys
-