nili/ui
All components

Drawer

Overview
13 exports5 variant axes30 props4 files
import { Drawer, DrawerFooter, DrawerHeader, DrawerSide } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

Basic

A panel that slides in from an edge. Controlled by open and onOpenChange, like Modal — it portals, traps focus, and returns focus to the trigger.

import { Drawer, Button, TextInput } from "@nili/ui"

export function Example() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open drawer</Button>

      <Drawer
        open={open}
        onOpenChange={setOpen}
        title="Filters"
        description="Narrow the list down."
        closeLabel="Close"
        footer={
          <>
            <Button appearance="stroke" onClick={() => setOpen(false)}>Reset</Button>
            <Button onClick={() => setOpen(false)}>Apply</Button>
          </>
        }
      >
        <TextInput
              label={t('filters.search')}
              placeholder={t('filters.searchPlaceholder')}
            />
      </Drawer>
    </>
  )
}

Sides

side is logical: end is right in English and left in Persian, so the drawer always opens from the edge the reader expects. top and bottom are physical, because there is no reading direction on that axis.

import { Drawer } from "@nili/ui"

export function Example() {
  return (
    <>
      <Drawer side="end" … />
      <Drawer side="start" … />
      <Drawer side="top" … />
      <Drawer side="bottom" … />
    </>
  )
}

Sizes and header density

Four panel sizes, and a separate headerSize for Figma's Small / Large header.

panel size
import { Drawer } from "@nili/ui"

export function Example() {
  return (
    <>
      <Drawer size="sm" headerSize="sm" … />
      <Drawer size="lg" headerSize="lg" … />
      <Drawer size="full" … />
    </>
  )
}

Stretched footer

stretchFooter makes the actions fill the width — Figma's footer Stretch. Right on a narrow drawer, where two hugging buttons leave an awkward gap.

import { Drawer, Button } from "@nili/ui"

export function Example() {
  return (
    <Drawer
      open={open}
      onOpenChange={setOpen}
      title="Settings"
      stretchFooter
      footer={
        <>
          <Button appearance="stroke" onClick={close}>Cancel</Button>
          <Button onClick={close}>Save</Button>
        </>
      }
    />
  )
}

Controlling dismissal

closeOnOutsideClick and closeOnEscape are on by default. showClose keeps the ✕ — leave it when you turn the other two off, or the drawer has no exit.

import { Drawer } from "@nili/ui"

export function Example() {
  return (
    <Drawer
      open={open}
      onOpenChange={setOpen}
      closeOnOutsideClick={false}
      closeOnEscape={false}
      showClose
      closeLabel="Close"
      title="Editing"
      …
    />
  )
}