Skip to content

refactor(Calendar): migrate to motion components#35666

Open
robertpenner wants to merge 40 commits intomicrosoft:masterfrom
robertpenner:refactor/calendar-motion
Open

refactor(Calendar): migrate to motion components#35666
robertpenner wants to merge 40 commits intomicrosoft:masterfrom
robertpenner:refactor/calendar-motion

Conversation

@robertpenner
Copy link
Collaborator

@robertpenner robertpenner commented Jan 16, 2026

This PR migrates Calendar animations from legacy CSS keyframe animations to Fluent UI v9 motion components in the @fluentui/react-calendar-compat package. The main focus is on replacing slide and fade animations in the calendar with reusable motion components, improving maintainability and consistency with Fluent UI v9 standards. All related CSS animations and constants have been removed or deprecated, and the necessary dependencies have been added.

Calendar Animation Migration

  • Migrated all calendar slide and fade animations from CSS to motion components (DirectionalSlide, HeaderFade), including day, month, and year views.
  • Removed CSS animation styles and constants from style files and marked all animation constants in animations.ts as @deprecated for backwards compatibility.

Component Refactoring

  • Updated CalendarGridRow to use React.forwardRef to support motion component refs and maintain accessibility.
  • Fixed PresenceComponent.In and .Out to use MotionComponent type in createPresenceComponent.ts (@fluentui/react-motion minor bump).

Dependency Updates

  • Added @fluentui/react-motion and @fluentui/react-motion-components-preview as dependencies to support new motion components.

Package and Documentation Updates

  • Added a detailed migration plan in MOTION_MIGRATION_PLAN.md documenting the phases, completed work, and validation tasks for the motion migration.
  • Added change files for tracking the patch and minor updates to the relevant packages.

- Copied from MessageBarGroup.motions.tsx for now
- Simplified document to reflect completed Phase 1 (slide animations)
- Documented Phase 2 remaining work (CalendarPicker button rows and header fade animations)
- Clarified migration status with table of completed vs remaining CSS animations
- Updated file status table to show Phase 1 completion
- Added specific migration approach for Phase 2 tasks
- Use motionTokens.durationSlower (400ms) instead of hardcoded 367ms
- Rename fromX/fromY props to outX/outY to match Slide.In API
- Simplify distance calculation logic
- Add JSDoc comment explaining duration token choice
- Change from FunctionComponent to forwardRef to enable ref support
- Required for motion components to properly animate table rows
- Add displayName for better debugging
…Slide

- Remove unnecessary <div> wrappers inside DirectionalSlide components
- CalendarGridRow now accepts refs directly via forwardRef
- Fixes invalid DOM nesting (div inside tbody)
- Maintains slide animation functionality
…endarDayGrid

- Remove CSS keyframe animations for row sliding (now handled by DirectionalSlide)
- Remove unused imports (SLIDE_*, DURATION_3, EASING_FUNCTION_1, TRANSITION_ROW_DISAPPEARANCE)
- Remove animation-related style classes from weekRow, firstTransitionWeek, lastTransitionWeek
- Remove animateBackwards and animationDirection logic from style application
- Add comments explaining migration to motion components
- Keeps FADE_IN, DURATION_2, EASING_FUNCTION_2 for header animations (not yet migrated)
- Convert DURATION_* from string seconds to millisecond numbers using motion tokens
- Update comments to clarify which animations still use CSS vs motion components
- Document that DURATION_3 is no longer used (slide animations now use motion)
- Note that EASING_FUNCTION_2 has no exact motion token equivalent
- Add @fluentui/react-motion ^9.11.5
- Add @fluentui/react-motion-components-preview ^0.14.2
- Required for DirectionalSlide motion component
…arGridRow

Required for server-side rendering compatibility with React.forwardRef
…d rows

- Wrap year picker rows with DirectionalSlide motion component
- Consistent animation behavior with CalendarMonth button rows
- Part of Phase 2 motion migration
…endarPicker

