Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
fb6a82f
split view
Blackbaud-SteveBrush Mar 11, 2026
02851dc
cleanup
Blackbaud-SteveBrush Mar 11, 2026
0a86e11
fix tests
Blackbaud-SteveBrush Mar 11, 2026
593c241
remove unused properties
Blackbaud-SteveBrush Mar 11, 2026
cd87445
fix formatting
Blackbaud-SteveBrush Mar 11, 2026
751407b
pr feedback
Blackbaud-SteveBrush Mar 11, 2026
e3eba3d
cleanup
Blackbaud-SteveBrush Mar 11, 2026
b61fc90
remove change
Blackbaud-SteveBrush Mar 11, 2026
118dc25
updates
Blackbaud-SteveBrush Mar 11, 2026
95a11fd
Merge remote-tracking branch 'origin/main' into drawer-animation
Blackbaud-SteveBrush Mar 11, 2026
70e8002
fix tests
Blackbaud-SteveBrush Mar 11, 2026
9cca839
tabs
Blackbaud-SteveBrush Mar 11, 2026
4af5da1
Merge remote-tracking branch 'origin/main' into tabs-refactor-animations
Blackbaud-SteveBrush Mar 12, 2026
8c46321
cleanup
Blackbaud-SteveBrush Mar 12, 2026
5d630e9
fix code examples
Blackbaud-SteveBrush Mar 12, 2026
774584d
fix tests
Blackbaud-SteveBrush Mar 12, 2026
fc2e9e3
cleanup
Blackbaud-SteveBrush Mar 12, 2026
4729a8b
cleanup
Blackbaud-SteveBrush Mar 12, 2026
a366db8
Merge remote-tracking branch 'origin/main' into tabs-refactor-animations
Blackbaud-SteveBrush Mar 12, 2026
71a2f0e
fix
Blackbaud-SteveBrush Mar 13, 2026
c376cb2
updates
Blackbaud-SteveBrush Mar 13, 2026
f3234a0
Merge remote-tracking branch 'origin/main' into tabs-refactor-animations
Blackbaud-SteveBrush Mar 16, 2026
5eca62c
cleanup
Blackbaud-SteveBrush Mar 16, 2026
8fa440e
works
Blackbaud-SteveBrush Mar 16, 2026
7b55b2c
cleanup
Blackbaud-SteveBrush Mar 16, 2026
836bf08
Merge branch 'main' into tabs-refactor-animations
Blackbaud-SteveBrush Mar 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { SkyAppTestUtility } from '@skyux-sdk/testing';
import { provideNoopSkyAnimations } from '@skyux/core';

import { VerticalTabsetBackToTopComponent } from './vertical-tabset-back-to-top.component';
import { VerticalTabsetBackToTopModule } from './vertical-tabset-back-to-top.module';
Expand Down Expand Up @@ -52,7 +52,8 @@ describe('Vertical tabset with a back to top', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule, VerticalTabsetBackToTopModule],
imports: [VerticalTabsetBackToTopModule],
providers: [provideNoopSkyAnimations()],
});

fixture = TestBed.createComponent(VerticalTabsetBackToTopComponent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyInputBoxHarness } from '@skyux/forms/testing';
import { SkySectionedFormHarness } from '@skyux/tabs/testing';

