Skip to content

[scheduler] Add viewConfig prop to limit displayed hours in the day and week views#22929

Merged
rita-codes merged 7 commits into
mui:masterfrom
flaviendelangle:scheduler-view-config-start-end-time
Jul 2, 2026
Merged

[scheduler] Add viewConfig prop to limit displayed hours in the day and week views#22929
rita-codes merged 7 commits into
mui:masterfrom
flaviendelangle:scheduler-view-config-start-end-time

Conversation

@flaviendelangle

Copy link
Copy Markdown
Member

Changelog

Add a new viewConfig prop to the Event Calendar, keyed by view name, so each view can receive its own configuration.

For the day and week time-grid views, viewConfig accepts startTime and endTime (whole hours between 0 and 24) to limit the hours displayed in the time grid:

<EventCalendar viewConfig={{ week: { startTime: 8, endTime: 20 } }} />

Closes #19952

Details

  • New public viewConfig prop on EventCalendar, EventCalendarPremium, and the standalone day/week views (and their premium counterparts).

  • The day and week views render only the configured hour window: the time axis, grid height, event/placeholder/current-time-indicator positioning, and drag-and-drop / event creation all respect the range.

  • The internal "view config" concept (the per-view runtime behavior each view registers — siblingVisibleDateGetter / visibleDaysSelector) is renamed to "view definition" to free up the viewConfig name for this public API.

  • startTime / endTime must be whole hours; minute-level precision isn't supported yet (documented with a callout and in the JSDoc).

  • Added unit tests (range validation, axis-row count, event positioning, clamping, per-view key selection) and two documentation demos under the Week and Day view sections.

  • I have followed (at least) the PR section of the contributing guide.

🤖 Generated with Claude Code

…ek views

Adds a new public `viewConfig` prop to the Event Calendar (and standalone
views), keyed by view name. The `day` and `week` time-grid views accept
`startTime`/`endTime` (whole hours, 0-24) to limit the displayed hour range.

Renames the internal "view config" concept to "view definition" to free up
the `viewConfig` name for the public API.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@flaviendelangle flaviendelangle added the scope: scheduler Changes related to the scheduler. label Jun 24, 2026
@flaviendelangle
flaviendelangle marked this pull request as draft June 24, 2026 13:30
@flaviendelangle flaviendelangle self-assigned this Jun 24, 2026
@flaviendelangle flaviendelangle added the type: new feature Expand the scope of the product to solve a new problem. label Jun 24, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Jun 24, 2026

Copy link
Copy Markdown

Deploy preview

Bundle size

ℹ️ Using snapshot from parent commit d575a01 (fallback from merge base 0cb49d9).

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-scheduler 🔺+2.73KB(+0.77%) 🔺+774B(+0.80%)
@mui/x-scheduler-premium 🔺+4.59KB(+0.96%) 🔺+1.3KB(+0.98%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@flaviendelangle
flaviendelangle marked this pull request as ready for review June 24, 2026 17:53

@rita-codes rita-codes left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work 🙌, left a few things from a review pass, leading with a rendering bug that's visible in the new demo itself.

🔴 Events fully outside the hour range still render (visible in the Week demo)

In WeekViewStartEndTime (window 8–20), the Morning Run occurrence at 07:00–07:45 still shows up as a thin bar pinned to the top of the column, labeled "Morning Run 7:00 AM". TimeGridColumn feeds all of day.withoutPosition into useEventOccurrencesWithTimelinePosition without intersecting them against [startTime, endTime), so an out-of-window occurrence gets clamped to duration: 0 / position: 0 but is still in the DOM — and minHeight: 11.5 in TimeGridEventShared makes it a visible sliver with a misleading time.

Two consequences:

  • a ghost event renders at the top edge with the wrong displayed time;
  • it still counts toward maxIndex / --columns-count, so a genuinely-visible event in the same column can be squeezed into a narrower lane for no apparent reason.

Occurrences that only partially overlap the window should keep clamping (that part works), but ones entirely before startTime or after endTime shouldn't be placed at all.

Screenshot 2026-06-30 at 12 10 23

🟡 DST-day misalignment from deriving minutes out of elapsed time

In CalendarGridTimeColumn, dayStartMinute/dayEndMinute are computed from real elapsed time (adapter.getTime(end) - startOfDayMs), but event positions use wall-clock minutesInDay and the grid renders whole-hour rows (hoursCount = endTime - startTime). On a DST-transition day the derived dayMinutes becomes 1380/1500 while the rows stay whole-hour, so events and the current-time indicator drift off the grid lines. This also regresses the default full-day view on those days (it used a fixed 1440 before). The minute offsets really want to come from the whole-hour window itself rather than be reverse-engineered from the dates.

🟡 Keyboard event creation can land outside the window

triggerKeyboardCreation anchors at setHours(start, 12) (noon), ignoring the range. With e.g. { startTime: 13, endTime: 20 }, pressing Enter on the column creates an event at 12:00 — outside the visible window, so it renders clamped with the wrong time.

🟡 Tests

  • The new test files (getTimeGridHourRange.test.ts, DayTimeGrid.viewConfig.test.tsx) don't follow the repo's it('should …') convention.
  • Coverage gaps worth adding: clamped height (not just --y-position), current-time-indicator hidden when out of range, the endTime === 24 / startTime === 0 branches in TimeGridColumn, drag/creation inside a limited window, and the startTime === endTime validation case.

ℹ️ Minor

  • EventCalendarStore.ts:202 still warns "No config found for the current view. Please use useInitializeView" — stale after the config→definition rename (the hook is useEventCalendarView).
  • In TimeGridColumn, the start memo's startTime === 0 branch is equivalent to setHours(startOfDay, 0), so the ternary is redundant (the endTime === 24 one isn't — keep that).

