Drawer

A panel that slides out from the edge of the screen to display side content or forms.

Component Features

  • 👆 Gesture Driven: Supports swipe gestures to close, providing a smooth interaction experience similar to native apps.
  • 📏 Adaptive Size: Supports content-adaptive height or specified fixed sizes, adapting to various content amounts.
  • 🧭 Multi-direction Support: Supports sliding out from the top, bottom, left, and right directions of the screen.
  • 🎨 Theme Customization: Supports global theme customization based on BrConfigProvider.

Basic Usage

<script setup lang="ts">
import { ref } from 'vue'
import { 
  BrDrawer, 
  BrDrawerTrigger, 
  BrDrawerContent, 
  BrDrawerHeader, 
  BrDrawerFooter, 
  BrDrawerTitle, 
  BrDrawerDescription,
  BrDrawerClose,
  BrButton 
} from '@breezeui/vue'

const isOpen = ref(false)
</script>

<template>
  <div class="flex flex-col items-center gap-4">
    <BrDrawer v-model:open="isOpen">
      <BrDrawerTrigger as-child>
        <BrButton>Open Drawer</BrButton>
      </BrDrawerTrigger>
      <BrDrawerContent>
        <BrDrawerHeader>
          <BrDrawerTitle>Edit Profile</BrDrawerTitle>
          <BrDrawerDescription>
            Edit your profile here. Click save when you're done.
          </BrDrawerDescription>
        </BrDrawerHeader>
        
        <div class="p-6 space-y-4">
          <div class="h-32 bg-muted rounded-md flex items-center justify-center text-muted-foreground">
            Content Area
          </div>
        </div>

        <BrDrawerFooter>
          <BrButton>Save Changes</BrButton>
          <BrDrawerClose as-child>
            <BrButton variant="outline">Cancel</BrButton>
          </BrDrawerClose>
        </BrDrawerFooter>
      </BrDrawerContent>
    </BrDrawer>
    
    <p class="text-sm text-muted-foreground">
      Status: {{ isOpen ? 'Open' : 'Closed' }}
    </p>
  </div>
</template>

Direction

<script setup lang="ts">
import { ref } from 'vue'
import { 
  BrDrawer, 
  BrDrawerTrigger, 
  BrDrawerContent, 
  BrDrawerHeader, 
  BrDrawerFooter, 
  BrDrawerTitle, 
  BrDrawerDescription,
  BrDrawerClose,
  BrButton 
} from '@breezeui/vue'

const directions = ['top', 'bottom', 'left', 'right'] as const
</script>

<template>
  <div class="flex flex-wrap gap-4 justify-center">
    <div v-for="dir in directions" :key="dir">
      <BrDrawer :direction="dir">
        <BrDrawerTrigger as-child>
          <BrButton variant="outline">{{ dir.toUpperCase() }}</BrButton>
        </BrDrawerTrigger>
        <BrDrawerContent>
          <BrDrawerHeader>
            <BrDrawerTitle>Drawer Title - {{ dir.toUpperCase() }}</BrDrawerTitle>
            <BrDrawerDescription>
              Current drawer slide direction: {{ dir }}
            </BrDrawerDescription>
          </BrDrawerHeader>
          
          <div class="p-6 space-y-4">
            <div class="h-32 bg-muted rounded-md flex items-center justify-center text-muted-foreground">
              Content Area ({{ dir }})
            </div>
          </div>

          <BrDrawerFooter>
            <BrDrawerClose as-child>
              <BrButton>Close</BrButton>
            </BrDrawerClose>
          </BrDrawerFooter>
        </BrDrawerContent>
      </BrDrawer>
    </div>
  </div>
</template>

Sizes

<script setup lang="ts">
import { ref } from 'vue'
import { 
  BrDrawer, 
  BrDrawerTrigger, 
  BrDrawerContent, 
  BrDrawerHeader, 
  BrDrawerFooter, 
  BrDrawerTitle, 
  BrDrawerDescription,
  BrDrawerClose,
  BrButton 
} from '@breezeui/vue'

