mirror of
https://github.com/material-components/material-web.git
synced 2024-08-17 09:30:27 +03:00
fix(tabs): remove previously selected tab property
PiperOrigin-RevId: 563797711
This commit is contained in:
parent
2468241157
commit
70ce0d2779
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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 () => {
|
||||
|
Loading…
Reference in New Issue
Block a user