Skip to content

fix(components/tabs)!: replace @angular/animations with CSS transitions#4288

Merged
Blackbaud-SteveBrush merged 26 commits intomainfrom
tabs-refactor-animations
Mar 17, 2026
Merged

fix(components/tabs)!: replace @angular/animations with CSS transitions#4288
Blackbaud-SteveBrush merged 26 commits intomainfrom
tabs-refactor-animations

Conversation

@Blackbaud-SteveBrush
Copy link
Copy Markdown
Member

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

BREAKING CHANGE

SkySectionedFormComponent and SkyVerticalTabsetComponent have replaced @angular/animations with CSS transitions. Tests that interact with sectioned forms or vertical tabs in responsive/mobile mode may need to add provideNoopSkyAnimations() from @skyux/core to their TestBed providers to disable SKY UX CSS transitions during tests.

import { provideNoopSkyAnimations } from '@skyux/core';

TestBed.configureTestingModule({
  providers: [provideNoopSkyAnimations()],
});

AB#3913635
AB#3913634

Summary by CodeRabbit

  • Refactor

    • Modernized sectioned form and vertical tabset animation handling for improved performance and rendering efficiency.
    • Updated animation state management with reactive control patterns.
  • Tests

    • Updated test infrastructure across all tab component tests and harnesses.
  • Chores

    • Removed @angular/animations peer dependency.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

This pull request migrates the tabs components from Angular animations to CSS-based animations with provider-based test configuration. Changes include replacing Angular animation triggers with CSS class bindings, removing animation state properties from services, introducing a reactive animation-enabled signal, and updating all test files to use the new provideNoopSkyAnimations provider instead of NoopAnimationsModule.

Changes

