Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Drawer

Slide-out panel with backdrop overlay, keyboard dismissal, and left/right positioning for off-canvas navigation, filters, and detail views.

Components Drawer
navigation interactive
<arc-drawer>

Overview

Drawer is a slide-out panel that emerges from the left or right edge of the viewport, overlaying page content behind a semi-transparent backdrop. It is the standard pattern for housing navigation menus on mobile, exposing filter panels in data-heavy applications, or showing contextual detail views without navigating away from the current page. When the Drawer opens it locks body scroll, preventing the user from accidentally interacting with background content. A smooth CSS transform animation slides the panel into view while the backdrop fades in, creating a clear spatial relationship between the panel and the page behind it. Closing is handled automatically via the built-in close button, pressing the Escape key, or clicking the backdrop — all of which fire an `arc-close` event so your application state stays in sync. Choose Drawer over Modal when the supplementary content is navigation-oriented, when users need to glance back at the main page while interacting with the panel, or when the content is tall and benefits from full-height scrolling. For blocking decisions that require explicit user action, use Modal instead.

Guidelines

When to use

  • Use for mobile navigation menus that slide in from the left edge
  • Use for filter or settings panels in data-heavy dashboards
  • Provide a clear, short heading that tells the user what the panel contains
  • Keep the drawer width reasonable — the default 300px works for most navigation use cases
  • Use `position="right"` for detail views and contextual information panels
  • Always listen for the `arc-close` event to keep your open state in sync

When not to use

  • Do not use a Drawer for critical confirmations — use Modal instead
  • Do not nest a Drawer inside another Drawer
  • Do not put complex multi-step forms in a Drawer — consider a full page or Modal
  • Do not auto-open a Drawer on page load without a clear user-initiated trigger
  • Do not remove the backdrop — users expect click-outside-to-close behavior
  • Do not place unrelated content in the drawer heading area — keep it for the title and close button

Features

  • Slides in from the left or right edge via CSS transforms with configurable `position` prop
  • Semi-transparent backdrop overlay dims the page and captures click-to-close
  • Escape key dismissal with automatic keyboard listener management
  • Body scroll lock while open prevents background content interaction
  • Built-in header bar with heading text and close button
  • Scrollable body region for long content like navigation trees or filter forms
  • Fires `arc-close` custom event on any dismiss action for state synchronization
  • Max-width capped at 85vw so the drawer never fully obscures the page
  • CSS custom property theming via `--bg-surface`, `--border-subtle`, and `--text-primary`
  • Accessible with `role="dialog"`, `aria-modal="true"`, and `aria-label` from heading

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-button id="open-nav-drawer">Menu</arc-button>
<arc-drawer id="nav-drawer" heading="Navigation" position="left">
  <nav style="display:flex; flex-direction:column; gap:4px; padding:8px;">
    <a href="/dashboard" style="padding:10px 12px; border-radius:6px; color:var(--text-primary); text-decoration:none;">Dashboard</a>
    <a href="/projects" style="padding:10px 12px; border-radius:6px; color:var(--text-secondary); text-decoration:none;">Projects</a>
    <a href="/activity" style="padding:10px 12px; border-radius:6px; color:var(--text-secondary); text-decoration:none;">Activity</a>
    <a href="/settings" style="padding:10px 12px; border-radius:6px; color:var(--text-secondary); text-decoration:none;">Settings</a>
  </nav>
</arc-drawer>

<script>
  const openBtn = document.querySelector('#open-nav-drawer');
  const drawer = document.querySelector('#nav-drawer');
  openBtn.addEventListener('click', () => { drawer.open = true; });
  drawer.addEventListener('arc-close', () => { drawer.open = false; });
</script>
import { useState } from 'react';
import { Button, Drawer } from '@arclux/arc-ui-react';

