Lists supplied medication, dose, time, and recorded status with controlled 44px recording actions.
Preview
6 SeptemberEurope/Amsterdam
08:00
Morning medication
Dose as prescribed
Not recorded
In action
Today's record
Fictional entries. Choices update this example only; they are not saved to a patient record.
14 September 2026Europe/Amsterdam, UTC+02:00
08:00
Example medication A
Dose supplied by the care team
Instructions supplied by the care team
Not recorded
20:00
Example medication B
Dose supplied by the care team
Awaiting review
When to use
Use it for
Displaying an existing medication schedule and requesting explicit record updates.
Supply timezone, dosing text, instructions, action labels, and recorded statuses from the application.
Not for
Calculating doses, suggesting medication, guessing overdue entries, or declaring a record saved from a click alone.
Treating an empty list as evidence that a patient takes no medication.
Install
Three ways in. They share one source, so the pixels match whichever you pick.
1. Import the package
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { MedicationSchedule } from "@noorddev/vlak-react";
Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/medication-schedule.
2. Vendor the source
npx @noorddev/vlak-cli add medication-schedule
The StyleX leaf lands in components/vlak/ with its dependencies, for your own compiler to own. See StyleX.
No React. Link vlak.css and use the markup and classes below.
React
import { MedicationSchedule } from "@noorddev/vlak-react";
<MedicationSchedule dateLabel="14 September" timeZone="Europe/Amsterdam, UTC+02:00" items={[{ id: "morning", name: "Example medication", dose: "Dose supplied by the care team", timeLabel: "08:00", status: "Not recorded", instructions: "Instructions supplied by the care team" }]} />
// For editing, pass explicit item.actions and onAction(itemId, actionId).
// The caller persists the choice, sets item.pending, and supplies the new status.
Props
MedicationSchedule
A controlled record of supplied medication rows, not a dosing or reminder engine.
Prop
Type
Default
Description
itemsrequired
readonly MedicationScheduleItem[]
timeZonerequired
ReactNode
Display label supplied by the application, including any relevant UTC offset.
dateLabel
ReactNode
emptyLabel
ReactNode
"No medication entries supplied"
onAction
(itemId: string, actionId: string) => void
Requests a record change. The caller persists it and supplies updated items.
Also accepts Omit<HTMLAttributes<HTMLDivElement>, "onAction">.
Keyboard
Keys
Does
Tab
Moves between enabled recording buttons when onAction and item actions are supplied.
Enter, Space
Requests the selected recording action. Pending or disabled rows cannot request changes.
Accessibility
Rows remain in supplied order in an ordered list. Optional dateTime values are passed through unchanged.
Action names include the visible action label and medication name. Each action is described by its scheduled time, dose, and recorded status to distinguish repeated doses. Buttons have at least 44px targets.
Pending state remains visible alongside the existing status, uses aria-busy and a polite status region, and disables recording actions.
No internal persistence or automatic success state. Without onAction the schedule is read-only.
Markup
<div class="rs-medication-schedule" role="group" aria-label="Medication schedule"><div class="rs-medication-schedule-header"><span>14 September</span><span class="rs-medication-schedule-zone">Europe/Amsterdam, UTC+02:00</span></div><ol class="rs-medication-schedule-list"><li class="rs-medication-schedule-row"><span class="rs-medication-schedule-time">08:00</span><div class="rs-medication-schedule-body"><p class="rs-medication-schedule-name">Example medication</p><p class="rs-medication-schedule-detail">Dose supplied by the care team</p><p class="rs-medication-schedule-status">Not recorded</p></div></li></ol></div>