Time Grid
The week and day views draw the same grid: an hour gutter, one column per day and a scale that maps the clock to pixels. Nine props shape it.
Configure the Grid
Change a control and the grid follows. The props below are the ones the grid reads; everything else about the week view comes from the events.
Oct 19 – 25, 2026
<Scheduler
bind:events
view="week"
slotMinutes={30} <!-- minutes per grid line: the snap, the key step, the shortest event -->
slotHeight={24} <!-- pixels per slot; 24 x 48 slots is a 1152px day -->
dayStartHour={0} <!-- first hour drawn -->
dayEndHour={24} <!-- hour the grid ends at -->
weekStartsOn={1} <!-- 0 is Sunday -->
hiddenDays={[]} <!-- [0, 6] for a working week -->
weekNumbers={false} <!-- ISO 8601 week numbers -->
/>Slots
slotMinutes is the unit of the grid, and it reaches further than the lines. A drag snaps to it, the up and
down keys move by it, an event created or resized by hand is never shorter than it, and a drop
that has no length of its own takes two of them. slotHeight is pixels per slot. Fifteen minute slots at the default height make a day twice as tall as thirty
minute ones; shrink the height to keep the day the same size.
// slotMinutes is the unit of the grid. It sets:
// the lines drawn between hours (60 / slotMinutes per hour)
// where a drag snaps (nearest slot boundary)
// the step of the up and down keys (one slot)
// the shortest event a drag or resize makes (one slot)
// the length of a drop from a dragSource with no durationMinutes,
// and of an all-day event dropped onto the grid (two slots)
// slotHeight is pixels per slot. Together they fix the scale of the day:
// dayHeight = (dayEndHour - dayStartHour) * 60 / slotMinutes * slotHeightVisible Hours
dayStartHour and dayEndHour trim the day to the hours that matter. An event crossing an edge is cut there; an event that lies
entirely outside is not drawn at all, though it stays in the array and still counts elsewhere.
Both must be whole hours inside one day with start before end, or the grid warns and shows all
twenty four.
<!-- Draw 7:00 to 20:00. Events that start earlier are cut at the top; events
entirely outside stay in the array and are simply not drawn. -->
<Scheduler bind:events dayStartHour={7} dayEndHour={20} />
<!-- Whole hours inside one day, start before end. Anything else prints a warning
and falls back to 0 and 24:
[@sv5ui/scheduler] Visible hours 8 to 8 are not a range inside one day; showing the whole day. -->Hidden Days
hiddenDays drops week days from the week and month views, typically the weekend. The day view, the year and
the agenda keep every day, and the toolbar title names the days actually shown. An event on a
hidden day is not lost: it is still in the array and comes back in the other views.
<!-- Leave the weekend out of the week and month views. The day view, the year and
the agenda keep every day. The toolbar title follows what is shown: Sep 14 – 18. -->
<Scheduler bind:events hiddenDays={[0, 6]} />
<!-- Hiding all seven days shows all of them again, with a warning -->Overlapping Events
Events that overlap within a day share its width. A cluster of overlapping events is split into as many columns as it needs, and each event takes one: the earlier start goes left, and of two starting together the longer one goes left. Two identical events become two halves. A background event is never part of a cluster; it is drawn full width behind the others.
October 20, 2026
October 20, 2026
Today GMT+7// Events that overlap in one day share the column. A cluster of overlapping
// events is split into as many columns as it needs; each event takes one.
// Earlier start goes left; on the same start, the longer event goes left.
const events = [
{ id: 'a', title: 'Design review', start: '2026-09-15T13:00', end: '2026-09-15T14:30' },
{ id: 'b', title: 'Pairing', start: '2026-09-15T14:00', end: '2026-09-15T15:30' }, // overlaps a
{ id: 'c', title: 'Vendor call', start: '2026-09-15T14:00', end: '2026-09-15T14:30' }, // overlaps a and b
{ id: 'd', title: 'Standup', start: '2026-09-15T09:00', end: '2026-09-15T09:15' }, // alone: full width
{ id: 'e', title: 'Retro', start: '2026-09-15T16:00', end: '2026-09-15T17:00' },
{ id: 'f', title: 'Retro (dup)', start: '2026-09-15T16:00', end: '2026-09-15T17:00' } // identical: two halves
];
// Background events never take a column: they are drawn full width behind the rest.The All-Day Row
Under the headers, a row for events that own a whole day: those marked allDay and any timed event of twenty four hours or more. The row appears only while the visible range
has at least one of them. That has one consequence for drag and drop: with no all-day event in
the week there is no row to drop a timed event onto, so it cannot be turned all-day there. The
month view always can.
With an all-day event in the week
Oct 19 – 25, 2026
Without one: no row
Oct 19 – 25, 2026
// Goes to the all-day row: an allDay event, or any event that lasts 24 hours or more
{ id: 'offsite', title: 'Team offsite', start: '2026-09-17', end: '2026-09-19', allDay: true }
{ id: 'oncall', title: 'On call', start: '2026-09-14T09:00', end: '2026-09-15T09:00' }
// The row exists only while the range holds at least one such event. With none,
// there is nowhere to drop a timed event to make it all-day; use the month view.Current Time
A red line with a dot marks the current time in today's column, with the time itself in the gutter beside it. It moves once a minute and disappears outside the visible hours. Today's column is tinted too, in every view.
Where the Grid Scrolls To
Each time the range changes, the grid scrolls to what is most likely wanted, leaving half an
hour of room above it. The day view aims at the first event of the day, the week view at the
current time; both fall back to the other, then to the opening hour of businessHours, then to 7:00.
// Where the grid scrolls to each time the range changes, half an hour above the target:
// day view: the first event that starts today, else the current time, else the opening hour
// week view: the current time (when today is in the range), else the first event, else the opening hour
// The opening hour is businessHours.start, or 7:00 without business hours.Week Numbers and the Zone Label
weekNumbers adds ISO 8601 week numbers: in the corner above the gutter here, beside the day title in the day
view, at the start of each month row and down the side of the year grid. The same corner always
names the time zone the grid is drawn in, so a reader in another zone knows what 9:00 means. See Time Zones.
Oct 19 – 25, 2026
<!-- ISO 8601: week 1 holds the year's first Thursday. Shown beside the header in
the week and day views, at the start of each month row, and down the year grid. -->
<Scheduler bind:events weekNumbers />
<!-- The corner above the hour gutter names the zone the way Intl does for the
locale: GMT+7 for Ho Chi Minh City, GMT+1 for London in summer, EDT for New York -->
<Scheduler bind:events timeZone="Europe/London" />Short Events
A chip is never shorter than half a slot, and it drops detail as it gets shorter so the title stays readable. A fifteen minute standup at the default scale is a twelve pixel chip with its title in small type.
October 21, 2026
October 21, 2026
GMT+7// slotMinutes is the unit of the grid. It sets:
// the lines drawn between hours (60 / slotMinutes per hour)
// where a drag snaps (nearest slot boundary)
// the step of the up and down keys (one slot)
// the shortest event a drag or resize makes (one slot)
// the length of a drop from a dragSource with no durationMinutes,
// and of an all-day event dropped onto the grid (two slots)
// slotHeight is pixels per slot. Together they fix the scale of the day:
// dayHeight = (dayEndHour - dayStartHour) * 60 / slotMinutes * slotHeightWhat a chip shows by height
| Chip height | Shows |
|---|---|
Under 20px | One line of small text, centred; the title only |
20px to 38px | The title in small type, without the time |
38px and up | The title and the time range |
Props
The props the time grid reads.
| Prop | Type | Default |
|---|---|---|
dayStartHour | number | 0 |
dayEndHour | number | 24 |
slotMinutes | number | 30 |
slotHeight | number | 24 |
hiddenDays | WeekDay[] | [] |
weekNumbers | boolean | false |
days | number | - |
timeZone | TimeZoneId | local zone |