Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new

Drawer

A drawer component for navigation.

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Reka UI.

Installation

Complete project setup first. Your configuration must select vue/reka and include your Design System ID.

pnpm exec frontfriend download drawer -f vue --primitive reka

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

<script setup lang="ts">
import { Drawer } from "@/components/ui/drawer";
import { DrawerTrigger } from "@/components/ui/drawer";
import { Button } from "@/components/ui/button";
import { DrawerContent } from "@/components/ui/drawer";
import { DrawerHeader } from "@/components/ui/drawer";
import { DrawerTitle } from "@/components/ui/drawer";
import { DrawerDescription } from "@/components/ui/drawer";
import { DrawerBody } from "@/components/ui/drawer";
import { DrawerFooter } from "@/components/ui/drawer";
import * as UI from "@/components/ui/drawer";

const Component = UI.Drawer;

const args = {
  "side": "bottom",
  "lgSide": "right",
  "height": "auto",
  "width": "md",
} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown> & {
    side?: "bottom" | "left" | "right" | "top";
    lgSide?: "bottom" | "left" | "right" | "top";
    height?: "auto" | "full";
    width?: "xs" | "sm" | "md" | "lg" | "3xl" | "5xl" | "full" | "fit";
  };
</script>

<template>
  <Drawer :side="args.side" :lg-side="args.lgSide"
    ><DrawerTrigger as-child
      ><Button variant="outline">Open Drawer</Button></DrawerTrigger
    ><DrawerContent :height="args.height" :width="args.width"
      ><DrawerHeader
        ><DrawerTitle>Move Goal</DrawerTitle
        ><DrawerDescription
          >Set your daily activity goal.</DrawerDescription
        ></DrawerHeader
      ><DrawerBody><p>Drawer content goes here.</p></DrawerBody
      ><DrawerFooter><Button>Submit</Button></DrawerFooter></DrawerContent
    ></Drawer
  >
</template>

Examples

Default

<script setup lang="ts">
import { Drawer } from "@/components/ui/drawer";
import { DrawerTrigger } from "@/components/ui/drawer";
import { Button } from "@/components/ui/button";
import { DrawerContent } from "@/components/ui/drawer";
import { DrawerHeader } from "@/components/ui/drawer";
import { DrawerTitle } from "@/components/ui/drawer";
import { DrawerDescription } from "@/components/ui/drawer";
import { DrawerBody } from "@/components/ui/drawer";
import { DrawerFooter } from "@/components/ui/drawer";
import * as UI from "@/components/ui/drawer";

const Component = UI.Drawer;

const args = {
  "side": undefined,
  "lgSide": undefined,
  "height": undefined,
  "width": undefined,
} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <Drawer :side="args.side" :lg-side="args.lgSide"
    ><DrawerTrigger as-child
      ><Button variant="outline">Open Drawer</Button></DrawerTrigger
    ><DrawerContent :height="args.height" :width="args.width"
      ><DrawerHeader
        ><DrawerTitle>Move Goal</DrawerTitle
        ><DrawerDescription
          >Set your daily activity goal.</DrawerDescription
        ></DrawerHeader
      ><DrawerBody><p>Drawer content goes here.</p></DrawerBody
      ><DrawerFooter><Button>Submit</Button></DrawerFooter></DrawerContent
    ></Drawer
  >
</template>

Sides

<script setup lang="ts">
import { Drawer } from "@/components/ui/drawer";
import { DrawerTrigger } from "@/components/ui/drawer";
import { Button } from "@/components/ui/button";
import { DrawerContent } from "@/components/ui/drawer";
import { DrawerHeader } from "@/components/ui/drawer";
import { DrawerTitle } from "@/components/ui/drawer";
import { DrawerDescription } from "@/components/ui/drawer";
import { DrawerBody } from "@/components/ui/drawer";
import { DrawerFooter } from "@/components/ui/drawer";
import { DrawerClose } from "@/components/ui/drawer";
import * as UI from "@/components/ui/drawer";

const Component = UI.Drawer;

const args = {

} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <div class="flex gap-4">
    <Drawer
      v-for="option in ['top', 'right', 'bottom', 'left']"
      :key="option"
      :side="option"
      :lg-side="option"
      ><DrawerTrigger as-child
        ><Button>{{ option }}</Button></DrawerTrigger
      ><DrawerContent
        ><DrawerHeader
          ><DrawerTitle>Move goal</DrawerTitle
          ><DrawerDescription
            >Set your activity goal.</DrawerDescription
          ></DrawerHeader
        ><DrawerBody>Review your changes.</DrawerBody
        ><DrawerFooter
          ><DrawerClose>Cancel</DrawerClose><Button>Save</Button></DrawerFooter
        ></DrawerContent
      ></Drawer
    >
  </div>
