Skip to content

fix(components/core): animationend and transitionend handlers detect suppressed animations via getComputedStyle#4310

Merged
Blackbaud-SteveBrush merged 8 commits intomainfrom
animation-handlers-fix
Mar 18, 2026
Merged

fix(components/core): animationend and transitionend handlers detect suppressed animations via getComputedStyle#4310
Blackbaud-SteveBrush merged 8 commits intomainfrom
animation-handlers-fix

Conversation

@Blackbaud-SteveBrush
Copy link
Copy Markdown
Member

@Blackbaud-SteveBrush Blackbaud-SteveBrush commented Mar 17, 2026

Our Storybook's PreviewWrapperComponent applies transition-property: none !important globally, which suppresses all CSS transitions and prevents transitionend events from firing. The transition/animation handler directives were refactored to remove the _skyAnimationsDisabled() check (which only looked for our own CSS properties' values) and instead detect disabled CSS motion via getComputedStyle(). When transitions or animations are suppressed (e.g., transition-property: none or transition-duration: 0s), the handlers now emit via a microtask fallback so consuming components still receive completion events. This means that even if our components are added to an application that deliberately disables animation/transition properties globally, our components will still work as expected.

Summary by CodeRabbit

  • Refactor

    • Motion handlers now detect disabled CSS motion on the element (e.g., animation-name none or zero-duration) and emit completion via a microtask when motion is disabled.
    • A centralized watcher utility replaces the prior global-flag conditional wiring and per-case simulation logic.
  • Tests

    • Test helpers simplified; removed global-flag scaffolding and added cases for zero-duration, property-none, and other CSS-based disabled-motion scenarios.

@Blackbaud-SteveBrush Blackbaud-SteveBrush added the risk level (author): 2 This change has a slight chance of introducing a bug label Mar 17, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 347f64ae-9b5e-4b5f-8105-63ce72998bcf

📥 Commits

Reviewing files that changed from the base of the PR and between bb32490 and d748b9c.

📒 Files selected for processing (1)
  • libs/components/core/src/lib/modules/animations/shared/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/components/core/src/lib/modules/animations/shared/utils.ts

📝 Walkthrough

Walkthrough

Replaces global noop-animation detection with element-level watchers: removes mimicCssMotionEvent and _skyAnimationsDisabled, adds watchForDisabledCssAnimations/watchForDisabledCssTransitions, and updates animation/transition handlers and tests to emit via microtask when CSS motion is disabled.

Changes

Cohort / File(s) Summary
Animation handler & tests
libs/components/core/src/lib/modules/animations/shared/animation-handler.ts, libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts
Handler now uses watchForDisabledCssAnimations instead of _skyAnimationsDisabled/mimicCssMotionEvent. Tests simplified (removed noopAnimations wiring) and expanded to cover animation-name: none and animation-duration: 0s microtask emission cases.
Transition handler & tests
libs/components/core/src/lib/modules/animations/shared/transition-handler.ts, libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts
Handler now uses watchForDisabledCssTransitions, adds private computed propertyToTrack, and test helpers updated (removed noopAnimations, added rethrow flag). Tests extended for transition-property: none, transition-duration: 0s, and property-tracking edge cases.
New motion utilities
libs/components/core/src/lib/modules/animations/shared/utils.ts
Adds watchForDisabledCssAnimations, watchForDisabledCssTransitions, and WatchMotionArgs; centralizes logic that reads computed styles, skips initial/unrendered runs, and queues microtask emissions when motion is disabled.
Removed legacy utilities & tests
libs/components/core/src/lib/modules/animations/shared/mimic-css-motion-event.ts, libs/components/core/src/lib/modules/animations/utility/animations-disabled.ts, libs/components/core/src/lib/modules/animations/utility/animations-disabled.spec.ts
Deleted mimicCssMotionEvent, top-level _skyAnimationsDisabled, and their tests — functionality consolidated into new utils and handlers.
Test scaffolding adjustments
.../animation-handler.spec.ts, .../transition-handler.spec.ts (same files as above)
Test setup functions signatures simplified/changed (removed noopAnimations option), provider arrays cleaned, and fixture/test flows updated to use new watcher behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Handler as Animation/Transition Handler
    participant Watcher as watchForDisabledCss* Utility
    participant Effect as Angular Effect
    participant DOM as DOM Element
    participant Emit as Output Emitter

    Handler->>Watcher: init(elementRef, destroyRef, trigger, emitter, propertyToTrack?)
    Watcher->>Effect: create effect observing trigger

    loop on trigger change
        Effect->>DOM: getComputedStyle(element)
        DOM-->>Effect: animation/transition properties
        Effect->>Effect: evaluate isMotionDisabled (name=none OR duration≤0 OR property-specific)
        alt motion disabled
            Effect->>+Emit: queueMicrotask(emit)
            Emit-->>-Effect: emission scheduled
        else motion enabled
            Effect->>Effect: no microtask emission
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • johnhwhite