Cohort / File(s) Summary
Test Module Configuration
apps/integration/.../vertical-tabset-back-to-top.component.spec.ts, libs/components/code-examples/.../tabs/*/example.component.spec.ts, libs/components/code-examples/.../modal.component.spec.ts, libs/components/docs-tools/.../code-example-viewer.component.spec.ts, libs/components/tabs/testing/.../harness.spec.ts, libs/components/tabs/.../vertical-tabset.service.spec.ts
Replaced NoopAnimationsModule imports with provideNoopSkyAnimations from @skyux/core and updated TestBed configurations to use the provider instead of module import.
Fixture Module Updates
libs/components/tabs/.../sectioned-form-fixtures.module.ts, libs/components/tabs/.../vertical-tabs-fixtures.module.ts
Replaced NoopAnimationsModule with provideNoopSkyAnimations provider in fixture module declarations and imports.
Vertical Tabset Component
libs/components/tabs/.../vertical-tabset.component.html, libs/components/tabs/.../vertical-tabset.component.ts, libs/components/tabs/.../vertical-tabset.module.ts
Removed Angular animation triggers and imports; replaced with CSS class bindings (sky-animation-slide-enter-left/right); added transition end handler directive; removed animation state constant dependencies.
Vertical Tabset Service
libs/components/tabs/.../vertical-tabset.service.ts
Removed exported animation state constants (VISIBLE_STATE, HIDDEN_STATE) and public animation state properties (animationContentVisibleState, animationTabsVisibleState).
Sectioned Form Component
libs/components/tabs/.../sectioned-form.component.html, libs/components/tabs/.../sectioned-form.component.ts, libs/components/tabs/.../sectioned-form.component.spec.ts
Replaced Angular animation triggers with CSS class bindings controlled by a new animationEnabled signal; added signal initialization on first render; updated test assertions to verify content visibility instead of animation states.
Dependencies
libs/components/tabs/package.json
Removed @angular/animations peer dependency.

Sequence Diagram

sequenceDiagram
    participant Component as Sectioned Form<br/>Component
    participant Signal as animationEnabled<br/>Signal
    participant Template as Template<br/>(HTML)
    participant CSS as CSS<br/>Transitions

    Note over Component,CSS: Animation Initialization
    Component->>Signal: Set animationEnabled = false (initial)
    Component->>Component: afterNextRender callback registered
    
    Note over Component,CSS: First Render Completes
    Component->>Signal: Enable animationEnabled via signal(true)
    Signal-->>Template: Notify of state change
    
    Note over Component,CSS: Animation Playback
    Template->>Template: Apply class when animationEnabled = true
    Template->>CSS: Bind sky-animation-slide-enter-left/right
    CSS->>CSS: CSS transition executes
    CSS-->>Template: transitionEnd event fires
    Template->>Component: Handler processes completion
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • johnhwhite
  • Blackbaud-TrevorBurch

Poem

🐰 Bouncing through code with glee and cheer,
No more Angular animations here!
CSS classes now take the stage,
Signals and transitions all the rage,
Smoother hops, no delays in sight,
Our animation migration's done just right! 🎬✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Title check ✅ Passed The title clearly and concisely describes the main refactoring: replacing Angular animations with CSS transitions in the tabs component.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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
  • Post copyable unit tests in a comment
  • Commit unit tests in branch tabs-refactor-animations
📝 Coding Plan
  • Generate coding plan for human review comments

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

Tip

You can disable poems in the walkthrough.

Disable the reviews.poem setting to disable the poems in the walkthrough.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 11, 2026

View your CI Pipeline Execution ↗ for commit 836bf08

Command Status Duration Result
nx build code-examples-playground --baseHref=ht... ✅ Succeeded 6m 12s View ↗
nx build playground --baseHref=https://blackbau... ✅ Succeeded 1m 37s View ↗
nx build integration --baseHref=https://blackba... ✅ Succeeded 37s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-17 12:49:49 UTC

@blackbaud-sky-build-user
Copy link
Copy Markdown
Collaborator

blackbaud-sky-build-user commented Mar 11, 2026

@Blackbaud-SteveBrush Blackbaud-SteveBrush added the risk level (author): 2 This change has a slight chance of introducing a bug label Mar 12, 2026
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 migrates SkySectionedFormComponent and SkyVerticalTabsetComponent from @angular/animations to CSS-based transitions (SKY UX animations), and updates affected tests/fixtures to disable CSS transitions via provideNoopSkyAnimations().

Changes:

  • Replace Angular animation triggers with CSS transition classes and a transition-end handler where needed.
  • Update unit tests, harness tests, and example/integration specs to use provideNoopSkyAnimations() (and provideNoopAnimations() where Angular animations are still relevant).
  • Remove @angular/animations from @skyux/tabs peer dependencies.

Reviewed changes

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

Show a summary per file
File Description
libs/components/tabs/testing/src/modules/vertical-tabset/vertical-tabset-harness.spec.ts Switch harness tests from NoopAnimationsModule to provideNoopSkyAnimations().
libs/components/tabs/testing/src/modules/sectioned-form/sectioned-form-harness.spec.ts Switch harness tests from NoopAnimationsModule to provideNoopSkyAnimations().
libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.service.ts Remove Angular-animation state fields/constants previously used by triggers.
libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.module.ts Import _SkyAnimationTransitionHandlerDirective needed for CSS transition completion events.
libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.component.ts Remove @angular/animations; add afterNextRender/signal-based animation enabling.
libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.component.html Replace Angular triggers with CSS classes + skyAnimationTransitionHandler and (transitionEnd).
libs/components/tabs/src/lib/modules/vertical-tabset/fixtures/vertical-tabs-fixtures.module.ts Replace NoopAnimationsModule with provideNoopSkyAnimations() for fixtures.
libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.ts Remove @angular/animations; add afterNextRender/signal-based animation enabling.
libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.html Replace Angular triggers with CSS transition classes.
libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.spec.ts Update expectations to validate actual visible content rather than animation state.
libs/components/tabs/src/lib/modules/sectioned-form/fixtures/sectioned-form-fixtures.module.ts Replace NoopAnimationsModule with provideNoopSkyAnimations() for fixtures.
libs/components/tabs/package.json Remove @angular/animations peer dependency.
libs/components/core/src/lib/modules/animations/shared/transition-handler.ts Tighten transitionTrigger typing and adjust noop-mode emission behavior.
libs/components/core/src/lib/modules/animations/shared/transition-handler.spec.ts Update tests for new transitionTrigger typing + new noop-mode init behavior.
libs/components/code-examples/src/lib/modules/tabs/wizard/basic/modal.component.spec.ts Replace NoopAnimationsModule with provider-based noop for Angular + SKY UX animations.
libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/mixed/example.component.spec.ts Update example tests to disable SKY UX CSS transitions via provider.
libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/grouped/example.component.spec.ts Update example tests to disable SKY UX CSS transitions via provider.
libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/basic/example.component.spec.ts Update example tests to disable SKY UX CSS transitions via provider.
libs/components/code-examples/src/lib/modules/tabs/sectioned-form/modal/example.component.spec.ts Update example tests to disable SKY UX CSS transitions via provider.
apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.spec.ts Update integration test to disable SKY UX CSS transitions via provider.

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

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

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

Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.

@Blackbaud-SteveBrush Blackbaud-SteveBrush marked this pull request as ready for review March 16, 2026 16:33
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: 2

🧹 Nitpick comments (1)
libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.html (1)

22-25: Replace ngClass with explicit class bindings in this touched template block.

The newly updated block still uses ngClass, which conflicts with the template guideline and can be converted directly to class bindings.

♻️ Proposed refactor
   `@if` (maintainSectionContent || tabService.tabsVisible()) {
     <div
       class="sky-sectioned-form-tabs"
       [class.sky-animation-slide-enter-left]="animationEnabled()"
-      [ngClass]="{
-        'sky-sectioned-form-tabs-hidden': !tabService.tabsVisible(),
-        'sky-sectioned-form-tabs-only': !tabService.contentVisible()
-      }"
+      [class.sky-sectioned-form-tabs-hidden]="!tabService.tabsVisible()"
+      [class.sky-sectioned-form-tabs-only]="!tabService.contentVisible()"
     >
       <ng-content />
     </div>
   }
   `@if` (maintainSectionContent || tabService.contentVisible()) {
     <div
       `#skySectionSideContent`
       class="sky-sectioned-form-content"
       [class.sky-animation-slide-enter-right]="animationEnabled()"
-      [ngClass]="{
-        'sky-sectioned-form-content-hidden': !tabService.contentVisible()
-      }"
+      [class.sky-sectioned-form-content-hidden]="!tabService.contentVisible()"
     ></div>
   }

As per coding guidelines: **/*.component.html: Do NOT use ngClass; use class bindings instead in Angular templates.

