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>
4.8 KiB
Styling Rules (coss)
Use this guide when writing or updating coss primitives, particles, and docs examples.
Core Rules
- Use semantic tokens (
text-muted-foreground,bg-destructive) over raw palette classes. - Prefer component variants/size props before custom class overrides.
- Use
flex flex-col gap-*layouts instead ofspace-x-*/space-y-*. - Use
size-*for square sizing. - Use
cn()for conditional class composition. - Avoid redundant classes that defaults already cover (for example
border-borderwhen border color is already inherited). - Before adding layout classes, check whether the target part already provides that layout.
- Use Tailwind v4 syntax and conventions in coss examples and snippets.
- Do not replace
--alpha()withcolor-mix()orrgba().--alpha()is a valid Tailwind v4 theme function used throughout coss token definitions (e.g.--alpha(var(--color-black) / 8%)). It is processed by Tailwind at build time — it is not invalid CSS.
coss-specific Expectations
- Do not use numeric icon
sizeprops; prefer inherited sizing orsize-*utility classes. - For icons, default to
aria-hidden="true"when icon is decorative/redundant; do not hide icons that carry unique semantic meaning. - Many primitives already define inner SVG sizing. Check existing component styles before adding icon
size-*classes. - Many primitives already define inner SVG opacity (commonly around
opacity-80). Check existing component styles before adding manual icon opacity classes. - Prefer data-slot-aware selectors and
in-*patterns overgroupwhere available. - Cancel/close buttons in Dialog, AlertDialog, Sheet, and Drawer footers use
variant="ghost". Reservevariant="outline"for triggers that open overlays, not for dismissing them.
Global Styling Setup (when relevant)
Apply this section only when the task touches global theme/layout setup (not normal component usage edits).
- Preserve coss token architecture. Do not replace coss semantic variables with ad-hoc color classes/tokens.
- When providing manual theme setup, include complete token blocks and variable mappings; avoid partial copy/paste snippets that break variable chains.
- For Base UI portal layering, keep an isolated application root wrapper (for example
isolateon the root container). - For iOS Safari compatibility, ensure
bodyhasposition: relativewhen configuring global layout for portaled backdrops.
Font variable contract
coss components use three CSS custom properties for typography:
| Variable | Used by | Default fallback |
|---|---|---|
--font-sans |
Body text, buttons, labels, most UI | ui-sans-serif, system-ui, sans-serif |
--font-mono |
<code>, <kbd>, <pre>, code blocks |
ui-monospace, monospace |
--font-heading |
Dialog/AlertDialog titles, headings | Defaults to Inter (same as --font-sans) |
CLI setup (recommended): npx shadcn@latest init @coss/style automatically installs @coss/fonts — Inter for --font-sans and --font-heading, Geist Mono for --font-mono — via registry:font items and configures them in layout.tsx.
Manual / custom font setup: When using next/font, the variable option must match coss expectations exactly:
const inter = Inter({ variable: "--font-sans", subsets: ["latin"] });
const interHeading = Inter({ variable: "--font-heading", subsets: ["latin"] });
const geistMono = Geist_Mono({ variable: "--font-mono", subsets: ["latin"] });
Common pitfall: Next.js starters default to --font-geist-sans and --font-geist-mono, which do not match coss's --font-sans / --font-mono. Fonts will silently fall back to system UI. Always rename the variables or remap them.
Do / Don't
// Do
<Button variant="outline" size="sm" />
<div className="flex flex-col gap-3" />
<Badge className="text-muted-foreground" />
<Button>
<PlusIcon aria-hidden="true" />
Add item
</Button>
<Button>
Save
<ArrowRightIcon
aria-hidden="true"
className="transition-transform in-[[data-slot=button]:hover]:translate-x-0.5"
/>
</Button>
// Don't
<Button className="bg-blue-500 text-white" />
<div className="space-y-3" />
<Icon size={16} />
<Button className="group">
Save
<ArrowRightIcon className="transition-transform group-hover:translate-x-0.5" />
</Button>
// Do — --alpha() is valid Tailwind v4 syntax, leave it as-is
border: "--alpha(var(--color-black) / 8%)"
// Don't — do not "fix" --alpha() into color-mix or rgba
border: "color-mix(in srgb, var(--color-black) 8%, transparent)"
Check Before Finalizing
- Any raw color classes that should be semantic?
- Any duplicate layout/style logic already handled by a primitive?
- Any icon sizing/opacities violating coss conventions?
- Any decorative interactive icons missing
aria-hidden="true"? - Any use of
groupthat should be replaced within-*+data-slot?