fix(tabs): remove previously selected tab property

PiperOrigin-RevId: 563797711
This commit is contained in:
Elizabeth Mitchell 2023-09-08 10:58:13 -07:00 committed by Copybara-Service
parent 2468241157
commit 70ce0d2779
3 changed files with 17 additions and 25 deletions

View File

@ -8,25 +8,25 @@ import '../../elevation/elevation.js';
import '../../focus/md-focus-ring.js';
import '../../ripple/ripple.js';
import {html, isServer, LitElement, nothing, PropertyValues} from 'lit';
import {html, isServer, LitElement, nothing} from 'lit';
import {property, query, queryAssignedElements, queryAssignedNodes, state} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {polyfillElementInternalsAria, setupHostAria} from '../../internal/aria/aria.js';
import {EASING} from '../../internal/motion/animation.js';
interface Tabs extends HTMLElement {
selected?: number;
selectedItem?: Tab;
previousSelectedItem?: Tab;
}
/**
* Symbol for tabs to use to animate their indicators based off another tab's
* indicator.
*/
const INDICATOR = Symbol('indicator');
/**
* Symbol used by the tab bar to request a tab to animate its indicator from a
* previously selected tab.
*/
export const ANIMATE_INDICATOR = Symbol('animateIndicator');
/**
* Tab component.
*/
@ -104,11 +104,8 @@ export class Tab extends LitElement {
};
}
protected override updated(changed: PropertyValues) {
if (changed.has('active')) {
this.internals.ariaSelected = String(this.active);
this.animateSelected();
}
protected override updated() {
this.internals.ariaSelected = String(this.active);
}
private async handleKeydown(event: KeyboardEvent) {
@ -125,7 +122,7 @@ export class Tab extends LitElement {
}
}
private animateSelected() {
[ANIMATE_INDICATOR](previousTab: Tab) {
if (!this[INDICATOR]) {
return;
}
@ -133,25 +130,22 @@ export class Tab extends LitElement {
this[INDICATOR].getAnimations().forEach(a => {
a.cancel();
});
const frames = this.getKeyframes();
const frames = this.getKeyframes(previousTab);
if (frames !== null) {
this[INDICATOR].animate(
frames, {duration: 250, easing: EASING.EMPHASIZED});
}
}
private getKeyframes() {
private getKeyframes(previousTab: Tab) {
const reduceMotion = shouldReduceMotion();
if (!this.active) {
return reduceMotion ? [{'opacity': 1}, {'transform': 'none'}] : null;
}
// TODO(b/298105040): avoid hardcoding selector
const tabs = this.closest<Tabs>('md-tabs');
const from: Keyframe = {};
const fromRect =
(tabs?.previousSelectedItem?.[INDICATOR]?.getBoundingClientRect() ??
({} as DOMRect));
previousTab[INDICATOR]?.getBoundingClientRect() ?? ({} as DOMRect);
const fromPos = fromRect.left;
const fromExtent = fromRect.width;
const toRect = this[INDICATOR]!.getBoundingClientRect();

View File

@ -11,7 +11,7 @@ import {property, queryAssignedElements, state} from 'lit/decorators.js';
import {polyfillElementInternalsAria, setupHostAria} from '../../internal/aria/aria.js';
import {Tab} from './tab.js';
import {ANIMATE_INDICATOR, Tab} from './tab.js';
const NAVIGATION_KEYS = new Map([
['default', new Set(['Home', 'End'])],
@ -85,7 +85,7 @@ export class Tabs extends LitElement {
/**
* The item previously selected.
*/
get previousSelectedItem() {
private get previousSelectedItem() {
return this.tabs[this.previousSelected];
}
@ -142,6 +142,7 @@ export class Tabs extends LitElement {
this.previousSelectedItem !== this.selectedItem) {
this.previousSelectedItem.active = false;
this.selectedItem.active = true;
this.selectedItem[ANIMATE_INDICATOR](this.previousSelectedItem);
}
if (this.selectedItem !== this.focusedItem) {
this.updateFocusableItem(this.selectedItem);

View File

@ -70,17 +70,14 @@ describe('<md-tabs>', () => {
});
});
it('updates selectedItem/previousSelectedItem', async () => {
it('updates selectedItem', async () => {
const {harness} = await setupTest({selected: 1});
expect(harness.element.selectedItem)
.toBe(harness.harnessedItems[1].element);
expect(harness.element.previousSelectedItem).toBeUndefined();
harness.element.selected = 0;
await harness.element.updateComplete;
expect(harness.element.selectedItem)
.toBe(harness.harnessedItems[0].element);
expect(harness.element.previousSelectedItem)
.toBe(harness.harnessedItems[1].element);
});
it('maintains selection when tabs are mutated', async () => {