shaduler
Recipes

All-day events

Multi-day strip above the hourly grid. Overlapping events stack into lanes.

Vacations, multi-day workshops, holidays — events that span entire days. They live in their own strip above the hourly grid (Google Calendar / Outlook style), keeping the hourly grid clean for time-of-day events.

Mon 9
Tue 10
Wed 11
Thu 12
Fri 13
Sat 14
Sun 15
Ana — PTO
React workshop
Marko — PTO
Public holiday
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
Standup
Workshop kickoff
Pair session
Demo day
Long run

The all-day strip is a separate primitive (ShadulerAllDayStrip) that you opt into when your data has multi-day events. Render it between the columns header and the hourly grid.

const START_HOUR = 8
const END_HOUR = 18
const HOUR_HEIGHT_PX = 60
const TIME_COLUMN_WIDTH_PX = 72

type VacationTask = ShadulerAllDayTaskData & {
  category: 'vacation' | 'workshop' | 'holiday'
}

const allDayEvents: VacationTask[] = [
  { id: 'pto-ana', name: 'Ana — PTO', startColumn: 'mon', endColumn: 'wed', category: 'vacation' },
  { id: 'workshop', name: 'React workshop', startColumn: 'tue', endColumn: 'thu', category: 'workshop' },
]

const calc = calculateShadulerData(
  columns,
  hourlyTasks,
  START_HOUR,
  END_HOUR,
  HOUR_HEIGHT_PX,
  { timeColumnWidth: TIME_COLUMN_WIDTH_PX },
)
<ShadulerColumnsHeader gridTemplateColumns={calc.gridTemplateColumns}>
  <ShadulerCorner />
  {columns.map(...)}
</ShadulerColumnsHeader>

<ShadulerAllDayStrip<VacationTask>
  columns={columns}
  tasks={allDayEvents}
  gridTemplateColumns={calc.gridTemplateColumns}
>
  {(positions) =>
    positions.map((pos) => (
      <ShadulerAllDayTask
        key={pos.task.id}
        position={pos}
        className={categoryClass[pos.task.category]}
      >
        <span className="truncate">{pos.task.name}</span>
      </ShadulerAllDayTask>
    ))
  }
</ShadulerAllDayStrip>

<ShadulerGrid ...>
  {/* hourly grid as usual */}
</ShadulerGrid>

Overlapping events stack into lanes automatically — calculateAllDayPositions (called internally by the strip) does a greedy lane assignment per event in input order.

Pass gridTemplateColumns from calc so the strip aligns perfectly with the columns header above and the hourly grid below.