Skip to content

[WC-3313]: Calendar Year View - #2353

Open
rahmanunver wants to merge 5 commits into
mainfrom
calendar/year-view
Open

[WC-3313]: Calendar Year View#2353
rahmanunver wants to merge 5 commits into
mainfrom
calendar/year-view

Conversation

@rahmanunver

@rahmanunver rahmanunver commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What

Adds a Year view to the Calendar widget: a 12-month grid with event-indicator dots and prev/next/today year navigation, available in both Standard and Custom view modes.

Configurable day-click target

Clicking a day drills into an author-configurable target view (yearDayClickView: day / week / work_week / month / agenda, default day). The target is constrained at runtime to views that are actually enabled — if the chosen target isn't enabled, day cells render non-interactive (no role/tabIndex/handlers, aria-label retained) and nothing navigates.

Also in this PR

  • fix: declare .css/.scss/.png module types (typings/modules.d.ts) to satisfy tsc — matches the sibling-widget convention.
  • chore: moved calendar's OpenSpec change into the package (calendar-web/openspec/), adopting the package-scoped OpenSpec model.

@github-actions

This comment has been minimized.

@rahmanunver rahmanunver changed the title feat(calendar-web): year view with configurable day-click target [WC-3313]: Calendar Year View Jul 23, 2026
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

AI Code Review

🔶 Changes requested — one or more medium-severity items must be addressed


What was reviewed

File Change
src/components/YearView.tsx New YearView container component
src/components/MonthMiniGrid.tsx New per-month grid with day cells and event dots
src/helpers/YearViewController.ts New factory controller (navigate/title/range statics)
src/helpers/CalendarPropsBuilder.ts Refactored view registration, added year + drill-down resolution
src/components/Toolbar.tsx Added year view button support
src/Calendar.xml Added year enum to three enumerations; new yearDayClickView* properties
typings/CalendarProps.d.ts Updated generated types to match XML changes
src/Calendar.editorConfig.ts Hide/show year properties based on view mode
src/Calendar.editorPreview.tsx Added year to preview views array
src/Calendar.tsx Import reordering only
src/ui/Calendar.scss Year view styles inside the &-year-view block
src/utils/calendar-utils.ts Expanded date-fns re-exports
typings/modules.d.ts New CSS/SCSS/PNG module declarations
CHANGELOG.md Unreleased entry for year view

Skipped (out of scope): openspec/, pnpm-lock.yaml


Findings

🔶 Medium — aria-label for leading/trailing day cells reports wrong month

File: src/components/MonthMiniGrid.tsx line 121
Problem: The ariaLabel is constructed using monthName, which is always the current grid month (e.g. "Apr" for April's grid). Leading days from the previous month (e.g. March 30 shown at the start of April's grid) are announced as "Apr 30, 2026" instead of "Mar 30, 2026". Screen-reader users hear the wrong date.
Fix: Derive the label from cell.date directly using the localizer — e.g. localizer.format(cell.date, "MMM d, yyyy", undefined) — instead of concatenating the grid's monthName with cell.dayNumber.


🔶 Medium — console.warn fires on every calendar re-render

File: src/helpers/CalendarPropsBuilder.tsresolveDayClickView method
Problem: CalendarPropsBuilder.build() runs inside a useMemo that depends on props, which gets a new reference on every Mendix data update. When the year drill-down target is not an enabled view, the console.warn inside resolveDayClickView fires once per re-render, spamming the browser console in production.
Fix: Deduplicate with a module-level Set of already-warned view names, or remove the warn entirely — the property description already explains the silent-disable behaviour.


⚠️ Low — cursor: pointer applied to non-interactive day cells

File: src/ui/Calendar.scss inside .year-day-cell
Note: cursor: pointer is set on every .year-day-cell, but when onDayClick is undefined the cell has no role, tabIndex, or click handler. A pointer cursor on a non-clickable element is misleading. Add a .year-day-cell-interactive modifier class in JSX when onDayClick is provided and move cursor: pointer there.


⚠️ Low — background-color: white hardcoded in month card

File: src/ui/Calendar.scss inside .year-month-card
Note: The literal white value cannot be overridden by custom Atlas themes or dark mode. Prefer an Atlas CSS variable with fallback: background-color: var(--bg-color-default, white).


Positives

  • Follows the established custom-view factory pattern exactlyYearViewController mirrors CustomWeekController with factory + static methods.
  • getEnabledViewNames() as single source of truth — the phantom-Day-view registration refactor is clean and well-tested with three dedicated unit tests.
  • Non-interactive fallback is well-implemented — when drill-down is disabled, cells correctly drop role/tabIndex/onClick while retaining aria-label, validated in both YearView and MonthMiniGrid specs.
  • Event grouping is efficient and correct — the useMemo month-grouping clamps events to year boundaries (handles Dec→Jan cross-year events) and avoids re-filtering on every render.
  • Comprehensive test coverage — new tests cover year-boundary events, multi-month spans, all-day events, today highlighting, keyboard navigation (Enter/Space), and the non-interactive mode.
  • Removed stale @ts-expect-error for navigatable — cleans up a suppressor that was no longer needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants