Logo VitNode
Documentation

Sheet

A panel that slides in from any edge of the screen for settings, filters and side tasks.

Preview

Usage

import { Button } from '@vitnode/core/components/ui/button'
import {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@vitnode/core/components/ui/sheet'
<Sheet>
  <SheetTrigger render={<Button variant="outline">Notifications</Button>} />
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Notifications</SheetTitle>
      <SheetDescription>Pick what lands in your inbox.</SheetDescription>
    </SheetHeader>
    <SheetFooter>
      <SheetClose render={<Button variant="outline">Done</Button>} />
    </SheetFooter>
  </SheetContent>
</Sheet>

SheetHeader and SheetFooter bring their own padding. Give the content between them px-4 to line up.

Side

side picks the edge: right (default), left, top or bottom. Left and right sheets take 3/4 of a phone screen and cap at max-w-sm from sm up.

<SheetContent side="left">...</SheetContent>

Forms

A sheet suits short settings: a handful of fields about one thing. Place the fields with layout in a scrollable body, and end with AutoFormSheetFooter. It shows an "Unsaved changes" note, a Cancel button that closes the sheet, and a Save button that stays disabled until something changes.

import { AutoFormSheetFooter } from '@vitnode/core/components/form/auto-form-sheet-footer'
const [open, setOpen] = React.useState(false)

<Sheet onOpenChange={setOpen} open={open}>
  <SheetContent className="w-full gap-0 data-[side=right]:w-full data-[side=right]:sm:max-w-lg">
    <SheetHeader className="border-b pe-14">
      <SheetTitle>Welcome message</SheetTitle>
    </SheetHeader>
    <AutoForm
      className="flex min-h-0 flex-1 flex-col gap-0"
      fields={fields}
      formSchema={formSchema}
      layout={(rendered) => (
        <>
          <div className="flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-4 py-5">
            {rendered.enabled}
            {rendered.welcome}
          </div>
          <AutoFormSheetFooter submitLabel="Save message" />
        </>
      )}
      onSubmit={async (values) => {
        await save(values)
        setOpen(false)
      }}
    />
  </SheetContent>
</Sheet>

Control open so a successful save can close the sheet. Pass disabled to the footer when the viewer may only read the settings.

Sheet, dialog or page?

Choose the surface by how much there is to edit:

SettingsUseExample in VitNode
A handful of fields about one thingSheetAI settings, one AI action
Several sections or tabsDialogA role's settings
A full editor with its own previewA pageEditing an article

Sheet or Drawer?

A sheet is a dialog that slides. A Drawer also follows your finger and closes with a swipe, which feels better on phones.

Props

Prop

Type

Both props live on SheetContent. Sheet takes open and onOpenChange like a Dialog.

API Reference

Base UI - Dialog