Poem

🐇 I sniff the stylesheet, quiet and neat,
When name is none or duration meets defeat,
I hop a microtask, soft and spry,
Emitting ends while change detection flies. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring animation/transition handlers to detect suppressed animations via getComputedStyle() instead of the previous _skyAnimationsDisabled() check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch animation-handlers-fix
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 17, 2026

View your CI Pipeline Execution ↗ for commit a916e69

Command Status Duration Result
nx build code-examples-playground --baseHref=ht... ✅ Succeeded 4m 28s View ↗
nx build playground --baseHref=https://blackbau... ✅ Succeeded 1m 43s View ↗
nx build integration --baseHref=https://blackba... ✅ Succeeded 38s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-18 12:41:56 UTC

@Blackbaud-SteveBrush Blackbaud-SteveBrush marked this pull request as ready for review March 17, 2026 13:12
@Blackbaud-SteveBrush Blackbaud-SteveBrush changed the title fix(components/core): animation and transition handlers detect suppressed animations via getComputedStyle fix(components/core): animationend and transitionend handlers detect suppressed animations via getComputedStyle Mar 17, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts (1)

72-74: Consider removing stale cleanup code.

Same as in animation-handler.spec.ts, the afterEach block removes the sky-animations-disabled CSS class, but no test in this file adds it. This cleanup appears to be leftover from the previous implementation.

Proposed fix
-  afterEach(() => {
-    document.body.classList.remove('sky-animations-disabled');
-  });
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts`
around lines 72 - 74, The afterEach cleanup that calls
document.body.classList.remove('sky-animations-disabled') in
transition-handler.spec.ts is stale because no test in this file adds that
class; remove the entire afterEach block (the anonymous function passed to
afterEach) to avoid unnecessary teardown, ensuring tests rely only on their own
setup/teardown and mirroring the change made in animation-handler.spec.ts.
libs/components/core/src/lib/modules/animations/shared/utils.ts (1)

9-21: Consider typing elementRef more strictly.

The interface accepts ElementRef without a type parameter, which defaults to any for nativeElement. Since getComputedStyle requires an Element, consider using ElementRef<Element> to make the type contract explicit.

Proposed fix
 interface EmitWhenMotionDisabledArgs {
   /** The directive's `DestroyRef`, used to suppress emissions after teardown. */
   destroyRef: DestroyRef;

   /** A reference to the host element whose computed styles are inspected. */
-  elementRef: ElementRef;
+  elementRef: ElementRef<Element>;

   /** The output emitter to call when CSS motion is disabled. */
   emitter: OutputEmitterRef<void>;

   /** A signal that drives motion tracking. Emissions are evaluated whenever this value changes. */
   trigger: Signal<unknown>;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/components/core/src/lib/modules/animations/shared/utils.ts` around lines
9 - 21, The interface EmitWhenMotionDisabledArgs currently types elementRef as
ElementRef (which makes nativeElement any); tighten the contract by changing
elementRef to ElementRef<Element> so callers provide an Element-compatible ref
for use with getComputedStyle, and update any call sites that construct
EmitWhenMotionDisabledArgs to pass Element-typed ElementRef instances
accordingly; ensure usages that call getComputedStyle(elementRef.nativeElement)
compile after the change.
libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts (1)

55-57: Consider removing stale cleanup code.

The afterEach block removes the sky-animations-disabled CSS class, but since provideNoopSkyAnimations is no longer used in these tests and no test adds this class, this cleanup appears to be dead code. Consider removing it to avoid confusion.

