bq-drawer is a side panel that slides in from the edge of the screen to surface navigation menus, settings, notifications, or contextual actions. Users keep the underlying page in view, so they can complete focused tasks without losing context.
The drawer manages its own open/close animation and backdrop. Call the
show() and hide() methods programmatically, or toggle the open prop, to control visibility. Do not remove the element from the DOM to hide it — use hide() instead.When to use
Use drawer when
- You need to surface supplementary content — navigation menus, settings, notifications, or contextual actions — without navigating away from the current page
- Users need a convenient way to access additional information or functionality while maintaining a clean and organised layout
- The content is too complex or lengthy for a tooltip, popover, or dropdown
Do not use drawer when
- Its presence would add unnecessary complexity or confusion — for simple applications where all necessary information can be displayed directly on the main screen
- It would obscure essential content or functionality
- There are better alternatives available for presenting supplementary information or navigation options, such as a dedicated page or
bq-dialog
Patterns
With footer
Use a footer to keep secondary actions — such as confirm, cancel, or links — anchored at the bottom of the panel. This separates actions from the main content and keeps them visible while users scroll.
Without footer
Use a drawer without a footer when the panel only displays content or primary actions inline. This keeps the layout focused and avoids reserving space for actions you don’t need.
Anatomy
| Part | Element | Description |
|---|---|---|
| 1 | Headline | The title text displayed in the drawer header |
| 2 | Icon (optional) | An optional icon displayed alongside the headline in the header |
| 3 | Close icon button | The icon button that dismisses the drawer |
| 4 | Container / Slot | The main content area that holds the default slot; supports rich media, forms, icons, buttons, and more |
| 5 | Divider | The horizontal rule between the body and footer (shown when a footer is present) |
| 6 | Actions (optional) | Footer action buttons; typically one primary button and one secondary button |
Design guidelines
Position
Always position the drawer close to the relevant content to avoid confusing users and ensure intuitive navigation.end (default)
The panel slides in from the end (right in LTR layouts). Use this for filter panels, detail views, and secondary settings — placing them on the right keeps them adjacent to the content being acted on.
Container
The drawer container area can hold rich media, images, forms, icons, buttons, and more. Its internal layout can be adjusted for the use case — use flexbox or grid inside the default slot to control how content is arranged.Backdrop
The backdrop dims the page content behind the drawer, reinforcing that the drawer is in focus.Enable the backdrop (
enable-backdrop) when the drawer contains a form or detail view that should feel visually separate from the page. For lightweight navigation drawers that share the screen with the page, omit the backdrop to keep the experience lighter.Width
The default drawer width is320px, controlled by --bq-drawer--width. Increase it for content-heavy panels such as filter forms or data tables, but keep it narrow enough that the underlying page remains recognisably visible.
Footer
Add a footer to house actions that apply to all content in the panel (e.g. save a form or close the panel). Buttons are left-aligned, and only one primary button should be used at a time. The footer slot is only rendered when it contains content.Keep it simple and clear
While drawers can efficiently store additional information not included on the parent page, it is essential to avoid overwhelming users with excessive content. Proper organisation and grouping of information within the drawer are crucial to ensure clarity and usability.Usage
Default
The default state of the drawer component displays a standard drawer with a header, content area, and footer. It typically slides in from the end (right) edge of the screen. Use this for general purposes when you need a drawer to provide additional content or options without disrupting the main view.No footer
The no-footer variant removes the footer section, providing a cleaner interface without additional controls at the bottom. Use this when the drawer’s primary purpose is to display content or options that do not require secondary actions.Start position
Theposition prop allows you to specify the edge from which the drawer appears. Use position="start" to open from the left edge — ideal for primary navigation menus.
Options
With backdrop
The backdrop variant adds a semi-transparent overlay behind the drawer, helping to focus user attention on the drawer content while dimming the background. Enable this variant when you want to visually separate the drawer from the rest of the interface and provide a modal-like experience.Custom footer divider
Replace the default footer divider by slotting a custom element intoslot="footer-divider". The example below uses bq-divider with a custom stroke.
Close behavior
By default, clicking outside the panel or pressingEsc closes the drawer. Set close-on-click-outside or close-on-esc to prevent those interactions when the user must explicitly confirm before dismissing.
Best practices
DoPlace drawers along the screen’s edge — typically the right side — to prevent interference with navigational components on the left edge.
Don’tInset a drawer significantly from the screen edges. Doing so makes its position and scroll behaviour unclear and can obscure primary content.
DoAlways provide a meaningful
title slot so users and screen readers know the purpose of the panel before interacting with its content.Don’tLeave the title slot empty. A drawer without a title gives assistive technologies no label for the
role="dialog" and leaves sighted users without orientation.DoUse
enable-backdrop when the drawer contains a form or a detail view that requires focused attention — it visually separates the panel from the underlying page.Don’tUse a drawer for critical, blocking confirmations such as destructive action prompts. Use
bq-dialog for those — a drawer implies the page behind it is still accessible.DoPlace primary actions (Save, Apply, Confirm) in the
footer slot so they are always accessible at the bottom of the panel, even when the body content is long and scrollable.Don’tBury primary action buttons in the scrollable body. Users who do not scroll to the bottom will miss them and may not know how to complete the task.
DoUse
close-on-click-outside and close-on-esc together when the panel contains unsaved changes that would be lost if the user accidentally dismisses it.Don’tLock the close behavior by default on every drawer. Preventing Esc and outside-click dismissal frustrates users who expect those standard interactions to work.
Accessibility
bq-drawer renders a role="dialog" panel with aria-modal="true" and aria-labelledby pointing to the built-in title element. When the drawer is closed, aria-hidden="true" is set on the panel so assistive technologies skip its content entirely.
The built-in close button has label="Close" and is announced by screen readers as “Close, button”.
As a developer, you are responsible for:
- Moving focus into the drawer when it opens — the component does not trap focus automatically. When you call
show(), move focus to the first interactive element inside the panel or to the panel itself so keyboard users can begin navigating immediately. - Returning focus to the trigger when the drawer closes — call
hide()and then restore focus to the element that opened the drawer so keyboard users are not left disoriented. - Providing a descriptive title — the
aria-labelledbyattribute references the title slot. Screen readers announce this text when the dialog opens. An empty or generic title such as “Panel” makes the dialog purpose unclear. - Avoid nesting focusable elements in the backdrop — the backdrop does not receive focus; keep interactive content inside the panel.
API reference
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
closeOnClickOutside | close-on-click-outside | If true, the drawer will not close when clicking outside the panel | boolean | false |
closeOnEsc | close-on-esc | If true, the drawer will not close when the Esc key is pressed | boolean | false |
enableBackdrop | enable-backdrop | If true, a backdrop overlay is shown when the drawer opens | boolean | false |
open | open | If true, the drawer is visible | boolean | false |
position | position | Defines the edge the drawer slides from | 'start' | 'end' | 'end' |
placement | placement | Deprecated. Use position instead. Defines the edge the drawer slides from | 'left' | 'right' | 'right' |
Methods
| Method | Description | Signature |
|---|---|---|
show() | Opens the drawer and emits bqOpen | show() => Promise<void> |
hide() | Closes the drawer and emits bqClose | hide() => Promise<void> |
Events
| Event | Description | Type |
|---|---|---|
bqOpen | Emitted when the drawer starts to open | CustomEvent<void> |
bqAfterOpen | Emitted after the open animation completes | CustomEvent<void> |
bqClose | Emitted when the drawer starts to close | CustomEvent<void> |
bqAfterClose | Emitted after the close animation completes | CustomEvent<void> |
Slots
| Slot | Description |
|---|---|
| (default) | The main body content of the drawer |
title | The title displayed in the header |
footer | Footer content — typically action buttons; only rendered when content is present |
button-close | Custom content for the close button; defaults to a close icon |
footer-divider | Content placed in the divider between body and footer |
Shadow parts
| Part | Description |
|---|---|
backdrop | The <div> holding the backdrop overlay |
panel | The <div> holding the full drawer surface |
header | The <header> holding the title and close button |
title | The <div> that holds the title slot content |
button-close | The bq-button wrapper for the close button |
button-close__btn | The native <button> inside the close control |
button-close__label | The label <span> inside the close button |
body | The <main> holding the default slot content |
footer | The <footer> holding footer slot content |
CSS custom properties
Resources
Interactive playground
Explore drawer variants and states in Storybook
Source code
View the component source on GitHub