</template>

Scrollable

<script setup lang="ts">
import { Drawer } from "@/components/ui/drawer";
import { DrawerTrigger } from "@/components/ui/drawer";
import { Button } from "@/components/ui/button";
import { DrawerContent } from "@/components/ui/drawer";
import { DrawerHeader } from "@/components/ui/drawer";
import { DrawerTitle } from "@/components/ui/drawer";
import { DrawerDescription } from "@/components/ui/drawer";
import { DrawerBody } from "@/components/ui/drawer";
import { DrawerFooter } from "@/components/ui/drawer";
import * as UI from "@/components/ui/drawer";

const Component = UI.Drawer;

const args = {

} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <Drawer
    ><DrawerTrigger as-child
      ><Button variant="outline">Open Scrollable</Button></DrawerTrigger
    ><DrawerContent height="full"
      ><DrawerHeader
        ><DrawerTitle>Ullamco dolor laboris reprehenderit.</DrawerTitle
        ><DrawerDescription
          >Scroll through the full content below.</DrawerDescription
        ></DrawerHeader
      ><DrawerBody
        ><p v-for="i in 8" :key="i">
          But I must explain to you how all this mistaken idea of denouncing
          pleasure and praising pain was born and I will give you a complete
          account of the system, and expound the actual teachings of the great
          explorer of the truth.
        </p></DrawerBody
      ><DrawerFooter
        ><Button variant="outline">Cancel</Button
        ><Button>Save</Button></DrawerFooter
      ></DrawerContent
    ></Drawer
  >
</template>

Footer Alignment

<script setup lang="ts">
import { Drawer } from "@/components/ui/drawer";
import { DrawerTrigger } from "@/components/ui/drawer";
import { Button } from "@/components/ui/button";
import { DrawerContent } from "@/components/ui/drawer";
import { DrawerHeader } from "@/components/ui/drawer";
import { DrawerTitle } from "@/components/ui/drawer";
import { DrawerDescription } from "@/components/ui/drawer";
import { DrawerBody } from "@/components/ui/drawer";
import { DrawerFooter } from "@/components/ui/drawer";
import { DrawerClose } from "@/components/ui/drawer";
import * as UI from "@/components/ui/drawer";

const Component = UI.Drawer;

const args = {

} satisfies Partial<
  InstanceType<typeof Component> extends { $props: infer Props } ? Props : {}
> &
  Record<string, unknown>;
</script>

<template>
  <div class="flex gap-4">
    <Drawer
      v-for="option in ['end', 'justify', 'start', 'stretch']"
      :key="option"
      ><DrawerTrigger as-child
        ><Button>{{ option }}</Button></DrawerTrigger
      ><DrawerContent
        ><DrawerHeader
          ><DrawerTitle>Move goal</DrawerTitle
          ><DrawerDescription
            >Set your activity goal.</DrawerDescription
          ></DrawerHeader
        ><DrawerBody>Review your changes.</DrawerBody
        ><DrawerFooter :align="option"
          ><DrawerClose>Cancel</DrawerClose><Button>Save</Button></DrawerFooter
        ></DrawerContent
      ></Drawer
    >
  </div>
</template>

API reference

Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Reka UI.

Drawer

Prop Type Default Description
lgSide "bottom" | "left" | "right" | "top" —
overlay boolean —
side "bottom" | "left" | "right" | "top" —

DrawerBody

Prop Type Default Description
class HTMLAttributes["class"] —
noPadding boolean —

DrawerContent

Prop Type Default Description
class HtmlHTMLAttributes["class"] —
container HTMLDivElement | null —
containerClassname string —
height "auto" | "full" —
width "xs" | "sm" | "md" | "lg" | "3xl" | "5xl" | "full" | "fit" —

DrawerDescription

Prop Type Default Description
class HtmlHTMLAttributes["class"] —

DrawerFooter

Prop Type Default Description
align "end" | "justify" | "start" | "stretch" —
class HtmlHTMLAttributes["class"] —

DrawerHeader

Prop Type Default Description
class HtmlHTMLAttributes["class"] —
closeIcon boolean —

DrawerTitle

Prop Type Default Description
class HtmlHTMLAttributes["class"] —

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.