- Remove CSS keyframe animations for button row sliding
- Now handled by DirectionalSlide motion component in CalendarMonth/CalendarYear
- Remove unused imports (SLIDE_*, DURATION_3, EASING_FUNCTION_1)
- Keep FADE_IN, DURATION_2, EASING_FUNCTION_2 for header fade animation
…eprecated

- Reorganize animations.ts with used vs deprecated sections
- Add @deprecated JSDoc tags to unused animation constants
- Add eslint-disable for deprecated re-exports in index.ts
- Keep FADE_IN, DURATION_2, EASING_FUNCTION_2 (still used for header fade)
- Maintain backwards compatibility for external consumers
Add HeaderFade component that wraps Fade.In from react-motion-components-preview.
The component uses navigationKey prop to trigger fade animation when the value changes.

- Uses motionTokens.durationGentle (~250ms) matching original DURATION_2 (267ms)
- Replaces CSS keyframe fade animations with motion component
Replace CSS fade animation on year string header with HeaderFade motion component.

- Add HeaderFade wrapper around yearString span in CalendarMonth.tsx
Replace CSS fade animation on year range title with HeaderFade motion component.

- Add HeaderFade wrapper around year range spans in CalendarYearTitle
- Handles both clickable button and static div cases
…darPicker styles

Remove CSS fade animation from useCalendarPickerStyles.styles.ts now that header fade
is handled by HeaderFade motion component.

- Remove DURATION_2, EASING_FUNCTION_2, FADE_IN imports
- Remove animation block from useCurrentItemButtonStyles
- Remove animateBackwards destructuring (no longer used)
…mplete

Update MOTION_MIGRATION_PLAN.md to reflect completed migration:

- All CSS animations migrated to motion components
- DirectionalSlide for slide animations
- HeaderFade for header fade animations
- Animation constants marked as deprecated
- Build and tests passing
…o Fade.In motion component

- Wrap day label <th> elements in Fade.In in CalendarMonthHeaderRow.tsx
- Remove CSS fade animation from useCalendarDayGridStyles.styles.ts
- Mark FADE_IN, DURATION_2, EASING_FUNCTION_2 as @deprecated in animations.ts
- Update migration plan to mark Phase 3 complete
@robertpenner robertpenner force-pushed the refactor/calendar-motion branch from 6d649b2 to 0579a4c Compare March 12, 2026 07:56
@github-actions
Copy link

Pull request demo site: URL

@robertpenner robertpenner added the Component: Calendar Compat Calendar Compat component label Mar 12, 2026
@github-actions
Copy link

github-actions bot commented Mar 12, 2026

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-calendar-compat
Calendar Compat
149.292 kB
39.866 kB
152.996 kB
42.129 kB
3.704 kB
2.263 kB
react-datepicker-compat
DatePicker Compat
225.125 kB
63.619 kB
228.505 kB
65.757 kB
3.38 kB
2.138 kB

🤖 This report was generated against ec5736348028dcf9a0fbebb818a79242d23b4e1c

@robertpenner robertpenner marked this pull request as ready for review March 12, 2026 08:58
@robertpenner robertpenner requested review from a team and ValentinaKozlova as code owners March 12, 2026 08:58
ariaHidden={true}
/>
{weeks!.slice(1, weeks!.length - 1).map((week: DayInfo[], weekIndex: number) => (
<DirectionalSlide key={'firstTransitionWeek_' + firstWeek[0].key} {...{ animationDirection, animateBackwards }}>
Copy link
Member

@layershifter layershifter Mar 16, 2026

Choose a reason for hiding this comment

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

Why do need a key there? To re-trigger a motion?

…te PR

Move the MotionComponent type change on .In/.Out to a dedicated PR
as requested in code review, since it affects a shared package.
…ndant div keys

Remove HeaderFade — the header fade animation was not present on master,
so it was adding new behavior rather than migrating existing animations.
Also remove redundant key on inner div inside DirectionalSlide wrappers.
@robertpenner robertpenner force-pushed the refactor/calendar-motion branch from c91fb99 to 73903d6 Compare March 16, 2026 16:14
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.

2 participants