Skip to content

release: v2.0.0 — multi-view calendar with i18n, dark mode, RTL & accessibility#76

Merged
Jaganath-MSJ merged 177 commits into
mainfrom
beta
May 26, 2026
Merged

release: v2.0.0 — multi-view calendar with i18n, dark mode, RTL & accessibility#76
Jaganath-MSJ merged 177 commits into
mainfrom
beta

Conversation

@Jaganath-MSJ

@Jaganath-MSJ Jaganath-MSJ commented May 26, 2026

Copy link
Copy Markdown
Owner

Description

Promotes betamain as the v2.0.0 major release of calendar-simple.

This release turns a single-view month calendar into a complete React calendar
library: five view types, full localization, theming with dark mode, RTL, keyboard
accessibility, and resilient loading/error states. It migrates the date engine from
dayjs to Luxon and adopts a compound-component API, so upgrading requires changes
see MIGRATION.md.

Scope: 177 commits · 148 files · +27.5k / −5.9k · 5 breaking changes.

Highlights

  • 🗓️ Five views — Month, Week, Day, Schedule, and configurable Custom-Days, with seamless view switching.
  • 🌍 Localization (i18n) — locale-aware dates and labels powered by Luxon.
  • 🧩 Compound-component APICalendar + provider/hook composition with merged prop distribution.
  • 🌗 Dark modecolorScheme of light / dark / auto with OS detection, plus a scheme-aware theme.
  • ↔️ RTLdirection prop and CSS logical properties, auto-detected from the locale.
  • Accessibility — keyboard navigation, ARIA semantics, and WCAG-compliant event contrast.
  • 📱 Responsive — tablet and phone breakpoints across every view.
  • 🕒 Time-aware — all-day banner, live current-time indicator with auto-scroll, 12-hour format, minHour/maxHour.
  • Resilient — skeleton loading + renderLoading, background-refresh overlay, and a render error boundary.
  • 🎨 Customizable — custom renderers (event / header / hour / date cell) and per-event style.

⚠️ Breaking release. Read MIGRATION.md before upgrading.

Full changelog

💥 Breaking changes

  • Migrate date handling from dayjs → Luxon (DateTime internally throughout).
  • Adopt the compound-component pattern with reworked prop handling.
  • Add internationalization support.
  • Rename types and props for clarity and consistency.
  • Correct plural unit names and ISO date formatting.

✨ Views

  • Day, Week, Schedule, and Custom-Days (multi-day) views, plus view switching.

✨ Events & layout

  • All-day event support and multi-day event handling.
  • All-day banner — expandable overflow, smart expand/collapse, timezone label, maxEvents, sticky header.
  • Live current-time indicator (day/week) with auto-scroll to now.
  • Overlapping-event layout (collision detection) and eventOverlapOffset for stacked events.
  • Slot creation via onSlotClick; onMoreClick receives the hidden-events array.
  • Custom renderers for events, header, hour cells, and date cells.
  • Per-event style prop (replaces color); invalid events (end before start) are filtered out.
  • Performance options (e.g. treating events as pre-sorted).

✨ Theming & display

  • Color scheme / dark mode with auto-detection; scheme-aware theme.
  • RTL direction prop with CSS logical properties.
  • Tablet/phone responsive breakpoints across all views.
  • Week-number display, 12-hour time format, configurable week start/end days.
  • minHour / maxHour, showAdjacentMonths, showAllDayRow, resetDateOnViewChange.
  • Custom separator rendering between Schedule date groups.
  • width / height accept a number (px) or any CSS length string.

✨ Robustness & testability

  • Loading states with view-specific skeletons + renderLoading; non-blocking background-refresh overlay.
  • Error boundary that catches renderer exceptions and renders a fallback.
  • testId prop; test-id container and CSS vars exposed in compound mode.

🐛 Notable fixes

  • Prevent scrollIntoView from scrolling ancestor containers.
  • Cap event z-index so events stay below header elements.
  • Fix flex layout that clipped Schedule-view content.
  • Show all-day banner arrows when the chip boundary differs from the event's actual day.
  • Sync the selectedDate prop and fix year-list calculation.
  • Stop onDateClick firing on non-selectable dates.

♻️ Refactors

  • Restructure component architecture; extract styles, hooks, and reusable core components.
  • Consolidate constants/utilities, extract theme types, replace string literals with enums.

🛠️ Tooling, CI & docs

  • ESLint (type-aware flat config), Prettier, Husky, commitlint, lint-staged.
  • semantic-release config; GitHub Actions PR + test workflow; bundle visualizer behind ANALYZE.
  • Playground redesigned to a single calendar with full prop control.
  • Docs: README, FEATURES, MIGRATION, SECURITY, CONTRIBUTING, CODE_OF_CONDUCT, TEST_CASES, CLAUDE.md, CHANGELOG.