ℹ️ API design (worth deciding before it ships)

  • viewConfig is accepted on views that ignore it (month/agenda) and with the wrong key on single-view standalone views — it type-checks and silently no-ops, with no hint to the user.

- Skip occurrences entirely outside the visible window so they no longer
  render as clamped slivers or inflate the column lane count.
- Derive the day minute offsets from the whole-hour window (passed as props)
  instead of elapsed time, fixing DST-day misalignment.
- Clamp keyboard event creation to the visible window.
- Fix the stale "useInitializeView" warning and drop the redundant
  startTime === 0 ternary.
- Follow the it('should …') test convention and add coverage for
  out-of-window events, clamped height, and the startTime === endTime case.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@flaviendelangle

flaviendelangle commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

Thanks for the review 🙌 — addressed the feedback in edc3bda.

🔴 Events fully outside the hour range still render

TimeGridColumn now filters day.withoutPosition down to occurrences that actually overlap [start, end) before placing them. Partially-overlapping events keep clamping; ones entirely before startTime or after endTime are no longer placed, so the ghost sliver is gone and they no longer count toward maxIndex / --columns-count.

🟡 DST-day misalignment

Removed the elapsed-time derivation of dayStartMinute/dayEndMinute in CalendarGridTimeColumn. The minute offsets now come from the whole-hour window itself: TimeGridColumn passes dayStartMinute={startTime * 60} / dayEndMinute={endTime * 60} as props (defaulting to 0 / 1440), so they stay aligned with the whole-hour rows on DST days and the default full-day view is no longer regressed.

🟡 Keyboard creation landing outside the window

triggerKeyboardCreation now clamps the noon anchor into the column window, so e.g. { startTime: 13 } creates inside the visible range instead of at 12:00.

🟡 Tests

  • Renamed the new test files to the it('should …') convention.
  • Added coverage: events entirely outside the window are not rendered (locks in the 🔴 fix), clamped height (not just --y-position), and the startTime === endTime validation case.

ℹ️ Minor

  • Fixed the stale warning → now No definition found for the current view. Please use useEventCalendarView.
  • Dropped the redundant startTime === 0 ternary in the start memo (kept the endTime === 24 one).