Proposed fix
-  afterEach(() => {
-    document.body.classList.remove('sky-animations-disabled');
-  });
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts`
around lines 55 - 57, Remove the stale cleanup in the test file: delete the
afterEach block that calls
document.body.classList.remove('sky-animations-disabled') since
provideNoopSkyAnimations is no longer used and no tests add that class; search
for and remove the specific afterEach that references 'sky-animations-disabled'
to avoid leaving dead test teardown code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts`:
- Around line 55-57: Remove the stale cleanup in the test file: delete the
afterEach block that calls
document.body.classList.remove('sky-animations-disabled') since
provideNoopSkyAnimations is no longer used and no tests add that class; search
for and remove the specific afterEach that references 'sky-animations-disabled'
to avoid leaving dead test teardown code.

In
`@libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts`:
- Around line 72-74: The afterEach cleanup that calls
document.body.classList.remove('sky-animations-disabled') in
transition-handler.spec.ts is stale because no test in this file adds that
class; remove the entire afterEach block (the anonymous function passed to
afterEach) to avoid unnecessary teardown, ensuring tests rely only on their own
setup/teardown and mirroring the change made in animation-handler.spec.ts.

In `@libs/components/core/src/lib/modules/animations/shared/utils.ts`:
- Around line 9-21: The interface EmitWhenMotionDisabledArgs currently types
elementRef as ElementRef (which makes nativeElement any); tighten the contract
by changing elementRef to ElementRef<Element> so callers provide an
Element-compatible ref for use with getComputedStyle, and update any call sites
that construct EmitWhenMotionDisabledArgs to pass Element-typed ElementRef
instances accordingly; ensure usages that call
getComputedStyle(elementRef.nativeElement) compile after the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd01bdd9-f2cd-4892-bb94-2374d788ec1d

📥 Commits

Reviewing files that changed from the base of the PR and between 90b183b and 4e0bdd0.

📒 Files selected for processing (6)
  • libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts
  • libs/components/core/src/lib/modules/animations/shared/animation-handler.ts
  • libs/components/core/src/lib/modules/animations/shared/mimic-css-motion-event.ts
  • libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts
  • libs/components/core/src/lib/modules/animations/shared/transition-handler.ts
  • libs/components/core/src/lib/modules/animations/shared/utils.ts
💤 Files with no reviewable changes (1)
  • libs/components/core/src/lib/modules/animations/shared/mimic-css-motion-event.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates SKY UX’s internal animationend/transitionend handler directives to detect suppressed CSS motion by inspecting element computed styles (rather than relying on the sky-animations-disabled mechanism), and to fall back to microtask emissions when native motion events won’t fire (e.g., transition-property: none !important in Storybook).

Changes:

  • Added shared utilities that watch computed CSS animation/transition properties and microtask-emit when motion is disabled.
  • Refactored the animation/transition handler directives to use the new computed-style detection (removing the prior global “animations disabled” check).
  • Updated unit tests to validate microtask fallback behavior under suppressed animation/transition CSS states.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
libs/components/core/src/lib/modules/animations/shared/utils.ts New shared helpers that inspect computed styles and microtask-emit when CSS motion is suppressed.
libs/components/core/src/lib/modules/animations/shared/transition-handler.ts Refactors transitionend handling to rely on computed-style suppression detection utilities.
libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts Updates tests to validate suppressed-transition detection and microtask fallback emissions.
libs/components/core/src/lib/modules/animations/shared/mimic-css-motion-event.ts Removes the old global “motion disabled” microtask mimic helper.
libs/components/core/src/lib/modules/animations/shared/animation-handler.ts Refactors animationend handling to rely on computed-style suppression detection utilities.
libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts Updates tests to validate suppressed-animation detection and microtask fallback emissions.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the core CSS transitionend/animationend handler directives to detect suppressed CSS motion by inspecting computed styles on the host element, ensuring consumers still receive completion events when transitions/animations are globally disabled (e.g., Storybook’s transition-property: none !important).

Changes:

  • Added shared utilities to detect disabled CSS transitions/animations via getComputedStyle() and emit a microtask fallback when suppressed.
  • Updated transition/animation handler directives to use the new computed-style based detection (removing reliance on _skyAnimationsDisabled() and the old mimic helper).
  • Updated unit tests to cover disabled/enabled motion scenarios based on CSS properties.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