Fixes # (n/a — release promotion)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor / chore (no functional change)

Pull Request Checklist

  • My PR targets the dev branch — N/A: this is the beta → main release promotion
  • My code follows the project's coding guidelines (TypeScript, CSS Modules, Luxon for dates)
  • My commit messages follow the Conventional Commits spec
  • I have added or updated tests that cover my change
  • I have added or updated a Storybook story (if applicable)
  • I have updated the documentation (README.md, FEATURES.md) where relevant
  • All local checks pass: npm run format:check, npm run lint, npm test, npm run build

How Has This Been Tested?

  • Added/updated automated tests (npm test)
  • Verified via Storybook (npm run storybook)
  • Verified via the local playground (cd playground && npm run dev)
  • Verified the build bundle (npm run build)

- Add new DayView component with hourly time grid layout
- Add MonthView component extracted from main Calendar for modularity
- Implement view selector in Header to switch between month/week/day views
- Extend CalendarContext to support view state management
- Add CSS modules for DayView and MonthView components
- Update type definitions to support CalendarViewType
- Refactor Calendar component to conditionally render views based on state
- Rename `data` prop to `events` across components for clarity
- Sync `view` prop from props to context to control calendar view
- Adjust DayView height to account for header
- Update default calendar props and types accordingly
…ypes

- Replace CalendarViewType string union with ECalendarViewType enum
- Replace DAY_TYPE constant with EDayType enum
- Update imports and exports accordingly
- Improve type safety and maintainability
…factor demo

Update the playground to use the local source of calendar-simple instead of the published npm package. This allows testing the latest changes directly. Also refactor the demo data generation to better showcase day/week views with precise datetime events and improve event categorization.
Introduce a new utility function to calculate event positions for overlapping events in day view. This replaces the previous simple top/height calculation with a column-based layout algorithm that properly handles overlapping events by distributing them horizontally.

- Add calculateEventLayout function that groups overlapping events into clusters
- Assign columns within each cluster to prevent visual overlaps
- Update DayView component to use the new layout utility
- Add Storybook example demonstrating overlapping event rendering
- Update playground data to test overlapping scenarios
- Implement sweep-line algorithm for accurate cluster grouping
- Add greedy column assignment with expansion to fill available space
- Fix event width calculation using CSS custom properties
- Ensure minimum event height and proper z-index stacking
- Handle edge cases like zero-duration events
…ties

