TaperSafe Design System
A code-truthful spec for a native iOS medication taper tracker. The palette is "Clinical Cyan" — a Material 3 inspired bright teal on cyan-washed white surfaces. Every token here maps to a real value in lib/constants.ts; when code and this doc disagree, code wins.
Calm before clever.
TaperSafe is opened in anxious moments. The design is built around one question: "how long until my next dose?" Three principles hold the whole thing together.
Bright teal primary. Washed-white surfaces. Distinct success green.
The palette is Material 3 inspired. One cyan-teal primary. One fresh green for success states. A six-stop surface scale that gets slightly darker as elements nest deeper. No grey — everything has a cyan tint.
Primary
Success & semantic
Surfaces — six-stop cyan-washed scale
Text
System font. Wide scale. One element dominates.
The system font (-apple-system on iOS, Roboto on Android) keeps text legible and familiar. The scale is intentionally wide so the 56pt countdown can dominate without competing with body copy.
The only place we use font-variant-numeric: tabular-nums — fixed-width digits prevent layout shift every second.
A 4px base scale.
Six steps, doubling loosely from a 4px hairline to 48px for large-screen rhythm.
Generous rounds. Everything interactive is a pill.
Sharp corners feel cold in a healthcare context. Five radius values; the full-pill (9999px) is non-negotiable for all interactive elements.
One soft shadow. Used sparingly.
One real shadow for cards. A deeper shadow for bottom sheets. No layered glows, no inner shadows — one shadow per card, maximum. All shadows use a near-black teal alpha channel, not grey.
All built from the same teal + washed-white recipe.
Core components in components/ui/. Rendered on the clinical teal stage:
Buttons
Countdown timer
Progress bar
Status chips
Signal, not decoration. Never startle.
This is a calm app. Motion must not alarm an already anxious user. With prefers-reduced-motion on, all animated demos collapse to a plain opacity fade.
Calm, plain, never urgent.
The copy speaks to someone who is managing a health condition. It is direct, reassuring, and never alarmist. It does not celebrate adherence in a way that would make missing a dose feel like failure.
"Next dose in 8 hours."
"Dose confirmed. Well done."
"Your plan: step 2 of 4."
"You missed a dose! Get back on track!"
"🔥 5-day streak — don't break it!"
"URGENT: Take your medication NOW"
Five ways to break the feel.
If a new screen does any of these, it is no longer TaperSafe.
- Don't shrink the countdown. The 56pt timer is always the largest element on the patient home screen. Nothing competes with it.
- Don't use square corners on interactive elements. Radius
full(9999px) on every button, chip, badge, and input is non-negotiable. - Don't use a saturated CTA colour for decoration. Orange, magenta, or any hue outside the system carries accidental clinical meaning. Teal for actions; green for success; red for overdue only.
- Don't add more than one shadow per card. No layered glows, no inner shadows. One soft drop shadow per elevated element, in near-black teal alpha.
- Don't alarm the user with motion on the overdue state. The colour switches instantly and silently. No shake, no flash, no haptic. The change must register — not startle.
Where every token actually lives.
This page documents the system; the code defines it. When they disagree, the code wins.