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

2.5 KiB

coss Button

When to use

  • Primary and secondary action triggers.
  • Icon, loading, and shortcut-enhanced actions across forms and toolbars.

Install

npx shadcn@latest add @coss/button

Manual deps from docs:

npm install @base-ui/react

Canonical imports

import { Button } from "@/components/ui/button"

Minimal pattern

<Button type="button">Button</Button>

Button defaults to type="button" when rendered as the native button part. In form flows, set type explicitly (button / submit / reset) to match intent, especially when using render composition.

Patterns from coss particles

Key patterns

Variants are set via the variant prop:

<Button>Default</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

Icon-only button (always needs aria-label):

<Button aria-label="Close" size="icon" variant="ghost">
  <XIcon aria-hidden="true" />
</Button>

Button with icon and text (no opacity on the icon):

<Button>
  <PlusIcon aria-hidden="true" />
  Add Item
</Button>

Sizes: xs, sm, default, lg, icon-xs, icon-sm, icon, icon-lg.

Loading state

Built-in loading prop (disables and shows spinner automatically):

<Button loading={isLoading} onClick={handleClick}>Submit</Button>

Composite approach (manual Spinner + disabled):

<Button disabled>
  <Spinner />
  Loading...
</Button>

Prefer the loading prop for typical async actions. Use the composite approach when you need custom spinner placement or label.

More examples

  • default: p-button-1
  • outline: p-button-2
  • secondary: p-button-3
  • destructive: p-button-4
  • destructive outline: p-button-5
  • ghost: p-button-6
  • link: p-button-7
  • extra-small size: p-button-8

Common pitfalls

  • Omitting explicit type inside forms/dialogs and triggering unintended submit behavior.
  • Using icon-only buttons without aria-label on the button.
  • Rebuilding button state styling with ad-hoc classes instead of variants/sizes.
  • Using SelectButton as if it were a general-purpose Button; SelectButton is a select-flavored trigger helper and should be treated as a select/combobox pattern.

Useful particle references

  • variants/sizes: p-button-1 through p-button-8
  • composite loading (Spinner + disabled): p-button-18
  • built-in loading prop: p-button-41