Expand All @@ -12,7 +12,8 @@ describe('Sectioned form in a modal example', () => {
fixture: ComponentFixture<TabsSectionedFormModalExampleComponent>;
}> {
await TestBed.configureTestingModule({
imports: [TabsSectionedFormModalExampleComponent, NoopAnimationsModule],
imports: [TabsSectionedFormModalExampleComponent],
providers: [provideNoopSkyAnimations()],
}).compileComponents();
const fixture = TestBed.createComponent(
TabsSectionedFormModalExampleComponent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyVerticalTabsetHarness } from '@skyux/tabs/testing';

import { TabsVerticalTabsBasicExampleComponent } from './example.component';
Expand All @@ -24,7 +24,8 @@ describe('Basic vertical tabs example', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [TabsVerticalTabsBasicExampleComponent, NoopAnimationsModule],
imports: [TabsVerticalTabsBasicExampleComponent],
providers: [provideNoopSkyAnimations()],
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyVerticalTabsetHarness } from '@skyux/tabs/testing';

import { TabsVerticalTabsGroupedExampleComponent } from './example.component';
Expand All @@ -24,7 +24,8 @@ describe('Group vertical tabs example', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [TabsVerticalTabsGroupedExampleComponent, NoopAnimationsModule],
imports: [TabsVerticalTabsGroupedExampleComponent],
providers: [provideNoopSkyAnimations()],
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyVerticalTabsetHarness } from '@skyux/tabs/testing';

import { TabsVerticalTabsMixedExampleComponent } from './example.component';
Expand All @@ -24,7 +24,8 @@ describe('Mixed vertical tabs example', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [TabsVerticalTabsMixedExampleComponent, NoopAnimationsModule],
imports: [TabsVerticalTabsMixedExampleComponent],
providers: [provideNoopSkyAnimations()],
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyInputBoxHarness } from '@skyux/forms/testing';
import { SkyModalInstance } from '@skyux/modals';
import {
Expand All @@ -19,7 +20,11 @@ describe('Wizard tabset demo', () => {
loader: HarnessLoader;
}> {
await TestBed.configureTestingModule({
providers: [provideRouter([]), SkyModalInstance],
providers: [
provideNoopSkyAnimations(),
provideRouter([]),
SkyModalInstance,
],
imports: [ModalComponent, NoopAnimationsModule],
}).compileComponents();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { expectAsync } from '@skyux-sdk/testing';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyBoxHarness } from '@skyux/layout/testing';

import { SkyDocsCodeExampleViewerComponent } from './code-example-viewer.component';
Expand Down Expand Up @@ -101,7 +101,8 @@ class FooExampleComponent {}`,
};

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

Expand Down
1 change: 0 additions & 1 deletion libs/components/tabs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
},
"homepage": "https://github.com/blackbaud/skyux#readme",
"peerDependencies": {
"@angular/animations": "^21.2.0",
"@angular/cdk": "^21.2.0",
"@angular/common": "^21.2.0",
"@angular/core": "^21.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';
import { SkyCheckboxModule } from '@skyux/forms';

import { SkySectionedFormModule } from '../sectioned-form.module';
Expand All @@ -19,18 +19,14 @@ import { SkySectionedFormFixtureComponent } from './sectioned-form.component.fix
SkySectionedFormNoSectionsFixtureComponent,
SkySectionedFormNoActiveFixtureComponent,
],
imports: [
NoopAnimationsModule,
SkySectionedFormModule,
SkyCheckboxModule,
FormsModule,
],
imports: [SkySectionedFormModule, SkyCheckboxModule, FormsModule],
exports: [
SkySectionedFormFixtureComponent,
SkySectionedFormFixtureInformation1Component,
SkySectionedFormFixtureInformation2Component,
SkySectionedFormNoSectionsFixtureComponent,
SkySectionedFormNoActiveFixtureComponent,
],
providers: [provideNoopSkyAnimations()],
})
export class SkySectionedFormFixturesModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
@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()
}"
[@tabEnter]="tabService.animationTabsVisibleState"
>
<ng-content />
</div>
Expand All @@ -31,10 +31,10 @@
<div
#skySectionSideContent
class="sky-sectioned-form-content"
[class.sky-animation-slide-enter-right]="animationEnabled()"
[ngClass]="{
'sky-sectioned-form-content-hidden': !tabService.contentVisible()
}"
[@contentEnter]="tabService.animationContentVisibleState"
></div>
}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,15 @@ describe('Sectioned form component', () => {
expect(indexChangedSpy.calls.count()).toEqual(1);
});

it('should have a visible animation state on load in mobile', () => {
it('should show content on load in mobile', () => {
mediaQueryController.setBreakpoint('xs');
const fixture = createTestComponent();
const el = fixture.nativeElement;

fixture.detectChanges();

expect(
fixture.componentInstance.sectionedForm?.tabService
.animationContentVisibleState,
).toBe('shown');
const content = getVisibleContent(el);
expect(content.length).toBe(1);
});

it('should hide content and show tabs on mobile after calling showTabs function', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { animate, style, transition, trigger } from '@angular/animations';
import {
AfterViewChecked,
ChangeDetectionStrategy,
Expand All @@ -11,6 +10,8 @@ import {
OnInit,
Output,
ViewChild,
afterNextRender,
signal,
} from '@angular/core';
import { SkyLogService } from '@skyux/core';

Expand All @@ -19,11 +20,7 @@ import { distinctUntilChanged, takeUntil } from 'rxjs/operators';

import { SkyTabIdService } from '../shared/tab-id.service';

import {
HIDDEN_STATE,
SkyVerticalTabsetService,
VISIBLE_STATE,
} from './../vertical-tabset/vertical-tabset.service';
import { SkyVerticalTabsetService } from './../vertical-tabset/vertical-tabset.service';
import { SkySectionedFormMessage } from './types/sectioned-form-message';
import { SkySectionedFormMessageType } from './types/sectioned-form-message-type';

Expand All @@ -36,20 +33,6 @@ import { SkySectionedFormMessageType } from './types/sectioned-form-message-type
styleUrls: ['./sectioned-form.component.scss'],
providers: [SkyTabIdService, SkyVerticalTabsetService],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('tabEnter', [
transition(`${HIDDEN_STATE} => ${VISIBLE_STATE}`, [
style({ transform: 'translate(-100%)' }),
animate('150ms ease-in'),
]),
]),
trigger('contentEnter', [
transition(`${HIDDEN_STATE} => ${VISIBLE_STATE}`, [
style({ transform: 'translate(100%)' }),
animate('150ms ease-in'),
]),
]),
],
standalone: false,
})
export class SkySectionedFormComponent
Expand Down Expand Up @@ -104,6 +87,8 @@ export class SkySectionedFormComponent

#_messageStream = new Subject<SkySectionedFormMessage>();

protected animationEnabled = signal(false);

constructor(
public tabService: SkyVerticalTabsetService,
changeRef: ChangeDetectorRef,
Expand All @@ -114,6 +99,11 @@ export class SkySectionedFormComponent
this.#tabIdSvc = tabIdSvc;
this.#logger = logger;

// Enable animations after the first render.
afterNextRender(() => {
this.animationEnabled.set(true);
});

this.#initMessageStream();

this.#tabIdSvc.ids.pipe(takeUntil(this.#ngUnsubscribe)).subscribe((ids) => {
Expand Down Expand Up @@ -158,7 +148,6 @@ export class SkySectionedFormComponent

if (this.tabService.isMobile()) {
this.ariaRole = undefined;
this.tabService.animationContentVisibleState = VISIBLE_STATE;
this.#changeRef.markForCheck();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { provideNoopSkyAnimations } from '@skyux/core';

import { SkyVerticalTabsetModule } from '../vertical-tabset.module';

Expand All @@ -21,10 +21,10 @@ import { VerticalTabsetTestComponent } from './vertical-tabset.component.fixture
],
imports: [
FormsModule,
NoopAnimationsModule,
SkyVerticalTabsetModule,
VerticalTabsetProgrammaticTestComponent,
],
providers: [provideNoopSkyAnimations()],
exports: [
VerticalTabsetTestComponent,
VerticalTabsetEmptyGroupTestComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,31 @@
"
[attr.role]="isMobile ? undefined : ariaRole"
></span>
@if (maintainTabContent || tabService.tabsVisible()) {
<div
#groupContainerWrapper
class="sky-vertical-tabset-group-container"
[@tabGroupEnter]="tabService.animationTabsVisibleState"
[ngClass]="{ 'sky-vertical-tabset-hidden': !tabService.tabsVisible() }"
[tabIndex]="tablistHasFocus ? -1 : 0"
(@tabGroupEnter.done)="tabsetFocus()"
(keydown.arrowDown)="tabGroupsArrowDown(); $event.preventDefault()"
(keydown.arrowUp)="tabGroupsArrowUp(); $event.preventDefault()"
(focusin)="trapFocusInTablist()"
(focusout)="resetTabIndex()"
>
<ng-content />
</div>
}
<div
#groupContainerWrapper
class="sky-vertical-tabset-group-container"
skyTransitionEndHandler
transitionPropertyToTrack="transform"
[class.sky-animation-slide-enter-left]="tabService.isMobile()"
[ngClass]="{ 'sky-vertical-tabset-hidden': !tabService.tabsVisible() }"
[tabIndex]="tablistHasFocus ? -1 : 0"
[transitionTrigger]="tabService.tabsVisible()"
(keydown.arrowDown)="tabGroupsArrowDown(); $event.preventDefault()"
(keydown.arrowUp)="tabGroupsArrowUp(); $event.preventDefault()"
(focusin)="trapFocusInTablist()"
(focusout)="resetTabIndex()"
(transitionEnd)="tabsetFocus()"
>
<ng-content />
</div>
@if (maintainTabContent || tabService.contentVisible()) {
<div
#contentContainerWrapper
class="sky-vertical-tabset-content"
[class.sky-animation-slide-enter-right]="tabService.isMobile()"
[ngClass]="{
'sky-vertical-tabset-content-hidden': !tabService.contentVisible()
}"
[@contentEnter]="tabService.animationContentVisibleState"
(focusin)="resetTabIndex()"
>
<div #skySideContent></div>
Expand Down
Loading
Loading