Drawer

Slide-in panel anchored to one edge of the viewport. Modal-style focus trap and Escape close.

Overview

The Drawer component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.

Why this exists

Drawers provide side-panel access to supplementary content without navigating away. They are ideal for detail views, filters, or settings panels that need to reference the main content.

Mental model

A drawer slides in from an edge (right, left, bottom) and shares the screen with the main content. Unlike a modal, it feels less disruptive and is better for reference workflows.

When to use

• Detail panels (user profile, order details) • Filter panels in data tables • Settings panels • Multi-step wizards that need page context

When not to use

• Do not use for critical confirmations — use a modal • Avoid for navigation — use a sidebar • Do not use on mobile for full-screen content — use a page route

Basic example

The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.

Variants

Each variant communicates a different meaning. Choose based on priority, not aesthetics.

Single default variant.

Sizes

Size should match the importance and context of the component.

  • md — md size.

States

This component reacts seamlessly to the following interaction and data states:

  • hidden — Not rendered in the DOM.
  • visible — Rendered and interactive.
  • default — Resting appearance before interaction.
  • hover — Pointer is over the element — visual feedback via color or shadow.
  • focus — Keyboard or tab focus — shows ring indicator for accessibility.
  • active — Currently selected or in use.
  • disabled — Non-interactive — grayed out, cursor not-allowed.
  • open — Component is expanded or visible.
  • closed — Component is collapsed or hidden.

Anatomy

• Overlay — optional, dimmed background • Panel — slides in from edge • Header — title and close button • Body — scrollable content • Footer — optional actions

Usage guidelines

  • Use the right edge for detail panels.
  • Use the left edge for navigation or filters.
  • Allow the overlay to be optional for non-blocking drawers.

Do and Don't

Do

  • Use right side for detail views.
  • Allow scroll within the drawer.
  • Provide a clear close action.

Don't

  • Do not open drawers on page load.
  • Do not nest drawers.
  • Do not use for destructive confirmations.

Accessibility

Drawer has role="dialog" when modal. Focus is trapped. Escape closes. Slide direction affects reading order.

Role:dialog

ARIA Attributes

  • aria-modal

Keyboard Navigation

  • Escape: Closes the overlay or cancels the action
  • Tab: Moves focus to the next interactive element

Customization

Width and slide direction are configurable. Z-index uses --z-overlay.

Compose with React cva()

Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.

import { cva, cn, type VariantProps } from '@byteion/react';

const myDrawer = cva('base classes…', {
 variants: {
  accent: { soft:'border-primary-200', loud:'border-primary-500' },
 },
 defaultVariants: { accent:'soft' },
});

type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myDrawer>;

Compose with Vue cva()

Use the exportedcva() +cn() utilities inside standard Vue setup blocks.

<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';

interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();

const myDrawer = cva('base classes…', {
  variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});

const cls = computed(() => myDrawer({ accent: props.accent, class: attrs.class as string | undefined }));
</script>

Runtime events

Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.

HTML / JS events

  • bi:drawer:hide
  • bi:drawer:show

React callbacks

  • onClose() => void

Vue emits

  • update:modelValue[v: boolean]
  • update:open[v: boolean]
  • close[]

Remote / AJAX

This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.

API Reference

Requires data-bi-component="drawer" with placement attribute.

HTML Data Attributes

  • data-bi-drawer
  • data-bi-drawer-placement
  • data-bi-drawer-toggle
  • data-bi-drawer-hide
  • data-bi-backdrop

React Props · DrawerProps

Extracted directly fromreact/src/components/Drawer.tsx.

export interface DrawerProps {
  open: boolean;
  onClose: () => void;
  /** Edge the drawer slides in from. */
  side?: 'left' | 'right' | 'top' | 'bottom';
  size?: 'sm' | 'md' | 'lg' | 'xl';
  staticBackdrop?: boolean;
  keyboard?: boolean;
  /** Backdrop visual treatment. */
  backdrop?: 'clear' | 'soft';
  title?: ReactNode;
  description?: ReactNode;
  footer?: ReactNode;
  children?: ReactNode;
  className?: string;
}

Vue Props · DrawerProps

Extracted directly fromvue/src/components/Drawer.vue.

export interface DrawerProps {
  modelValue?: boolean;
  open?: boolean;
  /** Edge the drawer slides in from. */
  side?: 'left' | 'right' | 'top' | 'bottom';
  size?: 'sm' | 'md' | 'lg' | 'xl';
  staticBackdrop?: boolean;
  keyboard?: boolean;
  backdrop?: 'clear' | 'soft';
  title?: string;
  description?: string;
}

Developer tips

• Drawer vs Modal: use Drawer when the user needs page context; use Modal when the user must decide before continuing. • Sticky footer: keep action buttons (Save/Cancel) visible when body content scrolls — the footer is outside the scroll area. • Avoid hidden pages: if a drawer contains multi-step forms, consider promoting to a page route. • Mobile behavior: prefer bottom sheet (side="bottom") for short mobile tasks and full-page routing for long tasks. • Destructive confirmation: for delete actions, have the drawer open a Modal confirmation rather than committing directly.

Common mistakes

Avoid hardcoded neutral colors, placeholder-only labels, duplicated primary actions, and missing keyboard states. Keep this component on Byteion tokens so dashboard, admin, POS, ERP, ecommerce back-office, Laravel, React, and Vue starter-kit screens can be rebranded without rewriting markup.

Production usage tips

  • Test with keyboard only — trigger via Enter/Space, tab through all controls, close via Escape.
  • Test focus trap and focus restoration — focus should cycle within the drawer and return to the trigger on close.
  • Test staticBackdrop and keyboard={false} — backdrop click and Escape should be blocked respectively.
  • Test long content scrolling — body scrolls independently, header and footer stay fixed.
  • Test inside dashboards, tables, and layouts with overflow-hidden parents — drawer must render via portal to body.
  • Test mobile bottom placement (side="bottom") — ensure close button is visible and drag handle has sufficient contrast.
  • Test dark mode and branded themes — all tokens (bg-card, text-card-foreground, shadow-modal) adapt automatically.
  • Keep React and Vue APIs aligned with the core schema — side/size props map to CSS classes and data attributes.

Premium examples

Advanced patterns available in Byteion Pro:

• Resizable drawer width — draggable edge handle to resize the panel width live. • Mobile bottom sheet — compact bottom drawer with drag-to-dismiss and handle affordance. • Split-view detail drawer — two-column layout inside the drawer for master-detail previews. • Filter drawer with saved presets — left drawer with filter controls, apply/reset, and saved filter preset dropdown. • Cart drawer for ecommerce — right drawer with item list, quantity controls, total, and checkout CTA. • Approval workflow drawer — right drawer showing purchase request, approval timeline, and approve/reject actions. • Activity timeline drawer — right drawer with scrollable event timeline, filters, and expandable entries.

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.

Explore Pro Components