Feedback · AlertDialog

AlertDialog

Modal Dialog with role='alertdialog', forced modal=true and click-outside disabled. The user MUST choose Action or Cancel (Escape still cancels). The morfo declares only 3 parts (Provider + Action + Cancel) — every other part (Trigger / Portal / Overlay / Content / Title / Description / Header / Footer) is delegated to Dialog's runtime via variant='alertdialog', including all 6 semantic events. Auto-coloring on intent='risk' | 'threat' cascades the destructive tint to the Action button.

parts{compiled.parts.order.length} + 7 inherited events0 + {dialogEvents.length} via Dialog intent{intent} apg alertdialog ↗ open{open ? 'true' : 'false'} {#if lastChoice} last{lastChoice} {/if}
(lastChoice = null)}> {triggerLabel} {#if showOverlay}{/if} {#if showHeader} {title} {description} {:else} {title} {description} {/if} {#if showFooter} {cancelText} {actionText} {:else} {cancelText} {actionText} {/if}
trace {#if trace.length === 0} open the dialog, click Cancel/Action to see Dialog events {:else} {#each trace.slice(0, 3) as entry} {entry.event} · {entry.family}{entry.intent ? ' · ' + entry.intent : ''} {fmtTime(entry.at)} {/each} {/if} open {String(open)} {#if lastChoice} last {lastChoice} {/if}
{#if tab === 'live'}

Controls

intent is the key knob — switching to risk / threat auto-colors the Action button (red / amber) via an eidos cascade, and primes the sema layer for a destructive-confirmation perceptual signature.

soma Provider props
eidos Content props · forwarded to Dialog
Composition · toggle structural wrappers in / out
Demo content · literal text rendered into the dialog
eidos Action · visual props forwarded to <Button>; intent inherits from the dialog
eidos Cancel · variant narrowed to ControlVariant; always neutral palette
soma headless · forced modal + role='alertdialog' + click-outside ignore svelte
{somaSnippet}
eidos visual · full composition with Portal/Overlay/Header/Footer svelte
{eidosSnippet}
{/if} {#if tab === 'api'}

API reference

AlertDialog declares 3 parts of its own (Provider + Action + Cancel). Trigger / Portal / Overlay / Content / Title / Description / Header / Footer come from Dialog via soma's runtime delegation. Below are the alert-dialog-specific props; for the inherited props see the Dialog demo.

AlertDialog (Provider)
PropTypeDefaultDescription
idstringautoStable identifier.
open bindablebooleanfalseWhether the dialog is open.
onOpenChange / onOpenChangeComplete(open: boolean) => void—Fire on every transition start / animation settle.
disabledbooleanfalseDisable the Trigger; dialog stays closed.
intent'neutral' | 'risk' | 'threat''neutral'Doctrinal intent. Narrowed from Dialog's full set — alert dialogs gate destructive actions. Drives the auto-color cascade on Action.
AlertDialog.Content
PropTypeDefaultDescription
size eidosResponsiveProp<'sm' | 'md' | 'lg' | 'xl' | 'full'>'md'Modal width preset (forwarded to Dialog).
position eidosDialogPosition (3×3 anchor grid)'middle-center'Where on the viewport.
escapeKeydownBehavior'close' | 'ignore' | 'defer-otherwise-close' | 'defer-otherwise-ignore''close'Escape does cancel by convention (overrides Dialog's 'defer' default).
interactOutsideBehaviorsame as above'ignore'Forced — click outside cannot dismiss. The user MUST choose Action or Cancel.
…inheritedDialogContentProps—trapFocus, loop, preventScroll, forceMount, onOpenAutoFocus, onCloseAutoFocus, onEscapeKeydown, etc.
AlertDialog.Action
PropTypeDefaultDescription
aria-labelstring"Confirm"Overrides the default accessible name.
onclick(e: MouseEvent) => void—Business handler. The default close runs LAST — consumer logic gets first chance to gate.
variant eidosSelectionVariant: 'solid' | 'outline' | 'ghost''solid'Forwarded to the inner <Button>. Narrowed from ButtonVariant per DEMO_AUTHORING_GUIDE §12.7 — 3-value SelectionVariant keeps 'solid' as the CTA default while staying in the canonical chip rhythm.
size eidos'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Button size scale.
intent eidos'neutral' | 'affirm' | 'fulfill' | 'risk' | 'threat' | 'loss'inheritsWhen omitted, reads the parent AlertDialog.intent (neutral · risk · threat) so a flagged dialog paints a matching Action automatically.
color · rounded · iconOnly · icon · endIcon eidosButton props—Standard Button visual knobs forwarded through.
child{`Snippet<[{ props; intent }]>`}—Opt out of <Button> entirely. The dialog's resolved intent is passed alongside props.
…native button attrsPrimitiveButtonAttributes—Renders a native <button type='button'>.
AlertDialog.Cancel
PropTypeDefaultDescription
aria-labelstring"Cancel"Overrides the default accessible name.
onclick(e: MouseEvent) => void—Business handler. Default close runs last.
variant eidosControlVariant: 'surface' | 'outline' | 'ghost''outline'Forwarded to <Button>. Narrowed from ButtonVariant per DEMO_AUTHORING_GUIDE §12.7 (form-control surface).
size eidos'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Button size scale.
intent eidosButtonIntent'neutral'Stays neutral by default so it contrasts with the (potentially destructive) Action.
color eidosColorRole'neutral'Forced to neutral so the outline reads as gray regardless of Button's default primary.
rounded · iconOnly · icon · endIcon eidosButton props—Standard Button visual knobs.
…native button attrsPrimitiveButtonAttributes—By convention, receives initial focus — render BEFORE Action in DOM order.
Inherited from Dialog

Same surface as Dialog. Listed for at-a-glance reference; the prop tables live in the Dialog demo.

PartNotes
TriggerRenders a native <button> with aria-haspopup='dialog' + aria-expanded.
PortalPortal to document.body (no props).
OverlayBackdrop. Optional via composition (toggle in / out).
TitleWired to Content's aria-labelledby.
DescriptionWired to Content's aria-describedby.
Header / FooterStructural wrappers — pure layout.
Reference parity
FeatureRadixbits-uiark-uiEidos (this)
Forced modal=true✓✓✓✓
role='alertdialog'✓✓✓✓
Click-outside ignored✓✓✓✓
Escape cancels (overrides Dialog)✓✓✓✓
Dedicated Action / Cancel parts✓✓✓✓
intent prop (risk/threat auto-color)———✓
Runtime delegation to Dialog———✓
Sema event inheritance (6 events)———✓
{/if} {#if tab === 'morfo'}

morfo · declarative contract

The alert-dialog morfo declares only the Action + Cancel button parts (Provider is virtual). Trigger / Content / Overlay / Title / Description / Header / Footer come from the Dialog morfo via soma's runtime delegation (variant='alertdialog' on the Dialog provider) — which also brings the full Dialog event vocabulary. Source: src/uix/morfo/components/alert-dialog.ts.

FieldValue
name"{alertDialogMorfo.name}"
kebab"{alertDialogMorfo.kebab}"
scope[{alertDialogMorfo.scope.map((s) => `"${s}"`).join(', ')}]
apg{alertDialogMorfo.apg}
parts.length{alertDialogMorfo.parts.length}
events.length0 (delegates to Dialog · {dialogEvents.length})
focus.initial"first-focusable"
focus.traptrue
focus.return"trigger"
Parts (own)
{#each partsList as part (part.kebab)} {/each}
PartMarkerElementRoleArchetypeOptional
{part.kebab} [{part.marker}] <{part.defaultElement}> {part.role ?? '—'} {part.archetype ?? '—'} {part.optional ? 'yes' : 'no'}
{#each alertDialogMorfo.parts as rawPart (rawPart.kebab)} {@const partAny = rawPart as unknown as { kebab: string; aria?: ReadonlyArray<{ attr: string; value: { kind: string }; condition?: { when: string; prop?: string; part?: string }; severity?: string }>; keyboard?: ReadonlyArray<{ key: string; action: string }> }} {@const dataAttrs = compiled.contracts.dataAttrsByPart.get(partAny.kebab) ?? []} {@const ariaAttrs = partAny.aria ?? []} {@const keyboard = partAny.keyboard ?? []} {#if dataAttrs.length || ariaAttrs.length || keyboard.length}
{partAny.kebab}
{#if dataAttrs.length}
{#each dataAttrs as attr (attr.attr)} {/each}
data-attrValuesSource kind
{attr.attr} {attr.values ? attr.values.join(' | ') : '—'} {'value' in attr && attr.value ? (attr as { value: { kind: string } }).value.kind : '—'}
{/if} {#if ariaAttrs.length}
{#each ariaAttrs as a (a.attr)} {/each}
aria-attrSource kindConditionSeverity
{a.attr} {a.value.kind} {a.condition ? `when ${a.condition.when}${a.condition.prop ? ` (${a.condition.prop})` : ''}${a.condition.part ? ` (${a.condition.part})` : ''}` : 'always'} {a.severity ?? 'required'}
{/if} {/if} {/each}
Inherited events (from Dialog)

The runtime stamps these events on the Content / Action / Cancel targets when the dialog opens / closes / commits. AlertDialog does NOT declare its own events array — the perceptual surface is identical to Dialog's. The Sema tab plays them.

{#each dialogEvents as action (action.name)} {@const sem = action.semantic} {@const intentDecl = 'intent' in sem ? sem.intent : undefined} {@const intentStr = typeof intentDecl === 'string' ? intentDecl : intentDecl ? `fromProp:${(intentDecl as { fromProp?: string }).fromProp ?? '?'}` : '—'} {/each}
namefamilyverbsequenceintenttarget
{action.name} {sem.family} {sem.verb ?? '—'} {sem.sequence ?? 'pre'} {intentStr} {action.target}
{/if} {#if tab === 'sema'}

sema · events + perceptual signature

0 events declared by alert-dialog morfo; perceptual surface inherited from Dialog (6 events). The intent prop on the Provider drives intent for the commit-* family on the Action button — risk / threat gets the destructive-confirmation signature (sharper timbre + saturated motion).

{#each dialogEvents as action (action.name)} {@const intentDecl = 'intent' in action.semantic ? action.semantic.intent : undefined} {@const effectiveIntent = typeof intentDecl === 'string' ? intentDecl : (intentDecl ? intent : undefined)} {/each}
NameFamilyVerbSequenceIntentTarget partPlay
{action.name} {action.semantic.family} {action.semantic.verb ?? '—'} {action.semantic.sequence ?? 'pre'} {effectiveIntent ?? (intentDecl ? `fromProp → ${intent}` : '—')} {action.target}
{/if} {#if tab === 'recipe'}

Eidos recipe

Source: src/uix/eidos/components/alert-dialog/alert-dialog.css. Only the Action + Cancel buttons get bespoke selectors — the chrome (overlay, content panel, header, footer, title, description) is inherited from dialog.css because the soma runtime emits the same data-dialog-* markers under variant='alertdialog'.

SelectorSourceConcern
[data-alert-dialog-action]morfoSolid primary button (neutral intent).
[data-alert-dialog-cancel]morfoOutline secondary button. Stays neutral regardless of intent.
[data-dialog-content][data-color='risk'] [data-alert-dialog-action]eidosAuto-color cascade: risk-flagged dialog ⇒ red Action.
[data-dialog-content][data-color='threat'] [data-alert-dialog-action]eidosSame cascade for threat-flagged ⇒ amber Action.
[data-dialog-overlay]morfoInherited backdrop dim.
[data-dialog-content]morfoInherited modal panel chrome.
[data-dialog-content][data-state='open' | 'closed']morfoInherited enter / exit transitions.
[data-dialog-header] / [data-dialog-footer]morfoInherited layout wrappers.
{/if} {#if tab === 'a11y'}

Accessibility

Follows the APG alertdialog pattern. Content emits role='alertdialog' (vs Dialog's role='dialog') so screen readers announce with alert semantics. Cancel receives initial focus by convention (render it BEFORE Action in DOM order) — the safe choice becomes the default when the user just presses Enter.

Keyboard
KeyEffect
EscapeCancel (fires Cancel's onclick + closes).
Tab / Shift+TabCycle focus inside the dialog (focus trap).
Enter on ActionConfirm (fires Action's onclick + closes).
Enter on CancelCancel (fires Cancel's onclick + closes).
Click outsideIgnored. The user MUST choose Action or Cancel.
ARIA contract
PartAttributeValue
triggeraria-haspopup"dialog"
triggeraria-expanded{`{open}`}
triggeraria-controls{``}
contentrole"alertdialog"
contentaria-modal"true" (forced)
contentaria-labelledby{``}</td></tr> <tr><td class="name">content</td><td>aria-describedby</td><td class="type">{`<description id>`}</td></tr> <tr><td class="name">action</td><td>type</td><td class="type">"button"</td></tr> <tr><td class="name">action</td><td>aria-label</td><td class="type">"Confirm" (default) or <code>{`{aria-label}`}</code></td></tr> <tr><td class="name">cancel</td><td>type</td><td class="type">"button"</td></tr> <tr><td class="name">cancel</td><td>aria-label</td><td class="type">"Cancel" (default) or <code>{`{aria-label}`}</code></td></tr> <tr><td class="name">overlay</td><td>aria-hidden</td><td class="type">"true"</td></tr> </tbody> </table> </div> </section> {/if} </div>