Skip to content

Commit 6116c34

Browse files
fix(tabs): high contrast and reduced motion styling; improve tab marshaling
PiperOrigin-RevId: 532180388
1 parent 2317c5a commit 6116c34

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

tabs/lib/_tab.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,11 @@
286286
::slotted(*) {
287287
white-space: nowrap;
288288
}
289+
290+
@media (forced-colors: active) {
291+
:host,
292+
:host([variant]) {
293+
--_active-indicator-color: CanvasText;
294+
}
295+
}
289296
}

tabs/lib/tab.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ export class Tab extends LitElement {
145145
};
146146

147147
private shouldAnimate() {
148-
return this.canAnimate && !this.disabled &&
149-
!window.matchMedia('(prefers-reduced-motion: reduce)').matches;
148+
return this.canAnimate && !this.disabled;
150149
}
151150

152151
private readonly getRipple = () => {
@@ -173,8 +172,9 @@ export class Tab extends LitElement {
173172
}
174173

175174
private getKeyframes() {
175+
const reduceMotion = shouldReduceMotion();
176176
if (!this.selected) {
177-
return null;
177+
return reduceMotion ? [{'opacity': 1}, {'transform': 'none'}] : null;
178178
}
179179
const from: Keyframe = {};
180180
const isVertical = this.variant.includes('vertical');
@@ -189,7 +189,8 @@ export class Tab extends LitElement {
189189
const toExtent = isVertical ? toRect.height : toRect.width;
190190
const axis = isVertical ? 'Y' : 'X';
191191
const scale = fromExtent / toExtent;
192-
if (fromPos !== undefined && toPos !== undefined && !isNaN(scale)) {
192+
if (!reduceMotion && fromPos !== undefined && toPos !== undefined &&
193+
!isNaN(scale)) {
193194
from['transform'] = `translate${axis}(${
194195
(fromPos - toPos).toFixed(4)}px) scale${axis}(${scale.toFixed(4)})`;
195196
} else {
@@ -200,3 +201,7 @@ export class Tab extends LitElement {
200201
return [from, {'transform': 'none'}];
201202
}
202203
}
204+
205+
function shouldReduceMotion() {
206+
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
207+
}

tabs/lib/tabs.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@
55
*/
66

77
import {html, isServer, LitElement, PropertyValues} from 'lit';
8-
import {property, state} from 'lit/decorators.js';
8+
import {property, query} from 'lit/decorators.js';
99

10-
import {Variant} from './tab.js';
11-
12-
/**
13-
* Type for list items.
14-
*/
15-
export interface Tab extends HTMLElement {
16-
disabled?: boolean;
17-
selected?: boolean;
18-
variant?: string;
19-
}
10+
import {Tab, Variant} from './tab.js';
2011

2112
const NAVIGATION_KEYS = new Map([
2213
['default', new Set(['Home', 'End', 'Space'])],
@@ -76,11 +67,15 @@ export class Tabs extends LitElement {
7667
*/
7768
@property({type: Boolean}) selectOnFocus = false;
7869

70+
@query('slot') private readonly itemsSlot?: HTMLSlotElement;
71+
7972
private previousSelected = -1;
8073
private orientation = 'horizontal';
8174
private readonly scrollMargin = 48;
82-
// note, populated via slotchange.
83-
@state() private items: Tab[] = [];
75+
76+
private get items() {
77+
return this.itemsSlot?.assignedElements({flatten: true}) as Tab[] ?? [];
78+
}
8479

8580
private readonly selectedAttribute = `selected`;
8681

@@ -298,9 +293,7 @@ export class Tabs extends LitElement {
298293
}
299294

300295
private handleSlotChange(e: Event) {
301-
this.items =
302-
(e.target as HTMLSlotElement).assignedElements({flatten: true}) as
303-
Tab[];
296+
this.requestUpdate();
304297
}
305298

306299
// ensures the given item is visible in view; defaults to the selected item

0 commit comments

Comments
 (0)