Also applies to: 35-37

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

In
`@libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.html`
around lines 22 - 25, The template is using ngClass for conditional classes
which violates the component HTML guideline; replace the ngClass usage with
explicit class bindings: bind the 'sky-sectioned-form-tabs-hidden' class to the
inverse of tabService.tabsVisible() and bind the 'sky-sectioned-form-tabs-only'
class to the inverse of tabService.contentVisible(), and apply the same
replacement for the other touched block that uses ngClass (the block referencing
tabService.contentVisible()/tabService.tabsVisible()). Ensure you remove the
ngClass attribute and add the corresponding explicit class bindings on the same
element.
🤖 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/code-examples/src/lib/modules/tabs/wizard/basic/modal.component.spec.ts`:
- Line 4: Remove the redundant NoopAnimationsModule import and its inclusion in
the TestBed imports, and rely solely on provideNoopSkyAnimations() in the
TestBed providers; specifically delete the "import { NoopAnimationsModule } ..."
line and remove NoopAnimationsModule from the TestBed.configureTestingModule({
imports: [...] }) array while keeping provideNoopSkyAnimations() in providers so
the test follows the migration pattern.

In
`@libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.component.html`:
- Line 33: The template uses [ngClass] to toggle single classes; replace those
with direct class bindings: change the [ngClass] that adds
'sky-vertical-tabset-hidden' based on tabService.tabsVisible() to a class
binding [class.sky-vertical-tabset-hidden]="!tabService.tabsVisible()", and
change the [ngClass] that toggles 'sky-vertical-tabset-content-hidden' based on
tabService.contentVisible() to
[class.sky-vertical-tabset-content-hidden]="!tabService.contentVisible()";
update the occurrences in vertical-tabset template where
tabService.tabsVisible() and tabService.contentVisible() are used (replace the
ngClass attributes with the corresponding [class.*] bindings).

---

Nitpick comments:
In
`@libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.html`:
- Around line 22-25: The template is using ngClass for conditional classes which
violates the component HTML guideline; replace the ngClass usage with explicit
class bindings: bind the 'sky-sectioned-form-tabs-hidden' class to the inverse
of tabService.tabsVisible() and bind the 'sky-sectioned-form-tabs-only' class to
the inverse of tabService.contentVisible(), and apply the same replacement for
the other touched block that uses ngClass (the block referencing
tabService.contentVisible()/tabService.tabsVisible()). Ensure you remove the
ngClass attribute and add the corresponding explicit class bindings on the same
element.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9bf7559-c040-43ac-9591-d4f3b8158a7b

📥 Commits

Reviewing files that changed from the base of the PR and between 3b9cd2d and 7b55b2c.

📒 Files selected for processing (20)
  • apps/integration/src/app/integrations/vertical-tabset-back-to-top/vertical-tabset-back-to-top.component.spec.ts
  • libs/components/code-examples/src/lib/modules/tabs/sectioned-form/modal/example.component.spec.ts
  • libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/basic/example.component.spec.ts
  • libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/grouped/example.component.spec.ts
  • libs/components/code-examples/src/lib/modules/tabs/vertical-tabs/mixed/example.component.spec.ts
  • libs/components/code-examples/src/lib/modules/tabs/wizard/basic/modal.component.spec.ts
  • libs/components/docs-tools/src/lib/modules/code-example-viewer/code-example-viewer.component.spec.ts
  • libs/components/tabs/package.json
  • libs/components/tabs/src/lib/modules/sectioned-form/fixtures/sectioned-form-fixtures.module.ts
  • libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.html
  • libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.spec.ts
  • libs/components/tabs/src/lib/modules/sectioned-form/sectioned-form.component.ts
  • libs/components/tabs/src/lib/modules/vertical-tabset/fixtures/vertical-tabs-fixtures.module.ts
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.component.html
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.component.ts
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.module.ts
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.service.spec.ts
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.service.ts
  • libs/components/tabs/testing/src/modules/sectioned-form/sectioned-form-harness.spec.ts
  • libs/components/tabs/testing/src/modules/vertical-tabset/vertical-tabset-harness.spec.ts
💤 Files with no reviewable changes (2)
  • libs/components/tabs/package.json
  • libs/components/tabs/src/lib/modules/vertical-tabset/vertical-tabset.service.ts

@Blackbaud-SteveBrush Blackbaud-SteveBrush enabled auto-merge (squash) March 17, 2026 12:39
@Blackbaud-SteveBrush Blackbaud-SteveBrush merged commit 90b183b into main Mar 17, 2026
36 checks passed
@Blackbaud-SteveBrush Blackbaud-SteveBrush deleted the tabs-refactor-animations branch March 17, 2026 12:53
johnhwhite pushed a commit that referenced this pull request Mar 17, 2026
##
[14.0.0-alpha.9](14.0.0-alpha.8...14.0.0-alpha.9)
(2026-03-17)


### ⚠ BREAKING CHANGES

* **components/indicators:** replace `@angular/animations` in tokens
component with CSS transitions (#4303)
* **components/tabs:** replace `@angular/animations` with CSS
transitions (#4288)
* **components/flyout:** replace `@angular/animations` with CSS
transitions (#4285)

### Features

* **components/lists:** deprecate filter summary
([#4307](#4307))
([b5567d9](b5567d9)),
closes
[AB#3611503](https://dev.azure.com/blackbaud/Products/_workitems/edit/3611503)
* **components/modals:** add modal banner
([#4275](#4275))
([#4280](#4280))
([b186fc2](b186fc2))


### Bug Fixes

* **components/core:** transition handler emits via microtask when
animations disabled
([#4304](#4304))
([3b9cd2d](3b9cd2d))
* **components/data-manager:** address data mutation during view updates
([#4309](#4309))
([#4311](#4311))
([6cadb59](6cadb59)),
closes
[AB#3705639](https://dev.azure.com/blackbaud/Products/_workitems/edit/3705639)
* **components/flyout:** replace `@angular/animations` with CSS
transitions ([#4285](#4285))
([96aa341](96aa341))
* **components/indicators:** replace `@angular/animations` in tokens
component with CSS transitions
([#4303](#4303))
([bcb9d88](bcb9d88))
* **components/tabs:** replace `@angular/animations` with CSS
transitions ([#4288](#4288))
([90b183b](90b183b))

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

## Summary by CodeRabbit

* **Breaking Changes**
* Indicators, tabs, and flyout components now use CSS transitions
instead of animations.

* **New Features**
  * Added modal banner component.

* **Deprecations**
  * Filter summary in list components deprecated.

* **Bug Fixes**
* Animation behavior when disabled, data handling during updates, and
transition styling improvements.

<!-- 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