intro

Dialog

A modal organism built on the native HTML5 `<dialog>` element, enforcing focus trapping and contextual state distribution.

Dialog

The Dialog organism relies heavily on the native browser implementations of the <dialog> element combined with Svelte 5 contextual state.

By relying on the native showModal() method, focus trapping, stacking contexts, and top-layer positioning are entirely managed by the browser.

Curva & Concreto: The main Dialog wrapper sports an --r-1 curve, acknowledging its interactivity. However, the internal boundaries between DialogHeader, DialogBody, and DialogFooter are entirely straight (concrete) where they meet, distinguishing structural joints from external interactive bounds.

Anatomy

A standard dialog relies on strict composition.

<script>
import { Dialog, DialogHeader, DialogBody, DialogFooter } from 'cobogo/components/Dialog';
import Button from 'cobogo/components/Button';
let open = $state(false);
</script>
<Button onclick={() => open = true}>Open Dialog</Button>
<Dialog bind:open aria-label="Action required">
<DialogHeader title="System Update" />
<DialogBody>
<p>Please confirm that you want to apply the following updates.</p>
</DialogBody>
<DialogFooter>
<Button variant="secondary" onclick={() => open = false}>Cancel</Button>
<Button onclick={() => open = false}>Confirm</Button>
</DialogFooter>
</Dialog>

Implicit State Management

Like Tabs and Accordion, the Dialog manages the state of its subcomponents inherently through Context. The DialogHeader retrieves a closeDialog function from the parent Dialog, meaning you do not need to manually bind the close button inside the header.

WAI-ARIA and Accessibility

  • aria-label or aria-describedby: You must provide accessible names to the <Dialog> directly.
  • Native <dialog>: Inherits the aria-modal="true" implicitly in modern browsers but we enforce it just in case.
  • Focus Trapping: By using showModal() and our internal FocusTrap utility, focus is naturally trapped within the Dialog. If focus escapes the modal bounds (e.g. programmatically), the trap aggressively intercepts the Tab key and pulls focus back inside to guarantee compliance with WCAG 2.1.2 (No Keyboard Trap).
  • Escape Dismissal: The Esc key automatically manages closure (manually intercepted to maintain Svelte $state parity and out-transitions).