Sheet

Displays content on one side of the screen in a modal dialog.

Edit profile

Make changes to your profile here. Click save when you're done.

<Sheet>
  <SheetTrigger>
    <Button variant="outline">Open</Button>
  </SheetTrigger>
  <SheetContent>
    <SheetHeader>
      <SheetTitle>Edit profile</SheetTitle>
      <SheetDescription>
        Make changes to your profile here. Click save when you're done.
      </SheetDescription>
    </SheetHeader>
    <div class="grid gap-4 py-4">
      <div class="grid grid-cols-4 items-center gap-4">
        <Label htmlFor="name" className="text-right">
          Name
        </Label>
        <Input id="name" value="Pedro Duarte" className="col-span-3" />
      </div>
      <div class="grid grid-cols-4 items-center gap-4">
        <Label htmlFor="username" className="text-right">
          Username
        </Label>
        <Input id="username" value="@peduarte" className="col-span-3" />
      </div>
    </div>
    <SheetFooter>
      <SheetClose asChild>
        <Button type="submit">Save changes</Button>
      </SheetClose>
    </SheetFooter>
  </SheetContent>
</Sheet>

Installation

uvx --from basic-components components add sheet
pipx run --spec basic-components components add sheet
pip install basic-components && components add sheet
  • Copy Sheet components below to your local environment
  • Place them in the components/ui/sheet directory in your project
  • Configure your jinja environment for JinjaX
  • Add the cn() helper function to your global jinja environment

Usage

<Alert>
    <TerminalIcon className="h-4 w-4" />
    <AlertTitle>Heads up!</AlertTitle>
    <AlertDescription>
        You can add components to your app using the cli.
    </AlertDescription>
</Alert>

Attributes

Component Prop Type Default Description
SheetContent side String "right" Position of the sheet (top/bottom/left/right).

Code

{#def
    className: str = "",
#}
<div x-data="{ open: false }"
     x-init="$watch('open', value => document.body.classList.toggle('overflow-hidden', value))"
     class="{{ className }}"
     {{ attrs.render() }}
>{{ content }}</div>
{#def
    className: str = "",
#}
<button
    type="button"
    @click="open = false"
    class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-zinc-950 focus:ring-offset-2 dark:ring-offset-zinc-950 dark:focus:ring-zinc-300"
>
  <XIcon className="h-4 w-4"/>
  <span class="sr-only">Close</span>
  {{ content }}
</button>
{#def
    side: str = "right",
    className: str = "",
#}

{% set layout = {
  'top':    'inset-x-0 top-0 border-b slide-in-from-top overflow-x-auto',
  'bottom': 'inset-x-0 bottom-0 border-t slide-in-from-bottom overflow-x-auto',
  'left':   'inset-y-0 left-0 h-full w-3/4 border-r slide-in-from-left sm:max-w-sm overflow-y-auto',
  'right': 'inset-y-0 right-0 h-full w-3/4 border-l slide-in-from-right sm:max-w-sm overflow-y-auto',
}[side] %}


<SheetOverlay/>
<div
    x-show="open"
    @keydown.escape.window="open = false"
    @click.away="open = false"
    x-transition:enter="transition ease-in-out duration-300"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    x-transition:leave="transition ease-in-out duration-300"
    x-transition:leave-start="opacity-100"
    x-transition:leave-end="opacity-0"
    class="{{ layout }} {{ className }} fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out dark:bg-zinc-950"
  {{ attrs.render() }}
>
  {{ content }}
  <SheetClose/>
</div>
{#def
    className: str = "",
#}
<p class="{{ className }} text-sm text-zinc-500 dark:text-zinc-400">{{ content }}</p>
{#def
    className: str = "",
#}
<div class="{{ className }} flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2">
  {{ content }}
</div>
{#def
    className: str = "",
#}
<div class="{{ className }} flex flex-col space-y-2 text-center sm:text-left">{{ content }}</div>
{#def
    className: str = "",
#}
<div
    class="{{ className }} fixed inset-0 z-50 bg-black/80 transition-opacity ease-in-out overflow-hidden"
    x-show="open"
    x-transition:enter="transition-opacity duration-300"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    x-transition:leave="transition-opacity duration-300"
    x-transition:leave-start="opacity-100"
    x-transition:leave-end="opacity-0"
></div>
{#def
    className: str = "",
#}
<h2 class="{{ className }} text-lg font-semibold text-zinc-950 dark:text-zinc-50">{{ content }}</h2>
{#def
    className: str = "",
#}
<div @click="open = true" class="inline-block {{ className }}">{{ content }}</div>

Examples

Sides

Edit profile

Make changes to your profile here. Click save when you're done.

Edit profile

Make changes to your profile here. Click save when you're done.

Edit profile

Make changes to your profile here. Click save when you're done.

<div class="grid grid-cols-2 gap-2 place-items-center">
  {% for side in ["top", "right", "bottom", "left" ] %}
    <Sheet :id="{{ side }}">
      <SheetTrigger>
        <Button variant="outline">{{ side }}</Button>
      </SheetTrigger>
      <SheetContent :side="{{ side }}">
        <SheetHeader>
          <SheetTitle>Edit profile</SheetTitle>
          <SheetDescription>
            Make changes to your profile here. Click save when you're done.
          </SheetDescription>
        </SheetHeader>
        <div class="grid gap-4 py-4">
          <div class="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="name" className="text-right">
              Name
            </Label>
            <Input id="name" value="Pedro Duarte" className="col-span-3"/>
          </div>
          <div class="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="username" className="text-right">
              Username
            </Label>
            <Input id="username" value="@peduarte" className="col-span-3"/>
          </div>
        </div>
        <SheetFooter>
          <SheetClose>
            <Button type="submit">Save changes</Button>
          </SheetClose>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  {% endfor %}
</div>