function MobileNav() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Menu</Button>
      <Drawer open={open} heading="Navigation" position="left" onArcClose={() => setOpen(false)}>
        <nav style={{ display: 'flex', flexDirection: 'column', gap: 4, padding: 8 }}>
          <a href="/dashboard">Dashboard</a>
          <a href="/projects">Projects</a>
          <a href="/activity">Activity</a>
          <a href="/settings">Settings</a>
        </nav>
      </Drawer>
    </>
  );
}
<script setup>
import { ref } from 'vue';
import { Button, Drawer } from '@arclux/arc-ui-vue';

const open = ref(false);
</script>

<template>
  <Button @click="open = true">Menu</Button>
  <Drawer :open="open" heading="Navigation" position="left" @arc-close="open = false">
    <nav style="display:flex; flex-direction:column; gap:4px; padding:8px;">
      <a href="/dashboard">Dashboard</a>
      <a href="/projects">Projects</a>
      <a href="/activity">Activity</a>
      <a href="/settings">Settings</a>
    </nav>
  </Drawer>
</template>
<script>
  import { Button, Drawer } from '@arclux/arc-ui-svelte';

  let open = $state(false);
</script>

<Button onclick={() => open = true}>Menu</Button>
<Drawer {open} heading="Navigation" position="left" on:arc-close={() => open = false}>
  <nav style="display:flex; flex-direction:column; gap:4px; padding:8px;">
    <a href="/dashboard">Dashboard</a>
    <a href="/projects">Projects</a>
    <a href="/activity">Activity</a>
    <a href="/settings">Settings</a>
  </nav>
</Drawer>
import { Component } from '@angular/core';
import { Button, Drawer } from '@arclux/arc-ui-angular';

@Component({
  imports: [Button, Drawer],
  template: `
    <arc-button (click)="open = true">Menu</arc-button>
    <arc-drawer [open]="open" heading="Navigation" position="left" (arcClose)="open = false">
      <nav style="display:flex; flex-direction:column; gap:4px; padding:8px;">
        <a href="/dashboard">Dashboard</a>
        <a href="/projects">Projects</a>
        <a href="/activity">Activity</a>
        <a href="/settings">Settings</a>
      </nav>
    </arc-drawer>
  `,
})
export class MobileNavComponent {
  open = false;
}
import { createSignal } from 'solid-js';
import { Button, Drawer } from '@arclux/arc-ui-solid';

function MobileNav() {
  const [open, setOpen] = createSignal(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Menu</Button>
      <Drawer open={open()} heading="Navigation" position="left" onArcClose={() => setOpen(false)}>
        <nav style={{ display: 'flex', 'flex-direction': 'column', gap: '4px', padding: '8px' }}>
          <a href="/dashboard">Dashboard</a>
          <a href="/projects">Projects</a>
          <a href="/activity">Activity</a>
          <a href="/settings">Settings</a>
        </nav>
      </Drawer>
    </>
  );
}
import { useState } from 'preact/hooks';
import { Button, Drawer } from '@arclux/arc-ui-preact';

function MobileNav() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>Menu</Button>
      <Drawer open={open} heading="Navigation" position="left" onArcClose={() => setOpen(false)}>
        <nav style={{ display: 'flex', flexDirection: 'column', gap: 4, padding: 8 }}>
          <a href="/dashboard">Dashboard</a>
          <a href="/projects">Projects</a>
          <a href="/activity">Activity</a>
          <a href="/settings">Settings</a>
        </nav>
      </Drawer>
    </>
  );
}

API

open boolean false
Controls the visible state of the drawer. Set to `true` to slide the panel into view and activate the backdrop; set to `false` to run the exit animation, remove the backdrop, and restore body scroll.
position 'left' | 'right' 'left'
Which edge of the viewport the drawer slides in from. Use `left` for primary navigation menus and `right` for contextual detail panels, filter sidebars, or settings trays.
heading string ''
Text displayed in the drawer header bar. Also used as the `aria-label` for the dialog panel, ensuring screen readers announce the panel purpose when it opens.

Events

arc-close
Fired when the drawer closes via backdrop click or escape key

See Also