libs/components/core/src/lib/modules/animations/shared/utils.ts New shared computed-style based detection + microtask fallback helpers.
libs/components/core/src/lib/modules/animations/shared/transition-handler.ts Uses the new transition suppression watcher and tracks the property via a computed signal.
libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts Reworks tests to validate behavior under suppressed transitions via CSS properties.
libs/components/core/src/lib/modules/animations/shared/animation-handler.ts Uses the new animation suppression watcher for microtask fallback emission.
libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts Reworks tests to validate behavior under suppressed animations via CSS properties.
libs/components/core/src/lib/modules/animations/shared/mimic-css-motion-event.ts Removes the old “animations disabled” microtask mimic helper.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts (1)

45-69: ⚠️ Potential issue | 🟡 Minor

This helper makes the new initial-render transition test a false positive.

Because setupTest() runs the first detectChanges() before callers can set transition-property: none, the case at Lines 206-223 is not exercising disabled motion on initial render. It also asserts before a queued microtask would run. Please allow pre-render style setup for that scenario and await fixture.whenStable() before asserting no emission.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts`
around lines 45 - 69, The test helper setupTest currently always calls
fixture.detectChanges() which forces initial render before callers can set
pre-render styles (e.g., transition-property: none) and it asserts before queued
microtasks run; change setupTest to accept an option like skipInitialDetect?:
boolean (or reuse skipTrackProperty name) so callers can set pre-render styles
before the first render, and make setupTest async: only call
fixture.detectChanges() when not skipping and after calling detectChanges await
fixture.whenStable() before returning; also update tests that check "no emission
on initial render" to call setupTest({ skipInitialDetect: true }), set the
transition-property style, then call fixture.detectChanges() and await
fixture.whenStable() before asserting no emission. Reference functions/fields:
setupTest, fixture.detectChanges, fixture.whenStable,
handler.setPropertyToTrack, componentRef.setInput('trigger', signal(false)).
libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts (1)

40-53: ⚠️ Potential issue | 🟡 Minor

setupTest() can’t validate first-render suppression cases.

This helper performs the first detectChanges() before the spec can apply animation-name: none / animation-duration: 0s, so the case at Lines 108-123 never actually runs with disabled motion on initial render. It also asserts before any queued microtask would flush. Please let that test set initial styles before the first render and await fixture.whenStable() before asserting no emission.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts`
around lines 40 - 53, The helper setupTest() currently calls
fixture.detectChanges() immediately which prevents tests from applying
"animation-name: none"/"animation-duration: 0s" before first render and also
skips waiting for microtasks; modify setupTest() (and any callers) to accept an
option (e.g., { skipInitialDetect?: true }) or a flag to avoid the immediate
detectChanges(), so tests can set initial styles on the TestComponent host (via
fixture.nativeElement.style or fixture.componentRef.setInput) before the first
render; also update the specs that assert no emission to call await
fixture.whenStable() after the first render (or after detectChanges when used)
before asserting to ensure queued microtasks have flushed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/components/core/src/lib/modules/animations/shared/utils.ts`:
- Around line 108-117: The effect created around trigger() is inadvertently
depending on propertyToTrack() because isMotionDisabled(style) reads that
signal; to fix, wrap the call to isMotionDisabled(style) inside untracked(() =>
...) so the effect only tracks trigger changes; import untracked from
`@angular/core` and replace the direct isMotionDisabled(style) check with an
untracked-wrapped call (preserving the initialized and isRendered guards) to
prevent unintended effect reruns.

---

Outside diff comments:
In
`@libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts`:
- Around line 40-53: The helper setupTest() currently calls
fixture.detectChanges() immediately which prevents tests from applying
"animation-name: none"/"animation-duration: 0s" before first render and also
skips waiting for microtasks; modify setupTest() (and any callers) to accept an
option (e.g., { skipInitialDetect?: true }) or a flag to avoid the immediate
detectChanges(), so tests can set initial styles on the TestComponent host (via
fixture.nativeElement.style or fixture.componentRef.setInput) before the first
render; also update the specs that assert no emission to call await
fixture.whenStable() after the first render (or after detectChanges when used)
before asserting to ensure queued microtasks have flushed.

In
`@libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts`:
- Around line 45-69: The test helper setupTest currently always calls
fixture.detectChanges() which forces initial render before callers can set
pre-render styles (e.g., transition-property: none) and it asserts before queued
microtasks run; change setupTest to accept an option like skipInitialDetect?:
boolean (or reuse skipTrackProperty name) so callers can set pre-render styles
before the first render, and make setupTest async: only call
fixture.detectChanges() when not skipping and after calling detectChanges await
fixture.whenStable() before returning; also update tests that check "no emission
on initial render" to call setupTest({ skipInitialDetect: true }), set the
transition-property style, then call fixture.detectChanges() and await
fixture.whenStable() before asserting no emission. Reference functions/fields:
setupTest, fixture.detectChanges, fixture.whenStable,
handler.setPropertyToTrack, componentRef.setInput('trigger', signal(false)).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 154a6a2e-6d26-4975-a53c-eb732eb06ac4

📥 Commits

Reviewing files that changed from the base of the PR and between 4e0bdd0 and e43c4e3.

📒 Files selected for processing (6)
  • libs/components/core/src/lib/modules/animations/shared/animation-handler.spec.ts
  • libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts
  • libs/components/core/src/lib/modules/animations/shared/transition-handler.ts
  • libs/components/core/src/lib/modules/animations/shared/utils.ts
  • libs/components/core/src/lib/modules/animations/utility/animations-disabled.spec.ts
  • libs/components/core/src/lib/modules/animations/utility/animations-disabled.ts
💤 Files with no reviewable changes (2)
  • libs/components/core/src/lib/modules/animations/utility/animations-disabled.ts
  • libs/components/core/src/lib/modules/animations/utility/animations-disabled.spec.ts

@Blackbaud-SteveBrush Blackbaud-SteveBrush enabled auto-merge (squash) March 18, 2026 12:32
@Blackbaud-SteveBrush Blackbaud-SteveBrush merged commit 88d7b0f into main Mar 18, 2026
193 of 194 checks passed
@Blackbaud-SteveBrush Blackbaud-SteveBrush deleted the animation-handlers-fix branch March 18, 2026 12:48
johnhwhite pushed a commit that referenced this pull request Mar 18, 2026
##
[14.0.0-alpha.10](14.0.0-alpha.9...14.0.0-alpha.10)
(2026-03-18)


### ⚠ BREAKING CHANGES

* **components/layout:** replace `@angular/animations` in text expand
repeater component with CSS transitions (#4317)
* **components/layout:** replace `@angular/animations` in text expand
component with CSS transitions (#4308)
* **components/inline-form:** replace `@angular/animations` with CSS
transitions (#4315)
* **components/popovers:** replace `@angular/animations` with CSS
transitions (#4313)

### Features

* **components/modals:** modal header close button is shown in modern
theme ([#4265](#4265))
([db2a615](db2a615))


### Bug Fixes

* **components/core:** animationend and transitionend handlers detect
suppressed animations via `getComputedStyle`
([#4310](#4310))
([88d7b0f](88d7b0f))
* **components/inline-form:** replace `@angular/animations` with CSS
transitions ([#4315](#4315))
([5254dbb](5254dbb))
* **components/layout:** replace `@angular/animations` in text expand
component with CSS transitions
([#4308](#4308))
([bbde359](bbde359))
* **components/layout:** replace `@angular/animations` in text expand
repeater component with CSS transitions
([#4317](#4317))
([bb4a3c7](bb4a3c7))
* **components/popovers:** replace `@angular/animations` with CSS
transitions ([#4313](#4313))
([28088aa](28088aa))
* **sdk/skyux-eslint:** remove `no-barrel-exports` rule
([#4320](#4320))
([73dafd6](73dafd6)),
closes
[AB#3614172](https://dev.azure.com/blackbaud/Products/_workitems/edit/3614172)
[#4268](#4268)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Breaking Changes**
  * Animation behavior updated across multiple components

* **New Features**
  * Added close button to modal headers in the modern theme

* **Bug Fixes**
  * Resolved animation handling issues affecting multiple components
  * Fixed related stability issues across components

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk level (author): 2 This change has a slight chance of introducing a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants