mirror of
https://github.com/material-components/material-web.git
synced 2026-01-09 07:21:09 +08:00
Merge branch 'main' into main
This commit is contained in:
commit
a5b8a761b0
@ -28,8 +28,8 @@ Current browsers and versions supported:
|
||||
|
||||
Browser | Version
|
||||
------- | -------
|
||||
Chrome | 112 +
|
||||
Edge | 112 +
|
||||
Chrome | 120 +
|
||||
Edge | 120 +
|
||||
Firefox | 119 +
|
||||
Safari* | 16.4 +
|
||||
|
||||
|
||||
@ -324,17 +324,6 @@ $_md-sys-motion: tokens.md-sys-motion-values();
|
||||
inset-inline-start: var(--_focus-outline-width);
|
||||
}
|
||||
|
||||
// TODO(https://bugs.chromium.org/p/chromium/issues/detail?id=1420655):
|
||||
// remove :host and :host-context once Chrome supports :dir
|
||||
:host-context([dir='rtl']),
|
||||
:host([dir='rtl']) {
|
||||
.resizable .container {
|
||||
clip-path: inset(
|
||||
var(--_focus-outline-width) var(--_focus-outline-width) 0 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.resizable .container:dir(rtl) {
|
||||
clip-path: inset(
|
||||
var(--_focus-outline-width) var(--_focus-outline-width) 0 0
|
||||
|
||||
@ -40,14 +40,24 @@
|
||||
font-family: map.get($tokens, 'font');
|
||||
display: inline-flex;
|
||||
font-style: normal;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
line-height: 1;
|
||||
// Avoid displaying overflowing text if font ligatures have not loaded.
|
||||
overflow: hidden;
|
||||
// Changing the letter-spacing for WCAG text spacing compliance will shift
|
||||
// around font ligature icons, so we revert that to normal. Note: some a11y
|
||||
// tools use `!important` style injection and may see shifting icons. Actual
|
||||
// text spacing override implementations in projects should not set
|
||||
// `letter-spacing` on icons, or revert it with a `text-indent` of the same
|
||||
// size.
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
// Prevent icons from shrinking when placed in a flex container.
|
||||
flex-shrink: 0;
|
||||
|
||||
/* Support for all WebKit browsers. */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
@ -171,13 +171,6 @@ $_indeterminate-duration: 2s;
|
||||
calc($_indeterminate-duration * 2);
|
||||
}
|
||||
|
||||
// TODO(https://bugs.chromium.org/p/chromium/issues/detail?id=1420655):
|
||||
// remove :host and :host-context once Chrome supports :dir
|
||||
:host-context([dir='rtl']),
|
||||
:host([dir='rtl']) {
|
||||
transform: scale(-1);
|
||||
}
|
||||
|
||||
:host(:dir(rtl)) {
|
||||
transform: scale(-1);
|
||||
}
|
||||
|
||||
@ -201,11 +201,11 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
}
|
||||
|
||||
// rtl for active track clipping
|
||||
@include _get-rtl-selectors('.track', '::after') {
|
||||
.track:dir(rtl)::after {
|
||||
clip-path: inset(0 $_active-track-start-clip 0 $_active-track-end-clip);
|
||||
}
|
||||
|
||||
@include _get-rtl-selectors('.tickmarks', '::after') {
|
||||
.tickmarks:dir(rtl)::after {
|
||||
clip-path: inset(0 $_active-track-start-clip 0 $_active-track-end-clip);
|
||||
}
|
||||
|
||||
@ -440,7 +440,7 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
}
|
||||
|
||||
// in 'rtl', clip right side of "lesser" input
|
||||
@include _get-rtl-selectors('.ranged input.start') {
|
||||
.ranged input.start:dir(rtl) {
|
||||
clip-path: inset(0 0 0 $_clip-to-end);
|
||||
}
|
||||
|
||||
@ -450,7 +450,7 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
}
|
||||
|
||||
// in 'rtl', clip left side of "greater" input
|
||||
@include _get-rtl-selectors('.ranged input.end') {
|
||||
.ranged input.end:dir(rtl) {
|
||||
clip-path: inset(0 $_clip-to-start 0 0);
|
||||
}
|
||||
|
||||
@ -477,28 +477,6 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a mixin of rtl selectors to construct distinct rulesets. If `:dir` is
|
||||
// supported, then it will take precedence over `:host-context` via a `@supports
|
||||
// not selector(:dir(rtl))` at-rule. Seprating rulesets ensure they are not
|
||||
// dropped on browsers where one is not supported;
|
||||
// Note, `:where` cannot be used to create compound selectors that contain
|
||||
// pseudo elements
|
||||
// (e.g. this does not work: `:where(:host([dir="rtl"]) .foo::after)`),
|
||||
@mixin _get-rtl-selectors($selector: '', $suffix: '') {
|
||||
$host-context-selectors: ':host-context([dir="rtl"]) #{$selector}#{$suffix}, :host([dir="rtl"]) #{$selector}#{$suffix}';
|
||||
$dir-selector: '#{$selector}:dir(rtl)#{$suffix}';
|
||||
|
||||
@supports not selector(:dir(rtl)) {
|
||||
#{$host-context-selectors} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
#{$dir-selector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a background-image with sized circular ticks of the given color.
|
||||
@function _get-tick-image($color) {
|
||||
@return radial-gradient(
|
||||
@ -537,10 +515,7 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
transform: translateX(var(--_x-translate));
|
||||
}
|
||||
|
||||
@include _get-rtl-selectors(
|
||||
'input.#{$start-or-end}',
|
||||
'::-webkit-slider-thumb'
|
||||
) {
|
||||
input.#{$start-or-end}:dir(rtl)::-webkit-slider-thumb {
|
||||
transform: translateX(calc(-1 * var(--_x-translate)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,10 @@ export interface StoryKnobs {
|
||||
|
||||
const styles = css`
|
||||
[role='tabpanel']:not([hidden]) {
|
||||
font-family: Roboto, Material Sans, system-ui;
|
||||
font-family:
|
||||
Roboto,
|
||||
Material Sans,
|
||||
system-ui;
|
||||
}
|
||||
|
||||
[role='tabpanel']:not(.subtabs) {
|
||||
@ -56,7 +59,7 @@ const primary: MaterialStoryInit<StoryKnobs> = {
|
||||
return html`
|
||||
<md-tabs
|
||||
aria-label="Primary tabs"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}
|
||||
${setupTabPanels()}>
|
||||
<md-primary-tab
|
||||
@ -119,7 +122,7 @@ const secondary: MaterialStoryInit<StoryKnobs> = {
|
||||
return html`
|
||||
<md-tabs
|
||||
aria-label="Secondary tabs"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}
|
||||
${setupTabPanels()}>
|
||||
<md-secondary-tab id="tab-one" aria-controls="panel-one">
|
||||
@ -160,7 +163,7 @@ const scrolling: MaterialStoryInit<StoryKnobs> = {
|
||||
return html` <md-tabs
|
||||
aria-label="A tab bar that scrolls"
|
||||
class="scrolling"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}>
|
||||
${new Array(10).fill(html`
|
||||
<md-primary-tab .inlineIcon=${inlineIcon}>
|
||||
@ -212,7 +215,7 @@ const custom: MaterialStoryInit<StoryKnobs> = {
|
||||
<md-tabs
|
||||
aria-label="A custom themed tab bar"
|
||||
class="custom"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}>
|
||||
<md-primary-tab id="tab-one" aria-controls="panel-one">
|
||||
${tabContent('flight', 'Travel')}
|
||||
@ -252,7 +255,7 @@ const primaryAndSecondary: MaterialStoryInit<StoryKnobs> = {
|
||||
return html`
|
||||
<md-tabs
|
||||
aria-label="Primary tabs"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}
|
||||
${setupTabPanels()}>
|
||||
<md-primary-tab .inlineIcon=${inlineIcon} aria-controls="movies">
|
||||
@ -269,7 +272,7 @@ const primaryAndSecondary: MaterialStoryInit<StoryKnobs> = {
|
||||
<div role="tabpanel" id="movies" class="subtabs" aria-label="Movies">
|
||||
<md-tabs
|
||||
aria-label="Secondary tabs for movies"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}
|
||||
${setupTabPanels()}>
|
||||
<md-secondary-tab aria-controls="star-wars"
|
||||
@ -298,7 +301,7 @@ const primaryAndSecondary: MaterialStoryInit<StoryKnobs> = {
|
||||
hidden>
|
||||
<md-tabs
|
||||
aria-label="Secondary tabs for photos"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}>
|
||||
<md-secondary-tab aria-controls="yosemite">Yosemite</md-secondary-tab>
|
||||
<md-secondary-tab aria-controls="mona-lisa"
|
||||
@ -327,7 +330,7 @@ const primaryAndSecondary: MaterialStoryInit<StoryKnobs> = {
|
||||
<div role="tabpanel" id="music" class="subtabs" aria-label="Music" hidden>
|
||||
<md-tabs
|
||||
aria-label="Secondary tabs for music"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}
|
||||
${setupTabPanels()}>
|
||||
<md-secondary-tab aria-controls="rock">Rock</md-secondary-tab>
|
||||
@ -413,7 +416,7 @@ const dynamic: MaterialStoryInit<StoryKnobs> = {
|
||||
</div>
|
||||
<md-tabs
|
||||
class="scrolling"
|
||||
.activeTabIndex=${knobs.activeTabIndex}
|
||||
active-tab-index=${knobs.activeTabIndex}
|
||||
.autoActivate=${knobs.autoActivate}>
|
||||
<md-primary-tab .inlineIcon=${inlineIcon}> Tab 1 </md-primary-tab>
|
||||
<md-primary-tab .inlineIcon=${inlineIcon}> Tab 2 </md-primary-tab>
|
||||
|
||||
@ -63,6 +63,7 @@ export class Tabs extends LitElement {
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
@property({type: Number, attribute: 'active-tab-index'})
|
||||
get activeTabIndex() {
|
||||
return this.tabs.findIndex((tab) => tab.active);
|
||||
}
|
||||
|
||||
@ -129,7 +129,25 @@ describe('<md-tabs>', () => {
|
||||
await env.waitForStability();
|
||||
const tabs = root.querySelector('md-tabs')!;
|
||||
expect(tabs.activeTabIndex).withContext('activeTabIndex').toBe(1);
|
||||
expect(tabs.activeTab?.textContent).withContext('activeTab').toBe('B');
|
||||
expect(tabs.activeTab?.textContent)
|
||||
.withContext('activeTab')
|
||||
.toBe('B');
|
||||
});
|
||||
|
||||
it('should allow setting active-tab-index as an attribute', async () => {
|
||||
const root = env.render(html`
|
||||
<md-tabs active-tab-index=${1}>
|
||||
<md-primary-tab>A</md-primary-tab>
|
||||
<md-primary-tab>B</md-primary-tab>
|
||||
</md-tabs>
|
||||
`);
|
||||
|
||||
await env.waitForStability();
|
||||
const tabs = root.querySelector('md-tabs')!;
|
||||
expect(tabs.activeTabIndex).withContext('activeTabIndex').toBe(1);
|
||||
expect(tabs.activeTab?.textContent)
|
||||
.withContext('activeTab')
|
||||
.toBe('B');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user