Theme
Version
GitHub PyPI Discord
On this page

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.

AlertDialog at a glance
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.

Acknowledge a blocking error
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".

Control an asynchronous decision
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.

Use native decision Buttons
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.

Compare AlertDialog sizes
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
Customize AlertDialog
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(...).

InputTypeDefaultEffect
idstr | NonegeneratedSets native Dialog identity and title, description, and activator relationships.
openboolFalseSets the server-visible initial modal state.
close_on_escapeboolTruePermits 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)NoneAdds native Dialog classes.
styleCStyleValue | None (CStyleValue)NoneAdds native Dialog inline styles.
attrsMapping[str, object] | NoneNoneAdds 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 />.

InputTypeOmitted behaviorEffect
openboolean | null | undefinedReleases control and preserves effective state.Controls modal visibility while supplied as a Boolean.
closeOnEscapeboolean | undefinedUses the server fallback.Controls Escape and platform cancel behavior.
size"sm" | "md" | "lg" | undefinedUses the server fallback.Controls data-size and width.
scroll"body" | "dialog" | undefinedUses the server fallback.Controls data-scroll and overflow.
onOpenChange((open, detail) => void) | undefinedNo 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

SlotRequiredDataFallback
activatorno{activator_attrs, activator_type} (CAlertDialogActivatorSlotData)No activator.
titleyes{} (CAlertDialogTitleSlotData)none
descriptionyes{} (CAlertDialogDescriptionSlotData)none
defaultno{} (CAlertDialogDefaultSlotData)Supplemental body omitted.
cancelyes{cancel_attrs, cancel_type} (CAlertDialogCancelSlotData)none
actionyes{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

EventSignatureTrigger and timingDetailControlled 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.

VariableTypePurposeDefault
--cui-alert-dialog-backdropcolorModal backdrop.rgb(15 23 42 / 58%)
--cui-alert-dialog-backgroundcolorSurface background.Canvas
--cui-alert-dialog-foregroundcolorSurface text.CanvasText
--cui-alert-dialog-border-colorcolorSurface boundary.Subtle CanvasText mix.
--cui-alert-dialog-radiuslengthSurface radius.0.875rem
--cui-alert-dialog-shadowshadowSurface elevation.0 1.5rem 4rem rgb(15 23 42 / 28%)
--cui-alert-dialog-inline-sizelengthPreferred responsive width.Size derived; 26rem at sm.
--cui-alert-dialog-max-block-sizelengthMaximum surface height.calc(100dvb - 2rem)
--cui-alert-dialog-paddinglengthSurface region padding.1.25rem
--cui-alert-dialog-gaplengthGap between regions.1rem

Attributes

HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.

CAlertDialog attributes

AttributeElementTypeMeaning
roleNative AlertDialogalertdialogExposes the urgent modal decision role.
aria-modalNative AlertDialogtrueMatches native showModal modality.
aria-labelledbyNative AlertDialogIDREFReferences the required title.
aria-describedbyNative AlertDialogIDREFReferences the required alert message.
data-openNative AlertDialogpresent-or-absentMirrors effective native open state.
data-sizeNative AlertDialog"sm" | "md" | "lg"Mirrors effective responsive size.
data-scrollNative 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

SelectorElementPurpose
[data-citry-ui-part="alert-dialog"]Native DialogStable modal root and attrs destination.
[data-citry-ui-part="surface"]SurfaceVisual decision surface.
[data-citry-ui-part="header"]HeaderTitle layout.
[data-citry-ui-part="title"]TitleRequired accessible name.
[data-citry-ui-part="description"]DescriptionRequired alert message.
[data-citry-ui-part="body"]BodyOptional supplemental content.
[data-citry-ui-part="actions"]ActionsRequired Cancel and Action controls.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue]
CAlertDialogSizeLiteral["sm", "md", "lg"]
CAlertDialogScrollLiteral["body", "dialog"]

CAlertDialogActivatorSlotData

FieldTypeDefaultMeaning
activator_attrsdict[str, object]-Owned trigger relationships and marker.
activator_typeLiteral["button"]-Form-safe native Button type.

CAlertDialogTitleSlotData

Empty dataclass: {}.

CAlertDialogDescriptionSlotData

Empty dataclass: {}.

CAlertDialogDefaultSlotData

Empty dataclass: {}.

CAlertDialogCancelSlotData

FieldTypeDefaultMeaning
cancel_attrsdict[str, object]-Owned close marker, cancel return value, and autofocus.
cancel_typeLiteral["button"]-Form-safe native Button type.

CAlertDialogActionSlotData

FieldTypeDefaultMeaning
action_attrsdict[str, object]-Owned close marker and action return value.
action_typeLiteral["button"]-Form-safe native Button type.

CAlertDialogOpenChangeDetail

FieldTypeDefaultMeaning
reason"trigger" | "escape" | "action" | "native"-Request origin.
controlledboolean-Whether client open currently owns state.
sourceElement | EventTarget | null-Browser source associated with the request.
returnValuestring-cancel, action, or an empty string.

Translation keys

-