Skip to content

Sheet

A neo-brutalist side panel component that can slide in from any edge. Built on top of reka-ui's Dialog primitive.

Demo

Preview

Installation

pnpm dlx brutx-vue@latest add sheet

Usage

vue
<script setup>
import { DialogRoot as Sheet, DialogTrigger as SheetTrigger, DialogClose as SheetClose } from 'reka-ui'
import {
    SheetContent,
    SheetHeader,
    SheetFooter,
    SheetTitle,
    SheetDescription,
    Button,
} from 'brutx-ui-vue'
</script>

<template>
    <Sheet>
        <SheetTrigger as-child>
            <Button variant="outline">Open Sheet</Button>
        </SheetTrigger>
        <SheetContent side="right">
            <SheetHeader>
                <SheetTitle>Edit Profile</SheetTitle>
                <SheetDescription>
                    Make changes to your profile here.
                </SheetDescription>
            </SheetHeader>
            <div class="py-4">
                <p class="text-sm">Sheet content goes here.</p>
            </div>
            <SheetFooter>
                <SheetClose as-child>
                    <Button variant="outline">Cancel</Button>
                </SheetClose>
                <Button variant="primary">Save</Button>
            </SheetFooter>
        </SheetContent>
    </Sheet>
</template>

Direction Variants

DirectionDescription
topSlides in from the top
bottomSlides in from the bottom
leftSlides in from the left (max sm:max-w-sm)
rightSlides in from the right (default, max sm:max-w-sm)
vue
<script setup>
import { DialogRoot as Sheet, DialogTrigger as SheetTrigger } from 'reka-ui'
import { SheetContent, Button } from 'brutx-ui-vue'
</script>

<template>
    <Sheet>
        <SheetTrigger as-child>
            <Button>Open Left Sheet</Button>
        </SheetTrigger>
        <SheetContent side="left">
            <p>Content slides in from the left.</p>
        </SheetContent>
    </Sheet>
</template>

Sub-components

ComponentDescription
SheetRoot component (re-exported DialogRoot from reka-ui)
SheetTriggerTrigger to open the panel (re-exported DialogTrigger from reka-ui)
SheetPortalPortal rendering container (re-exported DialogPortal from reka-ui)
SheetContentPanel content with direction variants, built-in close button
SheetHeaderHeader container
SheetFooterFooter container
SheetTitlePanel title (re-exported DialogTitle from reka-ui)
SheetDescriptionPanel description text (re-exported DialogDescription from reka-ui)
SheetCloseClose button (re-exported DialogClose from reka-ui)

Props

Sheet

Root component, inherits all props from reka-ui's DialogRoot.

PropTypeDefaultDescription
openbooleanControlled open state
defaultOpenbooleanDefault open state in uncontrolled mode
modalbooleantrueWhether the dialog is modal

SheetContent

PropTypeDefaultDescription
side'top' | 'bottom' | 'left' | 'right''right'Panel slide direction
classstringCustom CSS class

Note: SheetContent has a built-in close button (X icon in the top-right or top-left corner; when side="left", it appears in the top-left corner), so there is no need to add one manually. The close button's accessible text supports internationalization (sheet.close).

SheetHeader / SheetFooter / SheetTitle / SheetDescription

PropTypeDefaultDescription
classstringCustom CSS class

Events

Sheet

EventPayloadDescription
update:openbooleanEmitted when the open state changes, used for v-model:open two-way binding
open-changebooleanEmitted when the open state changes

SheetContent

Inherits all events from reka-ui's DialogContent.

EventPayloadDescription
open-auto-focusEventEmitted when auto-focused after content opens
close-auto-focusEventEmitted when auto-focused after content closes
interact-outsideInteractOutsideEventEmitted when interacting outside the content
escape-key-downKeyboardEventEmitted when the Escape key is pressed
pointer-down-outsidePointerDownOutsideEventEmitted when pressing a pointer outside the content

Slots

SlotScopeDescription
defaultDefault slot for placing SheetTrigger, SheetContent, and other sub-components

SheetContent

SlotScopeDescription
defaultDefault slot for placing panel content (SheetHeader, content area, SheetFooter, etc.)

SheetHeader / SheetFooter / SheetTitle / SheetDescription

SlotScopeDescription
defaultDefault slot

Accessibility

  • Keyboard: Supports Escape to close the panel
  • ARIA Attributes: Automatically manages aria-labelledby (linked to SheetTitle) and aria-describedby (linked to SheetDescription)
  • Focus Management: Focus is locked inside the panel when open; focus is restored to the trigger when closed

Brute force builds.