Day grid view
Day ranges, calendar periods and resource groups with spanning event bars.
Days as columns with spanning event bars, for a day, an N-day range, whole weeks, or calendar months, quarters and years.
Loading the preview…
export const dayGridsFeatures = calendarFeatures({});
export const dayGrids = calendarViews({
features: dayGridsFeatures,
views: {
day: dayGridView({ days: 1, maxEventsPerDay: 3 }),
threeDays: dayGridView({ days: 3, maxEventsPerDay: 3 }),
workweek: dayGridView({ weeks: 1, hiddenDays: [6, 7], maxEventsPerDay: 3 }),
year: dayGridView({ period: 'year', maxEventsPerDay: 3 }),
months: dayGridView({ period: 'year', groupBy: 'month', fixedWeekCount: true, maxEventsPerDay: 3 }),
rooms: dayGridView({ days: 1, groupBy: 'resource', maxEventsPerDay: 3 }),
monthsThenRooms: dayGridView({ period: 'quarter', groupBy: ['month', 'resource'], maxEventsPerDay: 3 }),
roomsThenMonths: dayGridView({ months: 3, groupBy: ['resource', 'month'], maxEventsPerDay: 3 }),
},
});Duration
Every view factory takes exactly one of days, weeks, months or period. Counts are positive integers.
| Duration | Range | next() / prev() |
|---|---|---|
days: N | N dates from date; 7 keeps week alignment. | N days. |
weeks: N | N whole weeks from firstDayOfWeek. | N weeks, keeping the weekday. |
months: N | N calendar months from the first of the anchor month. | N months, landing on the first day. |
period | 'month', 'quarter' or 'year', aligned to its calendar boundary. | One period, landing on its first day. |
Day ranges use one row, week ranges one row per week. Month-based ranges are padded to whole weeks, and padding days
have isOutside: true. A continuous year is one section of weeks.
Grouping
groupBy accepts 'month', 'resource', or an ordered tuple of those distinct keys. Month grouping requires a month-based duration.
groupBy | Result |
|---|---|
| omitted | One continuous grid. |
'month' or ['month'] | One section per month. |
'resource' or ['resource'] | Resource columns within the grid. |
['month', 'resource'] | Month sections, each containing resource columns. |
['resource', 'month'] | Each resource's month sections, in resource input order and then month order. |
groupOrder: 'resource-first' keeps each resource's dates together in a row so bars can span them. 'date-first'
groups columns by date and splits bars at resource boundaries. Neither changes the section order groupBy sets.
An event appears under every resource it names; unassigned events appear only in ungrouped grids. A background event
without resource IDs shades all resources. A cell is isUnavailable when its resource has no availability that day.
Overflow
| Setting | Description |
|---|---|
maxEventsPerDay | Visible bar rows per grid row. Further rows are hidden and counted; Infinity removes the cap. |
dayOverflow(date, resourceId?) | Marks a date/resource cell as having more events, such as events not loaded yet. |
fixedWeekCount | Six rows per month. Allowed with period: 'month' or month grouping. Defaults to false. |
See overflow.
Hidden weekdays
hiddenDays omits ISO weekdays. Use the exported DayOfWeek constants (DayOfWeek.Monday is 1, DayOfWeek.Sunday
is 7) or the numbers; the same values work for firstDayOfWeek and weekly background daysOfWeek.
import { DayOfWeek, timeGridView } from '@calendar-tsx/core';
timeGridView({ weeks: 1, hiddenDays: [DayOfWeek.Saturday, DayOfWeek.Sunday] }); // a workweekHidden weekdays change neither the nominal period, the inclusive fetch range nor the navigation step. Hiding all
seven weekdays throws. When every date in the range is hidden, such as a one-day view on a hidden Saturday, the range
shows its dates anyway.
Bars project onto the remaining columns, and events entirely on hidden dates disappear. Month rows keep their calendar-week boundaries.
Example
export const DayGrid = ({ calendar, onOverflow }: { calendar: DayCalendar; onOverflow: (date: string) => void }) => {
const layout = useCalendarSelector((state: State) => state.layout);
if (layout.kind !== 'dayGrid') return null;
return (
<DayGridView model={layout}>
{layout.sections.map(section => (
<DayGridViewSection key={section.key} section={section}>
{section.month || section.resource ? (
<DayGridViewSectionHeader>
{section.resource?.title} {section.month?.toLocaleString('en-US', { month: 'long', year: 'numeric' })}
</DayGridViewSectionHeader>
) : null}
<DayGridViewHeader>
{section.columns.map(column => (
<DayGridViewHeaderCell key={column.key} column={column}>
{column.resource?.title} {column.date.toLocaleString('en-US', { weekday: 'short' })}
</DayGridViewHeaderCell>
))}
</DayGridViewHeader>
{section.rows.map(week => (
<DayGridViewRow key={week.key} row={week}>
{week.days.map(day => (
<DayGridViewDay key={day.key} day={day}>
<DayGridViewDayTrigger calendar={calendar} day={day} view='day'>
{day.date.day}
</DayGridViewDayTrigger>
<DayGridViewOverflow day={day} onClick={() => onOverflow(day.date.toString())}>
{day.hiddenCount} more
</DayGridViewOverflow>
</DayGridViewDay>
))}
{week.backgroundEvents.map(segment => (
<DayGridViewRowBackgroundEvent key={segment.key} segment={segment} />
))}
{week.segments.map(segment => (
<DayGridViewRowEvent key={segment.key} segment={segment}>
{segment.event.data.title}
</DayGridViewRowEvent>
))}
</DayGridViewRow>
))}
</DayGridViewSection>
))}
</DayGridView>
);
};Model
layout is { kind: 'dayGrid', sections }. The view context also has kind: 'dayGrid'.
Each section has key, period, range, optional month and resource, header columns, columnCount and rows.
A section's month is its first date. isOutside is relative to the section's period, so a date can be outside in one
month and inside the next.
Each row has key, days, bar segments, backgroundEvents, columnCount and stackCount (visible bar rows).
Columns hold key, date and optional resource. Day cells add:
| Day field | Description |
|---|---|
isOutside | The date pads the section and lies outside its period. |
isToday | The date is today in timeZone. |
isUnavailable | The resource has no availability overlapping this date. |
hiddenCount | Hidden bar segments crossing this cell. |
hasMore | hiddenCount > 0, or dayOverflow returned true. |
events | Events on this date/resource, including hidden events, in order. |
| Bar segment field | Description |
|---|---|
event | The event, in the calendar's time zone. |
colStart, colSpan | First visible column, zero-based, and the number of visible columns covered. |
row | Stack row, zero-based. |
isAllDay | The event is all-day. |
isMultiDay | The event covers more than one date, before clipping. A timed event ending at midnight covers only its start date. |
continuesBefore, continuesAfter | The event extends beyond the visible dates at that bar's edges. |
Keys are stable within their parent. Render background events before bars. Background layers decorate each cell and respect its resource scope.
Parts
| Part | Model prop | Element | Notes |
|---|---|---|---|
DayGridView | model | div | Region labelled "Calendar". Contains sections. |
DayGridViewSection | section | div | role='grid'; emits --cal-columns, data-month, and data-resource-id. |
DayGridViewSectionHeader | none | div | Consumer-supplied month or resource label. |
DayGridViewHeader | none | div | role='row'. |
DayGridViewHeaderCell | column | div | role='columnheader', data-weekday, data-resource-id. |
DayGridViewRow | row | div | role='row'; emits column and stack counts. |
DayGridViewDay | day | div | role='gridcell', data-today, data-outside, data-weekday, data-unavailable, data-resource-id. |
DayGridViewDayTrigger | calendar, day, view | button | Navigates through calendar to view on this date. |
DayGridViewRowEvent | segment | button | A bar across the row's visible columns; data-all-day, data-multi-day. |
DayGridViewRowBackgroundEvent | segment | div | An all-day background span; aria-hidden. |
DayGridViewDayBackground | background | div | A background layer's shading; aria-hidden. |
DayGridViewOverflow | day | button | Renders only when day.hasMore. |
Render each section's header and rows inside DayGridViewSection, and bars inside their row beside its day cells.
The default theme lays sections out in a responsive grid: --calendar-section-min-width (default 20rem) sets the
minimum section width and --calendar-section-gap (default 1rem) the gap. Override them, or style the root's grid,
for another arrangement.
For a year overview, use groupBy: 'month' with fixedWeekCount: true. Calendar-only multi-month grids emit
data-multi-month, and the supplied themes give them compact rows, centered headings and padded month panels.
--calendar-section-gap also sets their spacing (defaults 2rem between columns, 1.5rem between rows). With section
and weekday headers present, CSS subgrid aligns neighboring months' header and week tracks. The root's
--cal-month-rows is the largest section row count. Resource grids and single months keep their usual sizing.