- Remove columnIndex, totalColumns, and clusterSize from DayEventLayout interface
- Rename internal properties from _prefix to regular names for clarity
- Simplify layout calculation by removing redundant cluster size parameter
- Clean up playground demo data by removing commented/test events
- Change default event duration from 60 to 1 minute when no end date is provided
- Add responsive event item styling for small and tiny time slots
- Improve tooltip formatting to handle events without end dates
- Move EventItem component to its own directory with dedicated styles
- Create new Popover component for displaying overflow events
- Improve code organization and maintainability by separating concerns
- Introduce new WeekView component with time grid layout
- Update calendar header navigation to support week and day views
- Add CSS module for week view styling
- Integrate week view into main calendar component with view switching logic
- Extend event calculation utilities to support weekly layout
- Remove events from CalendarContext and pass them directly to views
- Simplify NEXT/PREV actions using view as unit parameter
- Add onViewChange callback to CalendarType interface
- Remove currentDate prop from view components, use context instead
- Clean up Header month navigation logic
- Create TimeColumn component to display hour slots
- Create DayColumn component to render event slots and layout
- Create DayWeekEventItem component for day/week event rendering
- Extract MonthEventItem into separate component with its own styles
- Move shared CSS from view modules to component modules
- Add generateTooltipText utility for consistent event tooltips
- Update DayView and WeekView to use new components
- Add DATE_FORMATS constant to consolidate date format strings
- Add CALENDAR_ACTIONS constant for action type strings
- Extend CALENDAR_CONSTANTS with new height constants and default color
- Replace hardcoded strings with constants across components
- Use ECalendarViewType enum values instead of string literals
Add is12Hour prop to calendar configuration to allow displaying times in 12-hour format (hh:mm A) instead of 24-hour format. This includes updates to:
- Date constants to add TIME_12H format
- All calendar view components (Day, Week, Month)
- Event tooltips and time displays
- Time column rendering
Add an optional `id` field to the DataType interface to uniquely identify calendar events.
Use this id as the React key for event components (DayWeekEventItem, Popover items, MonthEventItem) to improve rendering performance and stability.
Extract view options into a constant array for cleaner code in the header dropdown.
Update playground example data to include sample ids.
Introduce a new "schedule" view that displays events grouped by date in a vertical list, similar to Google Calendar's agenda view. The view includes date headers, event times, colored dots, and supports multi-day events with appropriate labeling. Also updates the view selector and playground example to include the new view.
- Use 'month' as unit when navigating in schedule view instead of view type
- Remove unused imports and dead code (current time line, table styles, DataType)
- Export ManipulateType from date utils for type safety
- Update header to show dynamic title based on current view (day, week, schedule)
- Add day header styling with day name and number in day view
- Pass events prop to header for schedule view date range calculation
- Propagate dayType prop to DayView component
- Refactor DayColumn props to extend CalendarContentType
- Add view field to CalendarContentType to track current calendar view
- Change is12Hour from optional to required boolean with default false
- Add new date format constants for consistent date formatting across views
- Update all view components to use proper CalendarContentType props
- Fix date formatting in various components to use centralized constants
- Add day header improvements to DayView showing day name and number
- Rename `DataType` to `CalendarEvent` and `CalendarType` to `CalendarProps` for better semantic meaning
- Rename `DataTypeList` to `EventListType` and `CalendarContentType` to `CalendarContentProps`
- Replace `isSelectDate` prop with `selectable` for clearer intent
- Update `currentDate` references to `selectedDate` in context and views
- Remove unused date utility functions and simplify type exports
- Update default props to include `classNames` and reorder for consistency
Update the navigation logic for schedule view to use "day" instead of "month" when moving to next/previous periods. This ensures consistent navigation behavior across all calendar views. Also remove default theme from constants and add today styling support to schedule, day, and week views.
Add missing classNames properties to DayView, WeekView, MonthView, and ScheduleView components to allow custom styling of all calendar elements. This provides consistent styling API across all view types and enables fine-grained CSS customization for time slots, day headers, schedule items, and other UI components.
- Change EDayType keys from 'fullName'/'halfName' to 'full'/'half' for consistency
- Update all references to use new constant names
- Import CSSProperties type explicitly instead of using React.CSSProperties
- Use Dispatch type from React instead of React.Dispatch
…rver

- Remove .calendarContainer CSS class and replace with inline styles to set width/height
- Add optional `notNeeded` parameter to useResizeObserver hook to skip observation when dimensions are provided
- Pass width/height props to skip resize observation when dimensions are explicitly set
- Import CSSProperties and useRef for better type safety and consistency
- Split monolithic Calendar.stories.tsx into separate files for each view (Month, Day, Week, Schedule)
- Each view file includes relevant stories showcasing specific features and configurations
- Maintain all existing functionality while improving Storybook navigation and maintainability
- Add flexbox properties to header for better wrapping on small screens
- Make calendar container use flex column layout to prevent overflow issues
- Fix time column positioning to remain visible during horizontal scrolling
- Add horizontal scrolling support to day and week views
- Refactor month view to use flex layout with sticky headers
- Ensure consistent box-sizing across components
- Introduce AllDayBanner component to display multi-day events
- Filter single-day events from main grid layout to prevent duplication
- Implement row-based layout algorithm for overlapping multi-day events
- Support clipped edges for events that extend beyond visible date range
Add a "more" chip to show count of hidden all-day events beyond the first three rows, allowing users to expand and view all events. This improves usability when many all-day events are scheduled on the same day.
- Add GMT+00 label and expand/collapse button to the time header spacer
- Adjust TIME_12H format to show only hour with AM/PM
- Improve hidden events logic: show "+ X more" only when 2+ events are hidden
- Increase effective max rows when hiding would take same space as showing
- Refactor layout to use bannerWrapper for better structure
Move the complex layout calculation logic from the AllDayBanner component into a dedicated utility function getAllDayBannerLayout. This improves code separation, maintainability, and reusability while keeping the component focused on rendering.
Jaganath-MSJ and others added 26 commits May 9, 2026 10:37
feat: RTL support, color scheme/dark mode, error boundary, and bug fixes
feat!: v2 — compound components, RTL, dark mode, a11y, responsive, i18n, loading states, slot creation, and breaking refactors
- @actions/core 3.0.0 → 3.0.1
- @actions/http-client 4.0.0 → 4.0.1
- undici 6.24.1 → 6.25.0
- Additional transitive dependency updates
- Replace two-calendar layout with a single focused Calendar instance
- Rename kebab-case files to PascalCase (App, ControlPanel, TestFixtures)
- Rebuild ControlPanel with collapsible sections and modified-count badges
- Add per-section and global Reset buttons
- Add theme colour pickers and localeMessages label overrides
- Replace checkboxes with CSS toggle switches for boolean props
- Add Result + Notes columns to all test matrices (A–L) with current run data
- Merge 286 PASS, 4 FAIL, 19 N/A results from 2026-05-07 test session
- Update "Results file" reference to point to this file instead of TEST_REPORT.md
- Add TEST_REPORT.md to .gitignore (local-only artifact)
- Document G-12, K-03, K-05, TC3 failures and cross-cutting findings

