You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/alert-dialog
dev 32598d7cf3
fix(alert-dialog): narrow Action.variant to canonical SelectionVariant (3)
5 months ago
..
README.md feat(alert-dialog): port from soma to eidos (Tier 1 sprint, 2/5) 5 months ago
alert-dialog-action.svelte refactor(alert-dialog): Action/Cancel render <Button>; intent flows via snippet 5 months ago
alert-dialog-cancel.svelte refactor(alert-dialog): Action/Cancel render <Button>; intent flows via snippet 5 months ago
alert-dialog-content.svelte feat(alert-dialog): port from soma to eidos (Tier 1 sprint, 2/5) 5 months ago
alert-dialog.css refactor(alert-dialog): Action/Cancel render <Button>; intent flows via snippet 5 months ago
alert-dialog.svelte feat(alert-dialog): port from soma to eidos (Tier 1 sprint, 2/5) 5 months ago
index.ts feat(alert-dialog): port from soma to eidos (Tier 1 sprint, 2/5) 5 months ago
types.ts fix(alert-dialog): narrow Action.variant to canonical SelectionVariant (3) 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 (no affirm / fulfill) because alert dialogs gate destructive or irreversible actions — celebrating them is the wrong affordance. The recipe still picks up affirm if a consumer overrides the color by hand (defensive fallback in the cascade).
  • Auto-color the Action button based on the dialog's data-color. An intent="risk" AlertDialog gets a red Action without manual recipe code. Chakra and Radix Themes do this implicitly via colorPalette — 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

Powered by TurnKey Linux.