const isOpen = ref(false)
</script>

<template>
  <div class="flex flex-col items-center gap-4">
    <BrDrawer v-model:open="isOpen">
      <BrDrawerTrigger as-child>
        <BrButton variant="outline">Custom Size (via class)</BrButton>
      </BrDrawerTrigger>
      <BrDrawerContent class="max-h-[50vh]">
        <BrDrawerHeader>
          <BrDrawerTitle>Custom Height</BrDrawerTitle>
          <BrDrawerDescription>
            This drawer has a max-height set via `class="max-h-[50vh]"`.
          </BrDrawerDescription>
        </BrDrawerHeader>
        
        <div class="p-6 space-y-4">
          <div class="h-20 bg-muted rounded-md flex items-center justify-center text-muted-foreground">
            Content Area (50% Height)
          </div>
        </div>

        <BrDrawerFooter>
          <BrDrawerClose as-child>
            <BrButton>Close</BrButton>
          </BrDrawerClose>
        </BrDrawerFooter>
      </BrDrawerContent>
    </BrDrawer>
  </div>
</template>

Close Button

<script setup lang="ts">
import {
  BrDrawer,
  BrDrawerTrigger,
  BrDrawerContent,
  BrDrawerHeader,
  BrDrawerTitle,
  BrDrawerDescription,
  BrDrawerFooter,
  BrDrawerClose,
  BrButton,
} from '@breezeui/vue'
</script>

<template>
  <BrDrawer>
    <BrDrawerTrigger as-child>
      <BrButton variant="outline">With Close Button</BrButton>
    </BrDrawerTrigger>
    <BrDrawerContent show-close>
      <BrDrawerHeader>
        <BrDrawerTitle>Closable Drawer</BrDrawerTitle>
        <BrDrawerDescription>Click the close icon in the top right corner to close the drawer.</BrDrawerDescription>
      </BrDrawerHeader>
      <div class="p-4 pb-0">
        <div class="flex items-center justify-center space-x-2">
          <span class="text-2xl font-bold">Content Area</span>
        </div>
        <div class="mt-3 h-[120px] w-full rounded-md bg-muted/50 flex items-center justify-center text-muted-foreground">
          Here is some content...
        </div>
      </div>
      <BrDrawerFooter>
        <BrButton>Submit</BrButton>
        <BrDrawerClose as-child>
          <BrButton variant="outline">Cancel</BrButton>
        </BrDrawerClose>
      </BrDrawerFooter>
    </BrDrawerContent>
  </BrDrawer>
</template>

API

Props

NameTypeDefaultDescription
openbooleanfalseWhether the drawer is open
defaultOpenbooleanfalseDefault open state
directionstring'bottom'Direction: top, bottom, left, right
dismissiblebooleantrueWhether the drawer can be dismissed
modalbooleantrueWhether the drawer is modal

DrawerContent Props

NameTypeDefaultDescription
showHandlebooleanfalseWhether to show the handle
showClosebooleanfalseWhether to show the close button
classstring-Custom class
shouldScaleBackgroundbooleanfalseWhether to scale background
activeSnapPointstring | number-Active snap point

Slots

NameDescription
defaultTrigger content
contentDrawer content
headerHeader content
footerFooter content

Emits

EventDescriptionParameters
update:openFired when open state changes(value: boolean)
closeFired when closed-

Usage Example


<template>
  <BrDrawer v-model:open="isOpen">
    <BrDrawerTrigger>
      <BrButton>Open Drawer</BrButton>
    </BrDrawerTrigger>
    <BrDrawerContent>
      <BrDrawerHeader>
        <BrDrawerTitle>Title</BrDrawerTitle>
      </BrDrawerHeader>
      <div>Content...</div>
    </BrDrawerContent>
  </BrDrawer>
</template>