Files
temetro/.agents/skills/coss/references/primitives/dialog.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

4.0 KiB
Raw Blame History

coss Dialog

When to use

  • Modal overlays that require user focus and explicit action.
  • Multi-section popup flows with header/body/footer structure.

When NOT to use

  • If the overlay should slide from the edge -> use Sheet or Drawer instead.
  • If the interaction is a destructive confirmation -> use AlertDialog instead.
  • If the content is non-blocking contextual info -> use Popover instead.

Install

npx shadcn@latest add @coss/dialog

Manual deps from docs:

npm install @base-ui/react

Canonical imports

import {
  Dialog,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPanel,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"

Minimal pattern

<Dialog>
  <DialogTrigger render={<Button variant="outline" />}>Open Dialog</DialogTrigger>
  <DialogPopup>
    <DialogHeader>
      <DialogTitle>Dialog Title</DialogTitle>
      <DialogDescription>Dialog Description</DialogDescription>
    </DialogHeader>
    <DialogPanel>Content</DialogPanel>
    <DialogFooter>
      <DialogClose render={<Button variant="ghost" />}>Close</DialogClose>
    </DialogFooter>
  </DialogPopup>
</Dialog>

Patterns from coss particles

  • Portal forwarding: optional portalProps on DialogPopup → Base UI Dialog.Portal (keepMounted, container, …). See portal-props.md.
  • Section structure invariant: keep DialogHeader, DialogPanel, and DialogFooter as direct sections in DialogPopup to preserve built-in layout/styling behavior.
  • Form in dialog: keep DialogHeader outside the form; wrap DialogPanel + DialogFooter in <Form className="contents"> (or native <form className="contents">) so the popups flex column treats header, panel, and footer as direct layout sections.
  • Action buttons: use DialogClose with render={<Button ... />} for cancel/close actions and set explicit type on submit/action buttons.
  • Scrollable content: keep long content inside DialogPanel to preserve dialog scroll behavior.
  • Footer variants: use DialogFooter variant="bare" when border/background framing should be removed.
  • Controlled open state: for cross-component flows (for example menu item opens dialog), control with open + onOpenChange.
  • Detached trigger option (advanced): when the opener cannot live in the same subtree, use a detached/external trigger pattern via controlled state (open + onOpenChange) instead of forcing local DialogTrigger composition.
  • Close confirmation flow: when unsaved changes exist, combine controlled Dialog with AlertDialog confirmation before closing.
  • Nested dialogs: supported; use clear trigger hierarchy and consider disabling default close buttons with showCloseButton={false} when custom actions are preferred.
  • Responsive dialog/drawer variant: for form-heavy overlays, use Dialog on desktop and switch to Drawer on mobile (useMediaQuery("max-md")), keeping the same Form structure in both.

Common pitfalls

  • Omitting render={<Button ... />} composition on trigger/close actions.
  • Forgetting title/description structure in real dialogs.
  • Wrapping dialog sections with extra containers that break DialogHeader/DialogPanel/DialogFooter layout; prefer header outside, Form className="contents" around panel + footer only.
  • Putting large body content outside DialogPanel when scrolling is needed.
  • Missing explicit button type inside dialog forms/actions.
  • Using uncontrolled dialog patterns when the flow requires cross-component state coordination.
  • Using non-coss composition APIs without verifying docs.

Useful particle references

  • basic dialog scaffold: p-dialog-1
  • open dialog from another primitive flow: p-dialog-2 (menu -> dialog)
  • nested dialogs: p-dialog-3
  • close confirmation / unsaved changes flow: p-dialog-4
  • long scrollable content in panel: p-dialog-5
  • bare footer variant usage: p-dialog-6
  • responsive dialog/drawer variant: p-drawer-12