Components / Clinical
Medication schedule
A day of doses on a 24-hour timeline, with a checklist to mark each one taken or skipped and warnings for interactions you supply.
Your app state
Step through the days or mark doses taken or skipped. These callbacks can save to your own records.
Date: 2026-10-19
{}Illustrative example data, not a treatment plan or a complete list of interactions.
Installation
In a project set up as in Installation, run:
bunx shadcn@4.22.1 add https://organui.com/r/medication-schedule.json
Or by name: bunx shadcn@4.22.1 add @organui/medication-schedule.
The source installs into your configured UI directory, along with shadcn's alert, button and empty if you do not have them yet. It uses your existing theme tokens and installs no global styles, date library or drug database.
Usage
"use client"
import { useState } from "react"
import {
MedicationSchedule,
type DoseStatus,
} from "@/components/ui/medication-schedule"
const medications = [
{ id: "levothyroxine", name: "Levothyroxine", dose: "75 mcg", times: ["07:00"] },
{ id: "calcium", name: "Calcium carbonate", times: ["08:30", "19:00"] },
]
// From your own interaction source. None are bundled.
const interactions = [{
id: "levothyroxine-calcium",
medicationIds: ["levothyroxine", "calcium"],
severity: "moderate" as const,
summary: "Calcium can reduce levothyroxine absorption.",
separationHours: 4,
}]
export function Schedule() {
const [date, setDate] = useState("2026-10-19")
const [doseStatus, setDoseStatus] = useState<Record<string, DoseStatus>>({})
return <MedicationSchedule medications={medications}
interactions={interactions} date={date} onDateChange={setDate}
doseStatus={doseStatus} onDoseStatusChange={setDoseStatus} />
}Each medication has a unique id, a name and its local dosing times as "HH:MM". Optional days (0 for Sunday to 6 for Saturday), start and end dates limit when it is due. Dates are "YYYY-MM-DD" calendar days with no time zone, so the schedule renders the same on the server and the client. Invalid times, dates or repeated IDs throw an error.
The date is controlled. Pass onDateChange to show previous and next day buttons. Pass now from client state to mark the current time on the timeline; the component never reads the clock itself.
Dose tracking
Dose status is a map from dose keys, such as levothyroxine@2026-10-19T07:00, to "taken" or "skipped". Missing doses are still to take. With onDoseStatusChange, each dose in the list becomes a button that cycles from to take, to taken, to skipped and back; the callback receives the whole new map for you to store. Without it the status is shown as text.
The timeline is a visual summary and is hidden from assistive technology. The ordered dose list carries the same times, names, statuses and warnings, and each status button names its medication and time.
Interaction warnings
The component ships no drug database and makes no clinical judgement. It shows only the interactions you pass, each naming two or more medication IDs, a severity of minor, moderate or major, and a summary. A warning appears on days when every medication it names is due, most severe first, and major ones get a destructive border and title. Give separationHours to flag same-day doses of those medications that are closer than that, on the timeline and in the dose list.
Source your interactions from a reviewed clinical service, and keep the default disclaimer or replace it with your own through disclaimer. Doses across midnight are not compared.
Customize
Set label for the accessible name, locale for the date heading, className for the outer container and color on a medication for its swatch and markers. The helpers dosesOn, activeInteractions, doseConflicts and nextDoseStatus are exported for your own views, such as reminders or a weekly summary.
A display component, not a medical device. No reminders, notifications, as-needed dosing, titration or dose calculations. Built on shadcn's Base UI components; compatibility with Radix-based presets is not claimed.