Files
temetro/.agents/skills/coss/references/primitives/drawer.md
T
Khalid Abdi 929bec8f31 feat: AI-added records save with placeholders + "Added by AI" provenance
Stop blocking AI imports/proposals on missing non-critical fields. Records
the chat agent drafts now save with safe placeholders, auto-generated file
numbers, and a source="ai" marker that surfaces an "Added by AI" badge so a
clinician can review/edit them later.

Backend:
- add `source` (manual|ai) column to patients/appointments/prescriptions
  (migration 0014) + canonical types, services, validation schemas
- relax patient/appointment validation: empty file number allowed, demographic
  + type/provider/initials fall back to placeholders (initials derived from name)
- patients.generateFileNumber() auto-assigns an MRN when one is missing
- proposeAppointment accepts a name when no file number resolves; AI commits +
  /api/ai/import stamp source="ai"

Frontend:
- `source` on Appointment/Patient/Prescription types; AI commits send source="ai"
- reusable <AiBadge> shown on the Patients table/detail and prescriptions list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 19:27:17 +03:00

3.0 KiB

coss Drawer

When to use

  • Mobile-first overlay panels and bottom sheets.
  • Form-heavy or multi-step overlays where popover is too constrained.

When NOT to use

  • If the overlay should be a centered modal -> use Dialog instead.
  • If the overlay should be a persistent side panel on desktop -> use Sheet instead.
  • If you need a simple confirmation -> use AlertDialog instead.

Install

npx shadcn@latest add @coss/drawer

Manual deps from docs:

npm install @base-ui/react

Canonical imports

import {
  Drawer,
  DrawerCreateHandle,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerMenu,
  DrawerMenuCheckboxItem,
  DrawerMenuGroup,
  DrawerMenuGroupLabel,
  DrawerMenuItem,
  DrawerMenuRadioGroup,
  DrawerMenuRadioItem,
  DrawerMenuSeparator,
  DrawerPanel,
  DrawerPopup,
  DrawerMenuTrigger,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"

Minimal pattern

<Drawer>
  <DrawerTrigger>Open</DrawerTrigger>
  <DrawerPopup>
    <DrawerHeader>
      <DrawerTitle>Drawer Title</DrawerTitle>
      <DrawerDescription>Drawer Description</DrawerDescription>
    </DrawerHeader>
    <DrawerPanel>Content</DrawerPanel>
    <DrawerFooter>
      <DrawerClose>Close</DrawerClose>
    </DrawerFooter>
  </DrawerPopup>
</Drawer>

Patterns from coss particles

  • Portal forwarding: optional portalProps on DrawerPopup → Base UI Drawer.Portal (keepMounted, container, …). See portal-props.md.

Key patterns

Drawer with handle:

<Drawer>
  <DrawerTrigger render={<Button variant="outline" />}>Open Drawer</DrawerTrigger>
  <DrawerPopup>
    <DrawerCreateHandle />
    <DrawerHeader>
      <DrawerTitle>Edit Profile</DrawerTitle>
      <DrawerDescription>Make changes to your profile here.</DrawerDescription>
    </DrawerHeader>
    <DrawerPanel>
      {/* Form content */}
    </DrawerPanel>
    <DrawerFooter>
      <Button>Save</Button>
      <DrawerClose render={<Button variant="ghost" />}>Cancel</DrawerClose>
    </DrawerFooter>
  </DrawerPopup>
</Drawer>

Responsive drawer + dialog (drawer on mobile, dialog on desktop): see p-drawer-12.

More examples

See p-drawer-1 through p-drawer-13 for inset, straight, scrollable, nested, snap points, mobile menu, and responsive patterns.

Common pitfalls

  • Using drawer for desktop modal flows where dialog/sheet is clearer.
  • Forgetting responsive switch logic when drawer is mobile-only variant.
  • Breaking section layout by putting the whole dialog in a block-level <form>; prefer header outside, Form className="contents" around panel + footer (see dialog/form skills).

Useful particle references

  • inset variant: p-drawer-4
  • straight variant: p-drawer-5
  • scrollable content: p-drawer-6
  • nested drawers: p-drawer-7
  • snap points: p-drawer-9
  • mobile menu: p-drawer-11
  • responsive dialog: p-drawer-12
  • responsive menu: p-drawer-13
  • cross-overlay references: p-dialog-1, p-popover-1, p-menu-2