Skip to content

Commit

Permalink
Revert "feat(material/tabs): add the ability to keep content inside t…
Browse files Browse the repository at this point in the history
…he DOM while off-screen (#20393)" (#24298)

This reverts commit c3188c8.
  • Loading branch information
crisbeto authored Jan 27, 2022
1 parent c3188c8 commit 816099e
Show file tree
Hide file tree
Showing 15 changed files with 11 additions and 221 deletions.
3 changes: 0 additions & 3 deletions src/components-examples/material/tabs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {TabGroupHarnessExample} from './tab-group-harness/tab-group-harness-exam
import {TabGroupDynamicExample} from './tab-group-dynamic/tab-group-dynamic-example';
import {TabGroupHeaderBelowExample} from './tab-group-header-below/tab-group-header-below-example';
import {TabGroupLazyLoadedExample} from './tab-group-lazy-loaded/tab-group-lazy-loaded-example';
import {TabGroupPreserveContentExample} from './tab-group-preserve-content/tab-group-preserve-content-example';
import {TabGroupStretchedExample} from './tab-group-stretched/tab-group-stretched-example';
import {TabGroupThemeExample} from './tab-group-theme/tab-group-theme-example';
import {TabNavBarBasicExample} from './tab-nav-bar-basic/tab-nav-bar-basic-example';
Expand All @@ -38,7 +37,6 @@ export {
TabGroupThemeExample,
TabNavBarBasicExample,
TabNavBarWithPanelExample,
TabGroupPreserveContentExample,
};

const EXAMPLES = [
Expand All @@ -56,7 +54,6 @@ const EXAMPLES = [
TabGroupThemeExample,
TabNavBarBasicExample,
TabNavBarWithPanelExample,
TabGroupPreserveContentExample,
];

@NgModule({
Expand Down

This file was deleted.

This file was deleted.

11 changes: 0 additions & 11 deletions src/material-experimental/mdc-tabs/tab-body.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,6 @@
.mat-mdc-tab-group.mat-mdc-tab-group-dynamic-height &.mat-mdc-tab-body-active {
overflow-y: hidden;
}

// Usually the `visibility: hidden` added by the animation is enough to prevent focus from
// entering the collapsed content, but children with their own `visibility` can override it.
// This is a fallback that completely hides the content when the element becomes hidden.
// Note that we can't do this in the animation definition, because the style gets recomputed too
// late, breaking the animation because Angular didn't have time to figure out the target height.
// This can also be achieved with JS, but it has issues when when starting an animation before
// the previous one has finished.
&[style*='visibility: hidden'] {
display: none;
}
}

.mat-mdc-tab-body-content {
Expand Down
1 change: 0 additions & 1 deletion src/material-experimental/mdc-tabs/tab-group.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
[position]="tab.position!"
[origin]="tab.origin"
[animationDuration]="animationDuration"
[preserveContent]="preserveContent"
(_onCentered)="_removeTabBodyWrapperHeight()"
(_onCentering)="_setTabBodyWrapperHeight($event)">
</mat-tab-body>
Expand Down
53 changes: 1 addition & 52 deletions src/material-experimental/mdc-tabs/tab-group.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -666,56 +666,6 @@ describe('MDC-based MatTabGroup', () => {

expect(tabGroupNode.classList).toContain('mat-mdc-tab-group-inverted-header');
});

it('should be able to opt into keeping the inactive tab content in the DOM', fakeAsync(() => {
fixture.componentInstance.preserveContent = true;
fixture.detectChanges();

expect(fixture.nativeElement.textContent).toContain('Pizza, fries');
expect(fixture.nativeElement.textContent).not.toContain('Peanuts');

tabGroup.selectedIndex = 3;
fixture.detectChanges();
tick();

expect(fixture.nativeElement.textContent).toContain('Pizza, fries');
expect(fixture.nativeElement.textContent).toContain('Peanuts');
}));

it('should visibly hide the content of inactive tabs', fakeAsync(() => {
const contentElements: HTMLElement[] = Array.from(
fixture.nativeElement.querySelectorAll('.mat-mdc-tab-body-content'),
);

expect(contentElements.map(element => element.style.visibility)).toEqual([
'',
'hidden',
'hidden',
'hidden',
]);

tabGroup.selectedIndex = 2;
fixture.detectChanges();
tick();

expect(contentElements.map(element => element.style.visibility)).toEqual([
'hidden',
'hidden',
'',
'hidden',
]);

tabGroup.selectedIndex = 1;
fixture.detectChanges();
tick();

expect(contentElements.map(element => element.style.visibility)).toEqual([
'hidden',
'',
'hidden',
'hidden',
]);
}));
});

describe('lazy loaded tabs', () => {
Expand Down Expand Up @@ -1176,7 +1126,7 @@ class AsyncTabsTestApp implements OnInit {

@Component({
template: `
<mat-tab-group [preserveContent]="preserveContent">
<mat-tab-group>
<mat-tab label="Junk food"> Pizza, fries </mat-tab>
<mat-tab label="Vegetables"> Broccoli, spinach </mat-tab>
<mat-tab [label]="otherLabel"> {{otherContent}} </mat-tab>
Expand All @@ -1185,7 +1135,6 @@ class AsyncTabsTestApp implements OnInit {
`,
})
class TabGroupWithSimpleApi {
preserveContent = false;
otherLabel = 'Fruit';
otherContent = 'Apples, grapes';
@ViewChild('legumes') legumes: any;
Expand Down
11 changes: 0 additions & 11 deletions src/material/tabs/tab-body.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,4 @@
.mat-tab-group-dynamic-height & {
overflow: hidden;
}

// Usually the `visibility: hidden` added by the animation is enough to prevent focus from
// entering the collapsed content, but children with their own `visibility` can override it.
// This is a fallback that completely hides the content when the element becomes hidden.
// Note that we can't do this in the animation definition, because the style gets recomputed too
// late, breaking the animation because Angular didn't have time to figure out the target height.
// This can also be achieved with JS, but it has issues when when starting an animation before
// the previous one has finished.
&[style*='visibility: hidden'] {
display: none;
}
}
7 changes: 1 addition & 6 deletions src/material/tabs/tab-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ export class MatTabBodyPortal extends CdkPortalOutlet implements OnInit, OnDestr
});

this._leavingSub = this._host._afterLeavingCenter.subscribe(() => {
if (!this._host.preserveContent) {
this.detach();
}
this.detach();
});
}

Expand Down Expand Up @@ -151,9 +149,6 @@ export abstract class _MatTabBodyBase implements OnInit, OnDestroy {
/** Duration for the tab's animation. */
@Input() animationDuration: string = '500ms';

/** Whether the tab's content should be kept in the DOM while it's off-screen. */
@Input() preserveContent: boolean = false;

/** The shifted index position of the tab body, where zero represents the active center tab. */
@Input()
set position(position: number) {
Expand Down
7 changes: 0 additions & 7 deletions src/material/tabs/tab-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ export interface MatTabsConfig {

/** `tabindex` to be set on the inner element that wraps the tab content. */
contentTabIndex?: number;

/**
* By default tabs remove their content from the DOM while it's off-screen.
* Setting this to `true` will keep it in the DOM which will prevent elements
* like iframes and videos from reloading next time it comes back into the view.
*/
preserveContent?: boolean;
}

/** Injection token that can be used to provide the default options the tabs module. */
Expand Down
1 change: 0 additions & 1 deletion src/material/tabs/tab-group.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
[position]="tab.position!"
[origin]="tab.origin"
[animationDuration]="animationDuration"
[preserveContent]="preserveContent"
(_onCentered)="_removeTabBodyWrapperHeight()"
(_onCentering)="_setTabBodyWrapperHeight($event)">
</mat-tab-body>
Expand Down
53 changes: 1 addition & 52 deletions src/material/tabs/tab-group.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -665,56 +665,6 @@ describe('MatTabGroup', () => {

expect(tabGroupNode.classList).toContain('mat-tab-group-inverted-header');
});

it('should be able to opt into keeping the inactive tab content in the DOM', fakeAsync(() => {
fixture.componentInstance.preserveContent = true;
fixture.detectChanges();

expect(fixture.nativeElement.textContent).toContain('Pizza, fries');
expect(fixture.nativeElement.textContent).not.toContain('Peanuts');

tabGroup.selectedIndex = 3;
fixture.detectChanges();
tick();

expect(fixture.nativeElement.textContent).toContain('Pizza, fries');
expect(fixture.nativeElement.textContent).toContain('Peanuts');
}));

it('should visibly hide the content of inactive tabs', fakeAsync(() => {
const contentElements: HTMLElement[] = Array.from(
fixture.nativeElement.querySelectorAll('.mat-tab-body-content'),
);

expect(contentElements.map(element => element.style.visibility)).toEqual([
'',
'hidden',
'hidden',
'hidden',
]);

tabGroup.selectedIndex = 2;
fixture.detectChanges();
tick();

expect(contentElements.map(element => element.style.visibility)).toEqual([
'hidden',
'hidden',
'',
'hidden',
]);

tabGroup.selectedIndex = 1;
fixture.detectChanges();
tick();

expect(contentElements.map(element => element.style.visibility)).toEqual([
'hidden',
'',
'hidden',
'hidden',
]);
}));
});

describe('lazy loaded tabs', () => {
Expand Down Expand Up @@ -1122,7 +1072,7 @@ class AsyncTabsTestApp implements OnInit {

@Component({
template: `
<mat-tab-group [preserveContent]="preserveContent">
<mat-tab-group>
<mat-tab label="Junk food"> Pizza, fries </mat-tab>
<mat-tab label="Vegetables"> Broccoli, spinach </mat-tab>
<mat-tab [label]="otherLabel"> {{otherContent}} </mat-tab>
Expand All @@ -1131,7 +1081,6 @@ class AsyncTabsTestApp implements OnInit {
`,
})
class TabGroupWithSimpleApi {
preserveContent = false;
otherLabel = 'Fruit';
otherContent = 'Apples, grapes';
@ViewChild('legumes') legumes: any;
Expand Down
9 changes: 0 additions & 9 deletions src/material/tabs/tab-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,6 @@ export abstract class _MatTabGroupBase
@Input()
disablePagination: boolean;

/**
* By default tabs remove their content from the DOM while it's off-screen.
* Setting this to `true` will keep it in the DOM which will prevent elements
* like iframes and videos from reloading next time it comes back into the view.
*/
@Input()
preserveContent: boolean;

/** Background color of the tab group. */
@Input()
get backgroundColor(): ThemePalette {
Expand Down Expand Up @@ -222,7 +214,6 @@ export abstract class _MatTabGroupBase
this.dynamicHeight =
defaultConfig && defaultConfig.dynamicHeight != null ? defaultConfig.dynamicHeight : false;
this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;
this.preserveContent = !!defaultConfig?.preserveContent;
}

/**
Expand Down
36 changes: 6 additions & 30 deletions src/material/tabs/tabs-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,26 @@ export const matTabsAnimations: {
} = {
/** Animation translates a tab along the X axis. */
translateTab: trigger('translateTab', [
state(
'center, void, left-origin-center, right-origin-center',
style({
// Transitions to `none` instead of 0, because some browsers might blur the content.
transform: 'none',
// Ensures that the `visibility: hidden` from below is cleared.
visibility: '',
}),
),
// Note: transitions to `none` instead of 0, because some browsers might blur the content.
state('center, void, left-origin-center, right-origin-center', style({transform: 'none'})),

// If the tab is either on the left or right, we additionally add a `min-height` of 1px
// in order to ensure that the element has a height before its state changes. This is
// necessary because Chrome does seem to skip the transition in RTL mode if the element does
// not have a static height and is not rendered. See related issue: #9465
state(
'left',
style({
transform: 'translate3d(-100%, 0, 0)',
minHeight: '1px',

// Normally this is redundant since we detach the content from the DOM, but if the user
// opted into keeping the content in the DOM, we have to hide it so it isn't focusable.
visibility: 'hidden',
}),
),
state(
'right',
style({
transform: 'translate3d(100%, 0, 0)',
minHeight: '1px',
visibility: 'hidden',
}),
),
state('left', style({transform: 'translate3d(-100%, 0, 0)', minHeight: '1px'})),
state('right', style({transform: 'translate3d(100%, 0, 0)', minHeight: '1px'})),

transition(
'* => left, * => right, left => center, right => center',
animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),
),
transition('void => left-origin-center', [
style({transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden'}),
style({transform: 'translate3d(-100%, 0, 0)'}),
animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),
]),
transition('void => right-origin-center', [
style({transform: 'translate3d(100%, 0, 0)', visibility: 'hidden'}),
style({transform: 'translate3d(100%, 0, 0)'}),
animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),
]),
]),
Expand Down
9 changes: 0 additions & 9 deletions src/material/tabs/tabs.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,6 @@ duration can be configured globally using the `MAT_TABS_CONFIG` injection token.
"file": "tab-group-animations-example.html",
"region": "slow-animation-duration"}) -->

### Keeping the tab content inside the DOM while it's off-screen
By default the `<mat-tab-group>` will remove the content of off-screen tabs from the DOM until they
come into the view. This is optimal for most cases since it keeps the DOM size smaller, but it
isn't great for others like when a tab has an `<audio>` or `<video>` element, because the content
will be re-initialized whenever the user navigates to the tab. If you want to keep the content of
off-screen tabs in the DOM, you can set the `preserveContent` input to `true`.

<!-- example(tab-group-preserve-content) -->

### Accessibility
`MatTabGroup` and `MatTabNavBar` implement different interaction patterns for different use-cases.
You should choose the component that works best for your application.
Expand Down
Loading

0 comments on commit 816099e

Please sign in to comment.