Scheduler
schedulerManages events across month, week, day, and resource views with drag-based editing.
Usage
Controlled usage
events / view / date are all controlled, state is held by consumers; onEventsChange gives back the entire set of new events (according to Kanban controlled paradigm).
const [events, setEvents] = useState(INITIAL);
const [view, setView] = useState<SchedulerView>("week");
const [date, setDate] = useState(monday);
<Scheduler
events={events}
view={view}
date={date}
resources={resources}
onViewChange={setView}
onDateChange={setDate}
onEventsChange={setEvents}
/>Resource View
When view='resource', the horizontal axis is resources (doctor/clinic) and the vertical axis is time; resources needs to be passed.
<Scheduler
events={events}
view="resource"
date={date}
resources={resources}
onEventsChange={setEvents}
/>Monthly Overview
view='month' gives an overview of the whole month, click on a certain day onDateChange + onViewChange to drill down to the day view.
<Scheduler
events={events}
view="month"
date={date}
onDateChange={setDate}
onViewChange={setView}
/>Custom time range
dayStartHour / dayEndHour narrows the timeline, hourHeight adjusts the pixel height per hour.
<Scheduler
events={events}
view="day"
date={date}
dayStartHour={9}
dayEndHour={13}
hourHeight={72}
/>When to use
Use Scheduler for appointments, clinic rosters, or resource timelines where users create slots, move events, and resize duration. Use Gantt for a read-only project schedule or Calendar/DatePicker for date selection.
Import
import { Scheduler, dateOf, dayColumns, eventRect, hourLines, layoutColumns, minutesOfDay, minutesToISO, monthMatrix, resourceColumns, snap, startOfWeekISO, weekColumns, yToMinutes } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| events* | SchedulerEvent[] | — | Controlled {id, title, start, end, resourceId?, tone?, subtitle?} events using local ISO datetimes. |
| view* | "month" | "week" | "day" | "resource" | — | Controlled view. |
| date* | string | — | Controlled ISO focus date. |
| resources | SchedulerResource[] | — | Required in resource view: {id, title, subtitle?}. |
| dayStartHour | number | 8 | Timeline start hour. |
| dayEndHour | number | 20 | Timeline end hour. |
| slotMinutes | number | 30 | Drag and create snap interval in minutes. |
| hourHeight | number | 56 | Pixels per hour. |
| toolbar | boolean | true | Shows title, previous/today/next controls, and view selector. |
| className | string | — | Root class; establish a definite height for scrolling. |
SchedulerEvent.tone is "primary" | "success" | "warning" | "danger" | "neutral", defaulting to primary.
Events
| Event | Type | Description |
|---|---|---|
| onViewChange | (v: SchedulerView) => void | View selection. |
| onDateChange | (iso: string) => void | Focus-date change from navigation or month-day selection. |
| onEventsChange | (events: SchedulerEvent[]) => void | Returns the complete array after move or resize. |
| onSlotDragCreate | (slot: SchedulerSlot) => void | Reports a dragged blank time range. |
| onSlotClick | (slot: SchedulerSlot) => void | Reports a clicked blank slot. |
| onEventClick | (event: SchedulerEvent) => void | Reports an event click. |
Slots
| Slot | Type | Description |
|---|---|---|
| renderEvent | (event: SchedulerEvent) => ReactNode | Custom event content while Scheduler owns geometry and drag handles. |
Example
const [events, setEvents] = useState<SchedulerEvent[]>(INITIAL);
const [view, setView] = useState<SchedulerView>("week");
const [date, setDate] = useState("2026-06-15");
<div className="h-[520px] w-full">
<Scheduler
className="h-full"
events={events}
view={view}
date={date}
resources={resources}
onViewChange={setView}
onDateChange={setDate}
onEventsChange={setEvents}
onSlotDragCreate={(slot) =>
setEvents((prev) => [
...prev,
{ id: `n-${slot.start}`, title: "New appointment", start: slot.start, end: slot.end, resourceId: slot.resourceId ?? "d1", tone: "primary" },
])
}
/>
</div>Usage notes
- Events, view, and date are fully controlled. Write
onEventsChangeback to state or dragged changes snap back. - The host needs a definite height so the time grid can fill it and scroll internally.
- Tone accepts only five semantic values; use
renderEventfor arbitrary color. - Start and end are local ISO datetimes with time, unlike Gantt's inclusive date-only values.
- Toolbar actions, view names, weekdays, formatted titles, and the overflow label read
ConfigProvider'slocale.components.scheduler.zhCNandenUSinclude the dictionary; legacy custom locales that omit this optional field retain the Chinese fallback.
Related
Table · Book3D · ProTable · PricingTable · JsonViewer · EditableTable