PLAYWRIGHT_TEST_PLAN.md is now the single source of truth for both test spec and results.
Previously the bundle visualizer ran on every build, opening
dist/stats.html in the browser unconditionally. Wrap it in a
process.env.ANALYZE guard so it only activates when needed.

- visualizer now skipped unless ANALYZE=1 is set
- run with: $env:ANALYZE=1; npm run build
…script

- Switch from recommendedTypeChecked (was: recommended) in eslint.config.js;
  add parserOptions.project to enable type-aware rules
- Chain tsc --noEmit before eslint in lint and lint:fix scripts so all
  TypeScript compiler errors appear when running npm run lint
- Fix type-safety issues uncovered by stricter checking: replace non-null
  assertion with optional chaining in DayColumn, remove unnecessary HTMLElement
  cast in Popover, simplify config fallback cast in CalendarContext
- Fix useResizeObserver test: convert dynamic act import to static top-level
  import and move assertion outside the async callback
- Exclude eslint.config.js and vite.config.ts from type-aware linting as
  they are not part of tsconfig.json
- Add §1.2 Loading States (skeleton/overlay modes, RTL, console hygiene)
- Add §1.12–1.16: Color Scheme, i18n/RTL, Responsive Layout, Accessibility, Compound API
- Add §2.6–2.8: DST boundaries, year/month spanning, Unicode/XSS edge cases
- Add §3 Known Issues table tracking confirmed bugs (G-12, K-03, K-05, TC3)
- Expand §1.6 with creatable prop, testId, and popover focus/viewport tests
- Expand §1.7 with AllDayBanner expand/collapse toggle tests
- Renumber §1.2–1.10 → §1.3–1.11 to accommodate new Loading States section
- Clarify dayType prop: controls day-name format, not time bounds
…er bypass

useEvents() correctly filtered negative-duration events, but CalendarProvider
received the unfiltered allProps.events in its config prop. All sub-views read
events from that config via useCalendarProps(), bypassing the filter entirely.
Passing validEvents into the config spread closes the bypass for every view,
including compound-component children. Adds a regression test (TC3).
Consolidates the Playwright MCP test playbook into a Claude Code
slash command at .claude/commands/playwright.md. Captures the 310-case
test matrix (sweeps A-L), session init protocol, fixture/prop catalogs,
common selectors, and per-run result log.

- 12 sweeps x 309 executed cases with PASS/FAIL/N/A results
- TC3 negative-duration filter regression tracked through full
  discovery -> fix (commit 7e5714b) -> verified-closed lifecycle
- Known Issues and Open Follow-up Items tables updated through the
  2026-05-17 retest (only K-03 and K-05 remain as OPEN library FAILs)
- Run Log preserves 2026-05-07 / 05-16 / 05-17 (initial) / 05-17 (retest)
- Emit console.warn (K-03) when eventsAreSorted=true but the array is
  unsorted — surfaces silent render-order bugs at development time
- Emit console.warn (K-05) when enableEnrichedEvents=true but
  enrichedEventsByDate is absent — prevents silent multi-day fallback
- Thread enrichedEventsByDate into useEvents call in Calendar.tsx
- Add warnSpy guards to existing tests affected by the new warnings
- Add 6 new tests covering warn/no-warn branches for K-03 and K-05
Update TEST_CASES.md known-issues table to reflect that K-03 and K-05
are now resolved — both misuse patterns emit a console.warn instead of
failing silently.

Update JSDoc on enrichedEventsByDate, enableEnrichedEvents, and
eventsAreSorted props to document the console.warn contract so
consumers are aware at authoring time.
- Export CalendarClassNames from src/index.ts (was missing from public API)
- Add 20 cn* fields to PanelState, DEFAULTS, and SECTION_KEYS
- Assemble classNames object in toCalendarProps (undefined when all empty)
- Add "Class Names" section in JSX with text inputs grouped by view area
  (Global, Month, Events, Week/Day, Schedule) -- enables E-13--E-18 interactive re-run
