|
|
5 months ago | |
|---|---|---|
| .. | ||
| README.md | 5 months ago | |
| alert-dialog-action.svelte | 5 months ago | |
| alert-dialog-cancel.svelte | 5 months ago | |
| alert-dialog-content.svelte | 5 months ago | |
| alert-dialog.css | 5 months ago | |
| alert-dialog.svelte | 5 months ago | |
| index.ts | 5 months ago | |
| types.ts | 5 months ago | |
README.md
<AlertDialog> — eidos
Visual wrapper over soma/components/alert-dialog. A modal Dialog with
role="alertdialog", forced modal=true and click-outside disabled
(interactOutsideBehavior='ignore'). The user MUST choose
Action or Cancel. Escape still cancels.
Usage
<script lang="ts">
import { AlertDialog } from '$uix/eidos/components/alert-dialog';
let open = $state(false);
</script>
<AlertDialog bind:open intent="risk">
<AlertDialog.Trigger>Delete project…</AlertDialog.Trigger>
<AlertDialog.Portal>
<AlertDialog.Overlay />
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>Delete project?</AlertDialog.Title>
<AlertDialog.Description>
This action cannot be undone. All data will be lost.
</AlertDialog.Description>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
<AlertDialog.Action>Delete</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog.Portal>
</AlertDialog>
Differences from <Dialog>
| Concern | Dialog | AlertDialog |
|---|---|---|
| role | dialog |
alertdialog |
| modal | optional | forced true |
| click-outside | 'close' (default) |
'ignore' (forced) |
| Escape | 'close' |
'close' (preserved) |
| Initial focus | first focusable | Cancel (by convention; render it first) |
| Footer pattern | open-ended | always Cancel + Action for destructive choices |
| Doctrinal intent | full set | narrowed: neutral | risk | threat |
Parts
| Part | Origin | Notes |
|---|---|---|
AlertDialog (root) |
eidos | Wraps soma's AlertDialog.Provider |
Trigger |
inherited from Dialog | Identical contract |
Portal |
inherited from Dialog | Identical contract |
Overlay |
inherited from Dialog | Identical contract |
Content |
eidos (alert-dialog) | Wraps soma's AlertDialog.Content (forces escapeKeydownBehavior='close') |
Title |
inherited from Dialog | Identical contract |
Description |
inherited from Dialog | Identical contract |
Header |
inherited from Dialog | Identical contract |
Footer |
inherited from Dialog | Identical contract |
Action |
eidos (alert-dialog) | Primary destructive button — auto-colors from dialog's intent |
Cancel |
eidos (alert-dialog) | Secondary safe button — stays neutral |
Recipe
alert-dialog.css styles only the Action + Cancel buttons. Chrome
(overlay, panel, header, etc.) comes from dialog.css — soma's
AlertDialog re-uses the Dialog runtime, so the same data-dialog-*
markers reach the DOM.
Buttons consume the Toggle palette tokens (--toggle-color-*) — same
"interactive button" vocabulary used across <Toggle>,
<ToggleGroup.Item> and other action surfaces.
Passive justification
Passive at the alert-dialog morfo level — the morfo declares only
the Action / Cancel button parts (Provider is virtual). All
behavioural events (open/close presence, escape, focus trap, …) come
from the Dialog runtime that soma's AlertDialog delegates to. There
is no alert-dialog-specific sema event to fire; the
commit-confirm and close-cancel flows live inside the Dialog
morfo's vocabulary.
The component IS interactive from the user's perspective. "Passive" here is a contract-layer classification, not a UX one.
Baseline
WAI-ARIA APG Alert Dialog: https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/
Soma docs at src/uix/soma/components/alert-dialog/README.md cover
focus management (Cancel-first), nesting, and the interactOutside
behavioural locking.
Comparativa
| Lib | Role forced | Modal forced | Click-outside | Intent narrowing | Auto-Color Action |
|---|---|---|---|---|---|
| Radix Primitives | ✓ | ✓ | ignore (forced) | — | — |
| Bits UI | ✓ | ✓ | ignore | — | — |
| Ark UI | ✓ | ✓ | ignore | — | — |
| Chakra v3 | ✓ | ✓ | option | colorPalette |
by colorPalette |
| Radix Themes | ✓ | ✓ | ignore | color |
by color |
| shadcn/ui | ✓ | ✓ | ignore | — | manual variant="destructive" |
| Eidos | ✓ | ✓ | ignore | neutral|risk|threat |
✓ — cascades from dialog's data-color |
Decisiones
- Intent narrowing. The morfo restricts to
neutral | risk | threat(noaffirm/fulfill) because alert dialogs gate destructive or irreversible actions — celebrating them is the wrong affordance. The recipe still picks upaffirmif a consumer overrides the color by hand (defensive fallback in the cascade). - Auto-color the Action button based on the dialog's
data-color. Anintent="risk"AlertDialog gets a red Action without manual recipe code. Chakra and Radix Themes do this implicitly viacolorPalette— Eidos makes it explicit via the intent contract. - Cancel stays neutral. Contrast with the Action is the canonical visual cue for "this is the safe choice" (Radix Themes, Material Design, iOS Human Interface Guidelines all agree).
- Re-use Dialog's eidos parts rather than duplicate Trigger / Overlay / Title / etc. Soma already delegates to Dialog under the hood; the visual layer mirrors that.
Gaps
| Gap | Disposición | Detalle |
|---|---|---|
Soma's commit-confirm / close-cancel events not yet wired to a per-component sema cascade |
diferir | The commit family base ships sound; suffices for now. Add cascade if we want different sounds for confirm-destroy vs confirm-affirm. |
No async onAction returning Promise to gate close |
diferir | Soma's wrapper closes synchronously; consumers gate via a parent state machine instead. Open spec question. |
size='xs' / 'sm' shaping for very small confirmations |
diferir | Inherits Dialog's size scale (sm/md/lg/xl/full). Smaller would require Dialog-level changes. |
Reference
- Radix UI Primitives: https://www.radix-ui.com/primitives/docs/components/alert-dialog
- Bits UI: https://bits-ui.com/docs/components/alert-dialog
- Ark UI: https://ark-ui.com/docs/components/alert-dialog
- Chakra v3: https://chakra-ui.com/docs/components/dialog
- Radix Themes: https://www.radix-ui.com/themes/docs/components/alert-dialog
- shadcn/ui: https://ui.shadcn.com/docs/components/alert-dialog