161 lines
4.6 KiB
TypeScript
161 lines
4.6 KiB
TypeScript
/* EXAMPLE ONLY: an extract from the Superbill Review prototype, kept as reference for porting. ECW/eClinicalWorks, Tebra, 'Example Client', SPB_* tables and patient/ticket wording are that project's examples. Don't copy them into a new project. */
|
|
/**
|
|
* The icon set.
|
|
*
|
|
* Drawn here rather than pulled from a package, and drawn rather than typed:
|
|
* `✓`, `✗` and `●` are punctuation borrowed as pictures — they carry a font's
|
|
* metrics, not a stroke weight, so they sit at different optical sizes from each
|
|
* other and cannot be aligned with anything. A screen reader also reads them
|
|
* aloud as the characters they are.
|
|
*
|
|
* One grid (24), one stroke (1.75), round caps and joins throughout, so any two
|
|
* of these placed side by side read as the same hand. `currentColor` everywhere,
|
|
* so an icon inherits whatever the surface already decided about contrast.
|
|
*/
|
|
|
|
function Icon({
|
|
children,
|
|
size = 18,
|
|
className,
|
|
}: {
|
|
children: React.ReactNode
|
|
size?: number
|
|
className?: string
|
|
}) {
|
|
return (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={1.75}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
// Decorative by default: every icon in this app sits beside its own
|
|
// label. An icon that ever stands alone gets a real name at the call
|
|
// site instead of a title buried in here.
|
|
aria-hidden="true"
|
|
className={className}
|
|
>
|
|
{children}
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
type P = { size?: number; className?: string }
|
|
|
|
/** Stacked sheets — a count of documents. */
|
|
export const IconStack = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="M12 3 3 7.5l9 4.5 9-4.5L12 3Z" />
|
|
<path d="M3 12.5 12 17l9-4.5" />
|
|
<path d="M3 17.5 12 22l9-4.5" />
|
|
</Icon>
|
|
)
|
|
|
|
/** A file leaving the app for the reviewer's own disk. */
|
|
export const IconDownload = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="M12 3v12" />
|
|
<path d="m7.5 10.5 4.5 4.5 4.5-4.5" />
|
|
<path d="M4.5 19.5h15" />
|
|
</Icon>
|
|
)
|
|
|
|
/** A settled thing. */
|
|
export const IconCheck = (p: P) => (
|
|
<Icon {...p}>
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="m8.5 12.5 2.5 2.5 4.5-5.5" />
|
|
</Icon>
|
|
)
|
|
|
|
/** Work still in flight. */
|
|
export const IconClock = (p: P) => (
|
|
<Icon {...p}>
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="M12 7.5V12l3 2" />
|
|
</Icon>
|
|
)
|
|
|
|
/** Something absent or wrong — never used for "red band", which is data. */
|
|
export const IconAlert = (p: P) => (
|
|
<Icon {...p}>
|
|
<circle cx="12" cy="12" r="9" />
|
|
<path d="M12 8v4.5" />
|
|
<path d="M12 16h.01" />
|
|
</Icon>
|
|
)
|
|
|
|
/** A single scanned page. */
|
|
export const IconPage = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8l-5-5Z" />
|
|
<path d="M14 3v5h5" />
|
|
</Icon>
|
|
)
|
|
|
|
/** People, not rows: this counts patients. */
|
|
export const IconPatients = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="M16 20v-1.5a3.5 3.5 0 0 0-3.5-3.5h-4A3.5 3.5 0 0 0 5 18.5V20" />
|
|
<circle cx="10.5" cy="8" r="3.5" />
|
|
<path d="M19 20v-1.5a3.5 3.5 0 0 0-2.5-3.35" />
|
|
<path d="M15 4.6a3.5 3.5 0 0 1 0 6.65" />
|
|
</Icon>
|
|
)
|
|
|
|
/** Money spent. A coin edge-on, not a currency glyph. */
|
|
export const IconSpend = (p: P) => (
|
|
<Icon {...p}>
|
|
<ellipse cx="12" cy="6.5" rx="8" ry="3.5" />
|
|
<path d="M4 6.5v11c0 1.93 3.58 3.5 8 3.5s8-1.57 8-3.5v-11" />
|
|
<path d="M4 12c0 1.93 3.58 3.5 8 3.5s8-1.57 8-3.5" />
|
|
</Icon>
|
|
)
|
|
|
|
/** Two curved arrows chasing each other — a stage in a repeating flow. */
|
|
export const IconLoop = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="M4.5 12a7.5 7.5 0 0 1 12.5-5.6l2 1.9" />
|
|
<path d="M17.5 5.5v3.3h-3.3" />
|
|
<path d="M19.5 12a7.5 7.5 0 0 1-12.5 5.6l-2-1.9" />
|
|
<path d="M6.5 18.5v-3.3h3.3" />
|
|
</Icon>
|
|
)
|
|
|
|
/** A wallet card with a portrait square — a person's own identifying record. */
|
|
export const IconIdCard = (p: P) => (
|
|
<Icon {...p}>
|
|
<rect x="3" y="5.5" width="18" height="13" rx="2" />
|
|
<circle cx="9" cy="11.5" r="2" />
|
|
<path d="M6.5 15.5c0-1.4 1.1-2.2 2.5-2.2s2.5.8 2.5 2.2" />
|
|
<path d="M14.5 10h4" />
|
|
<path d="M14.5 13h4" />
|
|
</Icon>
|
|
)
|
|
|
|
export const IconChevronRight = (p: P) => (
|
|
<Icon {...p}>
|
|
<path d="m9 6 6 6-6 6" />
|
|
</Icon>
|
|
)
|
|
|
|
/**
|
|
* The legend and chip marker. A drawn disc rather than `●`, so it lands on the
|
|
* text baseline the same way at every size and takes its colour from the same
|
|
* `currentColor` chain as everything else.
|
|
*/
|
|
export const IconDot = ({ size = 8, className }: P) => (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox="0 0 8 8"
|
|
aria-hidden="true"
|
|
className={className}
|
|
>
|
|
<circle cx="4" cy="4" r="4" fill="currentColor" />
|
|
</svg>
|
|
)
|