Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .design-sync/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@
- Default `guidelinesGlob` swept 46 repo process docs into `guidelines/` —
the config pins a curated 5-file design set; keep it curated.

## Known claude.ai/design validator findings (accepted, do not "fix")

From the July 2026 design-side review (CLAUDE_CODE_FIXES.md): the design app's
validator flags on our compiled-Tailwind output that are heuristic noise, not
repo defects — re-flag to the design agent instead of restructuring CSS:

- "56 unregistered component-scoped custom properties" — all `--tw-*` Tailwind
runtime vars + `--footer-scrim-height` (component-local by design).
- "126 pseudo theme scopes" — Tailwind utility classes misread as themes.
- README token count vs stylesheet count — converter/validator counting
difference (`317 defined` includes non-`:root` definitions).
- `--text-hero` font-family misparse — mitigated 2026-07-14 by adding the
`--text-hero--line-height` companion; if the warning persists it is
design-app-side.

## Known render warns

- None — 10/10 render clean, no thin/blank/variantsIdentical flags.
Expand Down
12 changes: 12 additions & 0 deletions .design-sync/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@
"docs/redesign/09-ui-primitives-recipes.md",
"docs/redesign/permanent-colour-direction.md"
],
"dtsPropsFor": {
"InlineNotice": "tone: \"success\" | \"info\" | \"warning\" | \"danger\" | \"neutral\"; children?: React.ReactNode; onDismiss?: () => void; dismissLabel?: string; animated?: boolean; className?: string;",
"ToggleSwitch": "enabled: boolean; onToggle?: () => void; disabled?: boolean; className?: string; \"aria-label\"?: string;",
"SourceStatusBadge": "metadata?: { document_status?: \"current\" | \"review_due\" | \"outdated\" | \"unknown\" }; className?: string; showTitle?: boolean;",
"SourceProvenance": "metadata?: { clinical_validation_status?: \"unverified\" | \"locally_reviewed\" | \"approved\"; review_date?: string; jurisdiction?: string; extraction_quality?: \"good\" | \"partial\" | \"poor\" | \"unknown\" };",
"PanelHeading": "icon?: React.ComponentType<{ className?: string }>; title: string; description?: string;",
"LoadingPanel": "label: string; variant?: \"spinner\" | \"skeleton\"; lines?: number;",
"EmptyState": "icon?: React.ComponentType<{ className?: string }>; title: string; body: string;",
"Sheet": "open: boolean; onClose: () => void; title?: string; description?: string; children?: React.ReactNode; footer?: React.ReactNode; closeLabel?: string; headerActions?: React.ReactNode; placement?: \"default\" | \"left\"; mobilePlacement?: \"bottom\" | \"top\" | \"fullscreen\"; mobileSize?: \"content\" | \"viewport\"; portal?: boolean; contentClassName?: string; bodyClassName?: string;",
"SafeBoldText": "text: string;",
"AccessibleTable": "caption?: string | null; markdown?: string | null; rows?: string[][] | null; columns?: string[] | null; compact?: boolean; expandOnMobile?: boolean; previewRows?: number; hidePreviewCaption?: boolean; hidePreviewRowCount?: boolean; densePreview?: boolean; dialogTitle?: string | null; clinicalOnly?: boolean; rowActions?: Array<React.ReactNode | null>; actionsHeader?: string; lowConfidenceFallback?: React.ReactNode;"
},
"overrides": {
"Sheet": { "cardMode": "single", "primaryStory": "OpenDialog", "viewport": "480x640" },
"AccessibleTable": { "cardMode": "column" }
Expand Down
18 changes: 14 additions & 4 deletions .design-sync/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,27 @@ Join with the exported `cn(...)` helper.
## Example

```tsx
import { PanelHeading, quietPanel, primaryControl, cn } from "<pkg>";
import { FileText } from "lucide-react";
import { PanelHeading, quietPanel, primaryControl, cn, FileText } from "<pkg>";

<section className={cn(quietPanel, "p-4 space-y-3")}>
<PanelHeading icon={FileText} title="Document library" description="Indexed guidelines and protocols." />
<button className={primaryControl}>Upload document</button>
</section>;
```

## Icons

The bundle ships a curated lucide icon set — import icons from the package
itself, never from `lucide-react` (it is not available to designs): `Search`,
`SearchX`, `FileText`, `File`, `Inbox`, `Upload`, `Download`, `ShieldCheck`,
`ShieldAlert`, `TriangleAlert`, `AlertCircle`, `Ban`, `X`, `Check`,
`CheckCircle2`, `Info`, `Loader2`, `ChevronDown`, `ChevronRight`, `ArrowLeft`,
`ArrowRight`, `Plus`, `Trash2`, `Pencil`, `Filter`, `Settings`, `Database`,
`BookOpen`, `Stethoscope`, `HeartPulse`, `Pill`, `Calendar`, `Clock`,
`ExternalLink`, `Copy`, `Maximize2`. The `icon` prop on `PanelHeading` /
`EmptyState` is optional — omit it rather than inventing an icon.

## Where the truth lives

Read `styles.css` for the full token set (`:root` and `.dark` blocks) and each
component's `.d.ts` + `.prompt.md` for its API. Icons are `lucide-react`
components passed as the `icon` prop where accepted.
component's `.d.ts` + `.prompt.md` for its API.
42 changes: 42 additions & 0 deletions .design-sync/entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,45 @@ export * from "@/components/ui-primitives";
export { Sheet } from "@/components/ui/sheet";
export { SafeBoldText } from "@/components/SafeBoldText";
export { AccessibleTable } from "@/components/AccessibleTable";

// Curated lucide-react icon set: consumers of the synced bundle have no
// lucide-react install, so the icons PanelHeading/EmptyState-style `icon`
// props need must ship with the bundle itself.
export {
AlertCircle,
ArrowLeft,
ArrowRight,
Ban,
BookOpen,
Calendar,
Check,
CheckCircle2,
ChevronDown,
ChevronRight,
Clock,
Copy,
Database,
Download,
ExternalLink,
File,
FileText,
Filter,
HeartPulse,
Inbox,
Info,
Loader2,
Maximize2,
Pencil,
Pill,
Plus,
Search,
SearchX,
Settings,
ShieldAlert,
ShieldCheck,
Stethoscope,
Trash2,
TriangleAlert,
Upload,
X,
} from "lucide-react";
15 changes: 6 additions & 9 deletions .design-sync/previews/AccessibleTable.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { AccessibleTable } from "prompt-for-codex-medical-knowledge-base";

const doseRows = [
["Amoxicillin", "500 mg", "8-hourly", "Oral", "5 days"],
["Doxycycline", "100 mg", "12-hourly", "Oral", "7 days"],
["Benzylpenicillin", "1.2 g", "6-hourly", "IV", "Until stable"],
];
const doseColumns = ["Antibiotic", "Dose", "Frequency", "Route", "Duration"];

export const ClinicalDoseTable = () => (
<AccessibleTable
caption="Community-acquired pneumonia — empirical therapy (adult)"
rows={doseRows}
columns={doseColumns}
rows={[
["Amoxicillin", "500 mg", "8-hourly", "Oral", "5 days"],
["Doxycycline", "100 mg", "12-hourly", "Oral", "7 days"],
["Benzylpenicillin", "1.2 g", "6-hourly", "IV", "Until stable"],
]}
columns={["Antibiotic", "Dose", "Frequency", "Route", "Duration"]}
/>
);

Expand Down
4 changes: 4 additions & 0 deletions .design-sync/previews/EmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const NoDocuments = () => (
/>
);

export const NoIcon = () => (
<EmptyState title="Nothing pinned yet" body="Pin an answer or document to keep it one tap away." />
);

export const NoResults = () => (
<EmptyState
icon={SearchX}
Expand Down
2 changes: 2 additions & 0 deletions .design-sync/previews/PanelHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export const WithDescription = () => (
);

export const TitleOnly = () => <PanelHeading icon={ShieldCheck} title="Source governance" />;

export const NoIcon = () => <PanelHeading title="Recent searches" description="Last 7 days across the workspace." />;
5 changes: 5 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
by ~1033px — no breakpoint jumps. Generates the `text-hero` utility.
clamp() font sizes are not flagged by scripts/check-type-scale.mjs. */
--text-hero: clamp(1.45rem, 1.02rem + 1.75vw, 2.15rem);
/* Companion line-height marks --text-hero as a font-SIZE token (Tailwind v4
`--text-<name>--line-height` convention) so downstream tooling never
misreads the clamp() value as a font-family list. Call sites that set an
explicit leading-* utility still win over this default. */
--text-hero--line-height: 1.15;

/* Font families: bind Tailwind's font-sans / font-mono to the loaded Geist
faces (variables set on <html> by next/font). font-mono is used for
Expand Down
20 changes: 12 additions & 8 deletions src/components/ui-primitives.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,17 @@ export function PanelHeading({
title,
description,
}: {
icon: IconComponent;
icon?: IconComponent;
title: string;
description?: string;
}) {
return (
<div className="flex items-start gap-3">
<span className={iconTile}>
<Icon className="size-icon-md sm:size-icon-lg" />
</span>
{Icon && (
<span className={iconTile}>
<Icon className="size-icon-md sm:size-icon-lg" />
</span>
)}
<div className="min-w-0">
<h2 className="text-base font-semibold text-[color:var(--text-heading)]">{title}</h2>
{description && <p className={cn("mt-1 text-sm leading-6", textMuted)}>{description}</p>}
Expand Down Expand Up @@ -417,13 +419,15 @@ export function LoadingPanel({
);
}

export function EmptyState({ icon: Icon, title, body }: { icon: IconComponent; title: string; body: string }) {
export function EmptyState({ icon: Icon, title, body }: { icon?: IconComponent; title: string; body: string }) {
return (
<div className="rounded-lg border border-dashed border-[color:var(--border-strong)] bg-[color:var(--surface-inset)] p-4 text-sm shadow-[var(--shadow-inset)] sm:p-5">
<div className="flex items-start gap-3">
<span className="grid h-10 w-10 shrink-0 place-items-center rounded-lg bg-[color:var(--surface)] text-[color:var(--text-muted)]">
<Icon className="size-icon-md sm:size-icon-lg" />
</span>
{Icon && (
<span className="grid h-10 w-10 shrink-0 place-items-center rounded-lg bg-[color:var(--surface)] text-[color:var(--text-muted)]">
<Icon className="size-icon-md sm:size-icon-lg" />
</span>
)}
<div className="min-w-0">
<p className="font-semibold text-[color:var(--text)]">{title}</p>
<p className={cn("mt-1 leading-6", textMuted)}>{body}</p>
Expand Down