agentic-ui

Drawer

A panel that slides in from any edge of the screen with swipe-to-dismiss gestures. Supports left, right, top, and bottom orientations.

All sides

import { Drawer } from "@brijbyte/agentic-ui/drawer";
import { Button } from "@brijbyte/agentic-ui/button";
import { Drawer as BaseDrawer } from "@base-ui/react/drawer";
import type { DrawerSide } from "@brijbyte/agentic-ui/drawer";

import "@brijbyte/agentic-ui/drawer.css";
import "@brijbyte/agentic-ui/button.css";

const SIDES: DrawerSide[] = ["right", "left", "bottom", "top"];

export default function SidesDemo() {
  return (
    <div style={{ display: "flex", gap: "var(--space-2)", flexWrap: "wrap" }}>
      {SIDES.map((side) => (
        <Drawer
          key={side}
          side={side}
          trigger={
            <Button variant="outline" size="sm">
              {side}
            </Button>
          }
          title={`${side.charAt(0).toUpperCase() + side.slice(1)} drawer`}
          description="Slides in from the edge. Swipe to dismiss."
          footer={
            <Button variant="soft" size="sm" render={<BaseDrawer.Close />}>
              Done
            </Button>
          }
        >
          <p style={{ fontFamily: "var(--font-mono)", fontSize: "var(--font-size-sm)", color: "var(--color-secondary)", margin: 0 }}>
            Content goes here. This drawer slides in from the <strong>{side}</strong> edge and supports swipe-to-dismiss.
          </p>
        </Drawer>
      ))}
    </div>
  );
}

Bottom sheet

import { Drawer } from "@brijbyte/agentic-ui/drawer";
import { Drawer as BaseDrawer } from "@base-ui/react/drawer";
import { Button } from "@brijbyte/agentic-ui/button";
import { Separator } from "@brijbyte/agentic-ui/separator";

import "@brijbyte/agentic-ui/drawer.css";
import "@brijbyte/agentic-ui/button.css";
import "@brijbyte/agentic-ui/separator.css";

const ACTIONS = ["Rename", "Duplicate", "Move to folder", "Download"];

export default function BottomSheetDemo() {
  return (
    <Drawer
      side="bottom"
      trigger={
        <Button variant="outline" size="sm">
          File options
        </Button>
      }
      title="report-q4.pdf"
      dismissible={false}
      footer={
        <Button variant="solid" tone="destructive" size="sm" render={<BaseDrawer.Close />}>
          Delete file
        </Button>
      }
    >
      <div style={{ display: "flex", flexDirection: "column" }}>
        {ACTIONS.map((action, i) => (
          <div key={action}>
            {i > 0 && <Separator />}
            <button
              type="button"
              style={{
                display: "block",
                width: "100%",
                padding: "var(--space-3) 0",
                background: "none",
                border: "none",
                textAlign: "left",
                fontFamily: "var(--font-mono)",
                fontSize: "var(--font-size-sm)",
                color: "var(--color-primary)",
                cursor: "pointer",
              }}
            >
              {action}
            </button>
          </div>
        ))}
      </div>
    </Drawer>
  );
}

Composed: base-ui Root + styled parts

import { Drawer, Drawer as BaseDrawer } from "@base-ui/react/drawer";
import {
  DrawerBackdrop,
  DrawerViewport,
  DrawerPopup,
  DrawerContent,
  DrawerTitle,
  DrawerDescription,
  DrawerClose,
  DrawerFooter,
} from "@brijbyte/agentic-ui/drawer";
import { Button } from "@brijbyte/agentic-ui/button";

import "@brijbyte/agentic-ui/drawer.css";
import "@brijbyte/agentic-ui/button.css";

export default function ComposedDemo() {
  return (
    <Drawer.Root swipeDirection="right">
      <Drawer.Trigger
        render={
          <Button variant="ghost" size="sm">
            Open (composed)
          </Button>
        }
      />
      <Drawer.Portal>
        <DrawerBackdrop />
        <DrawerViewport side="right">
          <DrawerPopup side="right" style={{ position: "relative" }}>
            <DrawerContent>
              <DrawerTitle>Settings</DrawerTitle>
              <DrawerDescription>Composed with raw base-ui Root and styled parts.</DrawerDescription>
              <p
                style={{
                  fontFamily: "var(--font-mono)",
                  fontSize: "var(--font-size-sm)",
                  color: "var(--color-secondary)",
                  margin: 0,
                }}
              >
                You have full control over the base-ui Root behaviour while keeping all design-system styling via the styled parts.
              </p>
              <DrawerFooter>
                <Button variant="outline" size="sm" render={<BaseDrawer.Close />}>
                  Close
                </Button>
                <Button variant="solid" size="sm">
                  Save
                </Button>
              </DrawerFooter>
            </DrawerContent>
            <DrawerClose aria-label="Close drawer" />
          </DrawerPopup>
        </DrawerViewport>
      </Drawer.Portal>
    </Drawer.Root>
  );
}