Components/Drawer

Drawer

Side panels and form surfaces

VerifiedSince 0.3.4

Usage

Basic Drawer

The common drawer pattern, with a confirmation dialog above it. Tab stays in the confirmation and Escape closes only the confirmation.

Loading demo...

Best Practices

  • Use Drawer for long forms, audit details, permission matrices, and flows that need footer actions.
  • Keep title meaningful even when showHeader=false; it becomes the dialog's accessible fallback label.
  • Prefer size and full; keep width only for old call sites that have not migrated yet.
  • Use mobileAdapt=false only when preserving side direction is more important than bottom-sheet ergonomics on small screens.

API Reference

Props

PropertyTypeDefaultDescription
visibleControls drawer visibility
titleTitle text
sizeActive-axis size; width for left/right and height for top/bottom; numbers are px and full maps to 100%
fullOpen at 100% on the active axis, equivalent to size="full"
width-Deprecated compatibility alias; use size instead
directionSlide-in direction
showHeaderRender the header area
showFooterRender the footer slot area
showCloseShow close button
closeOnClickMaskClose on mask click
closeOnPressEscapeClose on Escape key
maskEffectMask visual effect
panelTransparentMake the panel translucent so the back layer shows through
mobileAdaptForce bottom direction on mobile viewport
zIndex-Custom z-index. When unset the runtime z-index manager assigns one (seeded at `10000`, incremented per drawer); set it manually only to coexist with externally fixed layers.
lazyDefer rendering slot content until the drawer first opens. The panel itself stays mounted, so the slide-out animation is unaffected; content is kept alive after the first open, so reopening never re-runs child setup. Set `false` when a child must mount eagerly.

Events

PropertyTypeDefaultDescription
update:visible-Emitted on visibility change
open-Emitted when opened
close-Emitted when closed

Slots

PropertyTypeDefaultDescription
default--Main content
header--Custom header; slot props: { close, title, titleId }
footer--Footer area; slot props: { close }

Direction

Drawers support left, right, top, and bottom. Mobile viewports adapt to bottom by default unless mobile-adapt="false" is set.

Direction

Four-direction drawers. The size prop maps to width for left/right and height for top/bottom.

Loading demo...

Size and Fullscreen

Size and Fullscreen

Use the unified size prop for the active axis: width for left/right, height for top/bottom. It supports px, rem, percentages, any CSS length, and full. You can also use the more discoverable boolean full prop, equivalent to size="full". width remains as a compatibility alias for old code.

Loading demo...

Use the header / footer slots to customize the chrome, or disable them with show-header / show-footer. Built-in header/footer separators reuse TxDivider. mask-effect supports blur, opacity, and transparent; panel-transparent lets the panel surface show content behind it.

Loading demo...

Compatibility example: use the footer slot to add action buttons.

EXAMPLE.VUE
<template>
  <TxDrawer v-model:visible="visible" title="Form">
    <form>
      <input type="text" placeholder="Name" />
    </form>

    <template #footer>
      <TxButton @click="visible = false">Cancel</TxButton>
      <TxButton type="primary" @click="handleSave">Save</TxButton>
    </template>
  </TxDrawer>
</template>

Close Behavior

EXAMPLE.VUE
<template>
  <!-- Disable mask click -->
  <TxDrawer
    v-model:visible="visible"
    title="Persistent"
    :close-on-click-mask="false"
  >
    <p>Close via the button only.</p>
  </TxDrawer>

  <!-- Disable Escape close -->
  <TxDrawer
    v-model:visible="visible2"
    title="Disable Escape"
    :close-on-press-escape="false"
  >
    <p>Escape key won't close this drawer.</p>
  </TxDrawer>
</template>

Events

EXAMPLE.VUE
<template>
  <TxDrawer
    v-model:visible="visible"
    title="Event Demo"
    @open="handleOpen"
    @close="handleClose"
  >
    <p>Content</p>
  </TxDrawer>
</template>

Dashboard Navigation Composition

Admin pages should not put every setting into one large form. Use TxTabs for first-level sections, TxDropdownMenu for lightweight actions in the current section, TxPopover for short explanations, and TxDrawer for dense configuration.

Dashboard navigation shell

A screenshot-verified Tabs / DropdownMenu / Popover / Drawer composition for Dashboard settings pages.

Loading demo...

Overview

  • The drawer root exposes role="dialog" and aria-modal="true"; with a header it links the title through instance-scoped aria-labelledby, and without a header it falls back to title as aria-label.
  • Opening the drawer focuses the drawer root; hiding or unmounting restores focus to the element that was active before opening.
  • The close button, mask click, and Escape close paths emit update:visible(false) and close by default; closeOnClickMask=false and closeOnPressEscape=false block their respective paths.
  • Keys already handled by another control, or originating in another modal dialog, are not handled again by the drawer. A confirmation above the drawer owns Tab, Shift+Tab and Escape without a page-level CSS-class or body-event guard.
  • showClose=false removes the default close button without changing mask or Escape behavior.
  • mobileAdapt=true forces bottom direction on mobile; set :mobile-adapt="false" to preserve the requested direction.

Technologies

  • Component source: packages/tuffex/packages/components/src/drawer/src/TxDrawer.vue.
  • Types: packages/tuffex/packages/components/src/drawer/src/types.ts.
  • Verified coverage: Coverage: packages/tuffex/packages/components/src/drawer/__tests__/drawer.test.ts verifies visibility emits, focus restoration, ARIA labeling, close controls, size resolution, mobile adaptation, and separator rendering.
查看源码
packages/tuffex/packages/components/src/drawer/index.ts
  • The drawer root already exposes role="dialog" / aria-modal="true" and title linkage; form fields inside still need explicit labels.
  • Opening stores the previously focused element and restores it on hide/unmount; avoid manually stealing focus from outside.
  • Dashboard settings pages should place long forms, permission matrices, and audit detail in Drawer rather than Popover.
  • Built-in header/footer separators come from TxDivider, avoiding duplicated border styling.