Still open for discussion

  • API design: viewConfig being accepted (and silently no-op'd) on month/agenda views and with the wrong key on standalone single-views is a genuine design decision — I left it untouched for now. Happy to add a dev-time warning or tighten the per-view types, whichever direction you'd prefer.
  • I added the highest-value test cases from the coverage list; a couple of the remaining ones (drag inside a limited window, explicit endTime === 24 / startTime === 0 branch tests) are not in yet — can round those out if you'd like full coverage.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jun 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

…nfig-start-end-time

# Conflicts:
#	packages/x-scheduler-internals/src/use-event-calendar-view/useEventCalendarView.ts
#	packages/x-scheduler/src/agenda-view/AgendaView.tsx
#	packages/x-scheduler/src/compact-day-view/CompactDayView.tsx
#	packages/x-scheduler/src/compact-three-day-view/CompactThreeDayView.tsx
#	packages/x-scheduler/src/compact-week-view/CompactWeekView.tsx
#	packages/x-scheduler/src/day-view/DayView.tsx
#	packages/x-scheduler/src/internals/utils/day-time-grid-view-definition.ts
#	packages/x-scheduler/src/month-view/MonthView.tsx
#	packages/x-scheduler/src/week-view/WeekView.tsx
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 1, 2026
@rita-codes

rita-codes commented Jul 1, 2026

Copy link
Copy Markdown
Member

Thanks for laying out the options 🙌

API design — let's tighten the per-view types rather than add a runtime warning. Keep viewConfig present on every view, but narrow its type to the keys that view can actually consume:

  • day → Pick<EventCalendarViewConfig, 'day'>
  • week → Pick<EventCalendarViewConfig, 'week'>
  • month / agenda → Omit<EventCalendarViewConfig, 'day' | 'week'> (empty today, picks up their own keys as we add them)
  • EventCalendar / EventCalendarPremium → full type

Same per-view type-refinement idea as CollapsibleResourcesParameterKeys in #22920, just narrowing the shape instead of dropping the prop. I'd keep it keyed (no flattening on the single-date views) so it doesn't diverge from EventCalendar and stays forward-compatible as viewConfig grows into a general per-view bucket. The empty {} on month/agenda is a bit bare in the API docs for now but honest — it stops those views advertising day/week keys they can't use.

Otherwise this looks good to me 🥇
Thanks!! 🙇‍♀️

@flaviendelangle

Copy link
Copy Markdown
Member Author

@rita-codes done ✔️

@rita-codes

rita-codes commented Jul 2, 2026

Copy link
Copy Markdown
Member

One gap! the standalone compact views (StandaloneCompactDayView, StandaloneCompactWeekView, StandaloneCompactThreeDayView). They use the same DayTimeGrid, so the day and week ones should use it too, read timeGridConfig and pass startTime/endTime like DayView/WeekView do.

CompactThreeDayView is the open one, since there's no key for a 3-day view in viewConfig. Since @noraleonte is working in this area, maybe worth checking with her on what to do there 👀

@flaviendelangle

Copy link
Copy Markdown
Member Author

If the compact views are not available within the EventCalendar for now, I would just omit the viewConfig prop for now from StandaloneCompactThreeDayViewProps and add it back when user can opt-in into this view in the EventCalendar somehow.

By the way, I think those standalone compact views should be exported as unstable because we don't know what the end DX will be.

@rita-codes

rita-codes commented Jul 2, 2026

Copy link
Copy Markdown
Member

If the compact views are not available within the EventCalendar for now, I would just omit the viewConfig prop for now from StandaloneCompactThreeDayViewProps and add it back when user can opt-in into this view in the EventCalendar somehow.

By the way, I think those standalone compact views should be exported as unstable because we don't know what the end DX will be.

that sounds reasonable to me!

cc @noraleonte

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 2, 2026
flaviendelangle and others added 2 commits July 2, 2026 17:53
…nfig-start-end-time

# Conflicts:
#	packages/x-scheduler-premium/src/agenda-view-premium/AgendaViewPremium.types.ts
#	packages/x-scheduler-premium/src/day-view-premium/DayViewPremium.types.ts
#	packages/x-scheduler-premium/src/month-view-premium/MonthViewPremium.types.ts
#	packages/x-scheduler-premium/src/week-view-premium/WeekViewPremium.types.ts
#	packages/x-scheduler/src/agenda-view/AgendaView.types.ts
#	packages/x-scheduler/src/day-view/DayView.types.ts
#	packages/x-scheduler/src/month-view/MonthView.types.ts
#	packages/x-scheduler/src/week-view/WeekView.types.ts
The compact views cannot yet be opted into within the EventCalendar, so
their standalone props should not expose viewConfig. Omit it for now; it
can be added back once these views become configurable from the calendar.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jul 2, 2026
@rita-codes
rita-codes merged commit c32058a into mui:master Jul 2, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: scheduler Changes related to the scheduler. type: new feature Expand the scope of the product to solve a new problem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[scheduler] Support custom start time and end time on the Time Column (week and day views)

2 participants