Scheduler - Cells and Headers

Customize month, timeline, and mini-month cells and headers.

#Choose a Surface

Use cell and header outlets when the month or year surface needs different content. Use data attributes when the content can stay the same and only state styling changes.

SurfaceUse
Scheduler.MonthHeaderCellReplace weekday labels, add compact abbreviations, or show calendar-specific weekday marks.
Scheduler.MonthCellNumberReplace the day-number chip while Scheduler keeps cell focus, range, disabled, and today state.
Scheduler.MonthCellWrap the whole month cell when the cell background or date-level layout needs app-owned markup.
Scheduler.MonthDayCellCustomize the day body beneath the number and above the event stack.
Scheduler.MiniMonthHeaderReplace the month label in year view.
Scheduler.MiniMonthCellReplace year-view date cells with small indicators or status marks.
Data attributesStyle today, selected, weekend, other-month, disabled, drop-valid, or range state without replacing markup.

Reserve a circular day-number treatment for today or the active day. Use the cell background, outline, or range fill for selected days so the user can distinguish selected state from the current date.

#Small Override

Start with the weekday header and day-number surfaces. The month cell root still owns focus, selection, range, disabled, other-month, event area, and more-link behavior.

<Scheduler.Content>
    <Scheduler.Month>
        <Scheduler.MonthHeaderCell>
            <AvailabilityWeekday />
        </Scheduler.MonthHeaderCell>
        <Scheduler.MonthCellNumber>
            <AvailabilityDayNumber />
        </Scheduler.MonthCellNumber>
    </Scheduler.Month>
</Scheduler.Content>

The replacement component receives the month cell number payload as props and should stay compact.

<script setup lang="ts">
const props = defineProps<{
    dayNumberLabel?: string;
    isToday?: boolean;
    isSelected?: boolean;
    isDisabled?: boolean;
    isOtherMonth?: boolean;
}>();
</script>

<template>
    <span class="availability-day" :data-today="props.isToday || undefined">
        {{ props.dayNumberLabel }}
    </span>
</template>

#Payload

Month and mini-month payloads carry date state rather than event-card state.

FieldSurfaceUse
dateMonth and mini-month cellsBind tooltips, labels, or data lookups to the exact day.
dayNumberLabel, dayOfMonthLabelDay-number surfacesRender localized day numbers.
isTodayMonth and mini-month cellsMark the current day.
isSelectedMonth and mini-month cellsStyle selected or range-selected days without changing today semantics.
isDisabledMonth and mini-month cellsDim dates outside min/max rules.
isOtherMonthMonth day numbersDe-emphasize adjacent-month filler days.
eventCount, hasEventsMini-month cellsShow dense year-view activity markers.
eventsMonth day cellsSummarize visible date activity without rebuilding the event stack.

Use the Data Attributes reference when state styling is enough. Use an outlet when a date needs different content, badges, labels, or mini-month markers.

#Month

Replace the month weekday header and day number with application-owned markup. The month grid still handles overflow state and event layout.

Loading Demo...

#Advanced Example

Customize month and mini-month cells with domain markers. The cell context still carries date ownership, disabled state, today state, and range behavior.

Loading Demo...

#Checklist

  • Keep weekday labels aligned with the column grid and avoid multi-line labels unless the month header height is designed for them.
  • Keep day-number badges small enough to avoid clipping in dense month cells.
  • Use cell background or outline for selected cells, not the same circular treatment used for today.
  • Preserve disabled and other-month states so adjacent-month days do not look active.
  • Keep event count badges away from the more-link area.
  • Keep mini-month cells compact and centered. Year view has less room than month view.
  • Check weekend, today, range, drop-valid, and overflow states after styling.

#Timeline Header Child Props

The normal Scheduler.TimelineHeaderCell declaration injects props into its single replacement child. It does not call its declaration slot with a scoped payload. Import SchedulerTimelineHeaderCellPayload to type that child:

<script setup lang="ts">
import type { SchedulerTimelineHeaderCellPayload } from '@primeui/vue-scheduler';

const props = defineProps<Partial<SchedulerTimelineHeaderCellPayload>>();
</script>

<template>
    <span>{{ props.label }}</span>
</template>

Declare it inside <Scheduler.TimelineHeaderCell><PlanningHeader /></Scheduler.TimelineHeaderCell>. Optional props keep that declaration valid because runtime injection happens after Vue checks the child invocation. The payload contains date, cell, label, width, startDate and endDate; it has no view field. The low-level Scheduler.Timeline.HeaderCell slot receives the same typed payload. Vue can type an explicitly declared child contract, but cannot infer arbitrary injected props on another child automatically.

#Full-Cell Timeline Headers

Custom TimelineHeaderCell content automatically owns the full available cell width and height. The cell keeps its width, borders and date alignment; your content supplies padding and alignment. There is no layout prop or mode.

Custom content renders outside the sticky label wrapper and receives no label max-width, translation or sticky inset. Built-in labels keep their existing sticky behavior. Existing custom headers may need padding or alignment adjustments after this patch. Declarations still follow the same view-scope precedence.

The studio example gives month, day and hour tiers a shared neutral surface, adds studio hours to the day tier, and keeps only the text group sticky. The background and padding still paint the whole cell, including while scrolling. The example uses theme tokens and works in either direction.

Loading Demo...

For the same behavior in your own content, put width: 100%; height: 100% on the painting surface, then position: sticky; inset-inline-start: 0.75rem; width: max-content on its inner text group. Keep the text bounded by that surface and use logical insets for RTL. Avoid overflow: hidden or overflow: auto on an intermediate child: they create another scroll owner and prevent native sticky text from following the timeline. Custom content remains application-owned; Scheduler does not make the entire outlet sticky.

The component keeps virtual header cells in normal flow, so this native sticky child works across virtual windows without a scroll listener or offset formula.

#API

Public outlets include Scheduler.MonthCellNumber, Scheduler.MonthHeaderCell, Scheduler.MonthCell, Scheduler.MonthDayCell, Scheduler.MiniMonthHeader, and Scheduler.MiniMonthCell with the context fields listed in Slots and Contexts.