intro

Drawer

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

Drawer

The Drawer organism is a sliding modal built upon the native browser implementation of the <dialog> element, combined with Svelte 5 contextual state. While Dialogs appear in the center of the viewport, Drawers slide in from the edges, often used for navigation, settings panels, or contextual side-tasks.

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

Curva & Concreto: The main Drawer wrapper rounds only the corners facing the interior of the screen (--r-1), acknowledging its interactivity while remaining anchored flush against the viewport edge. The internal boundaries between DrawerHeader, DrawerBody, and DrawerFooter are entirely straight (concrete).

Anatomy

Like the Dialog, a standard drawer relies on strict composition.

<script>
import { Drawer, DrawerHeader, DrawerBody, DrawerFooter } from 'cobogo/components/Drawer';
import Button from 'cobogo/components/Button';
let open = $state(false);
</script>
<Button onclick={() => open = true}>Open Drawer</Button>
<Drawer bind:open position="right" aria-label="Settings panel">
<DrawerHeader title="Application Settings" />
<DrawerBody>
<p>Adjust your preferences here. Changes are saved automatically.</p>
</DrawerBody>
<DrawerFooter>
<Button variant="secondary" onclick={() => open = false}>Close</Button>
</DrawerFooter>
</Drawer>

Implicit State Management

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

Position

The Drawer accepts a position prop, which dictates which side of the screen it slides in from.

  • right (default): Slides in from the right edge. Rounded on the left corners.
  • left: Slides in from the left edge. Rounded on the right corners.

WAI-ARIA and Accessibility

  • aria-label or aria-describedby: You must provide accessible names to the <Drawer> directly.
  • Native <dialog>: Inherits the aria-modal="true" implicitly in modern browsers.
  • Focus Trapping: By using showModal() and our internal FocusTrap utility, focus is naturally trapped within the Drawer. 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).