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

coss Select

When to use

  • Single-choice selection from a predefined list.
  • Select-style triggers with popup options.

When NOT to use

  • If the user needs to type/filter options -> use Combobox instead.
  • If the list is very short (2-3 items) with visible options -> consider RadioGroup.
  • If the selection drives complex search/autocomplete -> use Autocomplete instead.

Install

npx shadcn@latest add @coss/select

Manual deps:

npm install @base-ui/react

Canonical imports

import {
  Select,
  SelectGroup,
  SelectGroupLabel,
  SelectItem,
  SelectLabel,
  SelectPopup,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

Minimal pattern

const items = [
  { label: "Next.js", value: "next" },
  { label: "Vite", value: "vite" },
]

<Select items={items}>
  <SelectTrigger>
    <SelectValue placeholder="Select framework" />
  </SelectTrigger>
  <SelectPopup>
    <SelectLabel>Frameworks</SelectLabel>
    {items.map((item) => (
      <SelectItem key={item.value} value={item}>
        {item.label}
      </SelectItem>
    ))}
  </SelectPopup>
</Select>

Prefer this items-first pattern for migration work to keep options known before hydration and avoid SSR mismatch edge cases.

For form-bound selects, prefer wrapping with Field + FieldLabel + FieldError so value, label, and validation stay semantically linked.

Patterns from coss particles

  • Field composition: in forms, place Select inside Field wrappers (see p-select-23, p-form-1, p-form-2).
  • Trigger composition: keep SelectTrigger as the interaction entry point and avoid Radix asChild assumptions from other primitives; where composition is needed, prefer documented coss/Base UI render patterns for supported parts.
  • Multiple selection: use multiple with array values (for example defaultValue={["javascript", "typescript"]}) and a custom SelectValue render function for compact summaries.
  • Object values: use full objects in SelectItem value={item} with itemToStringValue for stable form value serialization.
  • Grouped options: use SelectGroup + SelectGroupLabel; combine with SelectSeparator between groups when needed.
  • Disabled options: pass disabled on individual SelectItem rows (for unavailable choices).
  • Rich row/trigger rendering: render custom content (icons, avatars, secondary text) in both SelectValue and SelectItem; adjust row density via className where needed.
  • Alignment tuning: use alignItemWithTrigger={false} only when the default selected-item alignment causes layout issues.

Portal forwarding

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

Common pitfalls

  • Keeping children-only Radix select patterns without adding items.
  • Forgetting to render SelectValue inside SelectTrigger.
  • Placing placeholder on the wrong part; use placeholder on SelectValue when needed.
  • Using object item values without itemToStringValue when stable string value serialization is required.
  • Treating multiple select values as scalars instead of arrays.
  • Mixing select and combobox APIs without validating docs.

Useful particle references

  • basic select + sizing: p-select-1, p-select-2, p-select-3
  • grouped/labeled/select field patterns: p-select-6, p-select-11, p-select-23
  • multiple selection summary rendering: p-select-7
  • object values + rich option content: p-select-10, p-select-17, p-select-20
  • disabled options: p-select-12
  • related pattern: p-combobox-18 (SelectButton with combobox trigger)