Call onChange outside the setState updater in patch and resetSection so
the parent setState no longer fires during React's render phase, fixing
the "Cannot update a component while rendering" warning.

Change the Section header from a <button> to a div with role="button"
(tabIndex, onKeyDown, aria-expanded) so the reset control can be a real
nested button without invalid <button>-in-<button> markup.
Document Firefox/WebKit cross-browser testing and bring the playbook in
line with the 2026-05-19 and 2026-05-21 runs.

- Add `--browser=firefox|webkit` parsing, a Cross-Browser Sessions
  section (tool namespaces, 29-case CB subset, CB Known Issues), and a
  Browser column on the Test Run Log
- Record CB results: full parity across Firefox/WebKit/Chromium; D-17
  verified PASS via a scrollTo spy (headless Firefox no-ops smooth
  scroll); note the browser-independent "1280pxpx" preset quirk
- Close K-03/K-05 and follow-up items 3-10; mark all 20 VIS screenshots
  captured; refresh the Known Issues and Open Follow-up tables
Add a global `colorScheme: "light"` arg in the Storybook preview config so
every story renders light by default instead of following the OS
`prefers-color-scheme` (the library's `auto` default). Also exclude the
`.storybook` directory from typed ESLint linting, matching how `src/stories`
and `vite.config.ts` are handled, so the pre-commit hook stops failing on
`.storybook/preview.ts`.

- Applies the light default to all current and future stories from one point
- Explicit dark/auto demo stories override via their own args, so unaffected
- Adds `.storybook` to eslint.config.js ignores to fix typed-lint parse errors
feat: v2 hardening — event validation fix, DX warnings, playground & tooling
Previously, width and height were always interpolated as `${value}px`,
which doubled the unit for string inputs like "1280px" or "100%".

- Add `toCssLength` utility: passes strings verbatim, appends px to numbers
- Use `toCssLength` for `--calendar-width` and `--calendar-height` CSS vars
  in both CalendarContent and the compound-children code path
- Wrap string heights in `calc(${rawHeight} - ${HEADER_HEIGHT}px)` so the
  header is correctly subtracted for any CSS length string
- Add unit tests for `toCssLength` and regression tests for dimension vars
  (A-11/J-12 regression coverage)
All entries in the Known Issues, Cross-Browser Known Issues, and Open
Follow-up Items tables were CLOSED or RESOLVED, making them dead weight
in the command file. Removing them keeps the run instructions lean.

- Drop Known Issues table (G-12, K-03, K-05, TC3, TC3-ROOT — all closed)
- Drop Cross-Browser Known Issues table (D-17 resolved, A-11/J-12 fixed)
- Drop Open Follow-up Items table (all 10 items closed)
- Remove [KNOWN BUG] tagging instruction and Known Issues/Follow-up
  sections from the TEST_REPORT.md template
- Remove Known Issues section from TEST_CASES.md (same bugs, all fixed)
Release beta: flexible width/height props, validated-events fix (TC3), dev-time misuse warnings (K-03/K-05), type-aware linting & playground redesign
Align contributor-facing docs with the actual project setup, correct
inaccurate CSS theming examples, and expand Claude's project guidance.

- README/FEATURES: fix dark-mode examples to use the real CSS variables
  (--bg-color, --text-primary, --primary-color), correct the light
  palette :root note, and drop links to the gitignored docs/ directory
- CONTRIBUTING/PR template/issue templates: target the `dev` branch,
  add CI-aligned verify steps, testing and Conventional Commits guidance,
  and Calendar-specific issue/PR fields
- CODE_OF_CONDUCT/SECURITY: replace placeholder/empty reporting details
  with a concrete private reporting channel and response window
- CLAUDE.md: document loading/error-handling, color-scheme and RTL
  architecture, and clarify the lint script
fix: correct theming variable docs and modernize project docs
Swap the boilerplate Vite + TypeScript README for documentation
specific to the calendar-simple playground.

- Explain the file:.. dependency on the library's dist/ build
- Document the build-library-first setup step (dist/ is git-ignored)
- Add scripts table, source-file tour, and usage tips
fix: replace playground Vite template README with playground guide
@netlify

netlify Bot commented May 26, 2026

Copy link
Copy Markdown

Deploy Preview for calendarsimple ready!

Name Link
🔨 Latest commit 00ec25e
🔍 Latest deploy log https://app.netlify.com/projects/calendarsimple/deploys/6a14fec86242180009cc9bc7
😎 Deploy Preview https://deploy-preview-76--calendarsimple.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@Jaganath-MSJ Jaganath-MSJ merged commit 734b18a into main May 26, 2026
7 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant