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 primitive (DialogRoot imported from reka-ui as Sheet)
SheetTriggerTrigger primitive (DialogTrigger imported from reka-ui)
SheetPortalPortal primitive (DialogPortal imported from reka-ui)
SheetContentPanel content with direction variants, built-in close button
SheetHeaderHeader container
SheetFooterFooter container
SheetTitleStyled panel title wrapping Reka UI DialogTitle
SheetDescriptionStyled panel description wrapping Reka UI DialogDescription
SheetCloseClose primitive (DialogClose imported from reka-ui)

Reka UI Primitives ​

Sheet, SheetTrigger, SheetPortal, and SheetClose are local aliases for DialogRoot, DialogTrigger, DialogPortal, and DialogClose, imported from reka-ui. The five styled components listed in the generated API below are imported from BrutxUI.

Sheet accepts the boolean open value for controlled state with v-model:open, and emits update:open with the new boolean state. defaultOpen initializes uncontrolled state and defaults to false; modal defaults to true. Its default slot contains the trigger and panel, and receives the current open state and a close() function.

SheetContent forwards additional attributes and event listeners to DialogContent. Event names such as openAutoFocus can be listened to using @open-auto-focus in templates. The built-in close button uses localized sheet.close text and sits at the top-left for side="left", or at the top-right for other sides.

API Reference ​

SheetContent

SheetContent — Props
NameTypeDefaultDescription
side
"bottom" | "left" | "right" | "top" | undefined
"right"
The viewport edge from which the panel enters, controlling position, border, and transition direction. The close button is top-left for left and top-right otherwise.
Details

Declared type

NonNullable<"right" | "bottom" | "left" | "top" | null | undefined> | undefined

Literal values

  • "bottom"
  • "left"
  • "right"
  • "top"

Default value details

Resolved value
"right"

Source

SheetContent.vue:25

packages/ui/src/components/sheet/SheetContent.vue

class
string | undefined
undefined
CSS classes merged onto the floating content panel. Other attributes and listeners are forwarded through $attrs to Reka UI DialogContent.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

SheetContent.vue:26

packages/ui/src/components/sheet/SheetContent.vue

SheetContent — Events
NameSignature or typeDescription
@openAutoFocus
[event: Event]
A Reka UI event forwarded through $attrs before automatic focus on opening. Call preventDefault() to handle focus yourself.
Details

Declared type

[event: Event]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

@closeAutoFocus
[event: Event]
A Reka UI event forwarded through $attrs before restoring focus on closing. Its default focus behavior can be prevented.
Details

Declared type

[event: Event]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

@interactOutside
[event: PointerDownOutsideEvent | FocusOutsideEvent]
A Reka UI event forwarded through $attrs for a pointer press or focus interaction outside the panel. It can prevent dismissal caused by that interaction.
Details

Declared type

[event: PointerDownOutsideEvent | FocusOutsideEvent]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

@escapeKeyDown
[event: KeyboardEvent]
A Reka UI event forwarded through $attrs when the topmost panel receives Escape. It can prevent the default dismissal.
Details

Declared type

[event: KeyboardEvent]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

@pointerDownOutside
[event: PointerDownOutsideEvent]
A Reka UI event forwarded through $attrs when the pointer is pressed outside the panel. It can prevent the default dismissal.
Details

Declared type

[event: PointerDownOutsideEvent]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

@focusOutside
[event: FocusOutsideEvent]
A Reka UI event forwarded through $attrs when focus moves outside the panel. It can prevent the default handling of that outside interaction.
Details

Declared type

[event: FocusOutsideEvent]

Source

SheetContent.vue:61

packages/ui/src/components/sheet/SheetContent.vue

SheetContent — Slots
NameSignature or typeDescription
#default
{}
The panel body, typically composing SheetHeader, content, and SheetFooter. A localized built-in close button follows the content.
Details

Declared type

{}

Source

SheetContent.vue

packages/ui/src/components/sheet/SheetContent.vue

SheetDescription

SheetDescription — Props
NameTypeDefaultDescription
class
string | undefined
—
CSS classes merged onto the Reka UI description primitive, styled as supporting text by default.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

SheetDescription.vue:8

packages/ui/src/components/sheet/SheetDescription.vue

SheetDescription — Slots
NameSignature or typeDescription
#default
{}
Supporting panel text used for its accessible description. The description element is omitted when the slot has no meaningful content.
Details

Declared type

{}

Source

SheetDescription.vue

packages/ui/src/components/sheet/SheetDescription.vue

SheetFooter

SheetFooter — Props
NameTypeDefaultDescription
class
string | undefined
—
CSS classes merged onto the panel footer action area.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

SheetFooter.vue:7

packages/ui/src/components/sheet/SheetFooter.vue

SheetFooter — Slots
NameSignature or typeDescription
#default
{}
Footer buttons or other actions.
Details

Declared type

{}

Source

SheetFooter.vue

packages/ui/src/components/sheet/SheetFooter.vue

SheetHeader

SheetHeader — Props
NameTypeDefaultDescription
class
string | undefined
—
CSS classes merged onto the panel header container.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

SheetHeader.vue:7

packages/ui/src/components/sheet/SheetHeader.vue

SheetHeader — Slots
NameSignature or typeDescription
#default
{}
The panel title, description, and other header content.
Details

Declared type

{}

Source

SheetHeader.vue

packages/ui/src/components/sheet/SheetHeader.vue

SheetTitle

SheetTitle — Props
NameTypeDefaultDescription
class
string | undefined
—
CSS classes merged onto the Reka UI title primitive, styled as a bold heading by default.
Details

Declared type

string | undefined

Default value details

Not declared
—

Source

SheetTitle.vue:8

packages/ui/src/components/sheet/SheetTitle.vue

SheetTitle — Slots
NameSignature or typeDescription
#default
{}
The panel title used for its accessible name. The title element is omitted when the slot has no meaningful content.
Details

Declared type

{}

Source

SheetTitle.vue

packages/ui/src/components/sheet/SheetTitle.vue

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.