mirror of
https://github.com/material-components/material-web.git
synced 2024-09-17 16:48:02 +03:00
5df9410e60
BREAKING CHANGE: `querySelector` for `[role]` and `[aria-*]` attributes may no longer work. See `@material/web/migrations/v2/README.md` and `@material/web/migrations/v2/query-selector-aria.ts`. Browser/SR test results (go/mwc-double-aria-test-results) - ✅ VoiceOver on Chrome - ✅ VoiceOver on iOS Safari - ✅ TalkBack on Chrome - ✅ ChromeVox on Chrome - ✅ NVDA on Chrome - ✅ NVDA on Firefox - ✅ JAWS on Chrome - ✅ JAWS on Firefox (Optional) - ❓ VoiceOver on Safari - ❓ VoiceOver on Firefox PiperOrigin-RevId: 648859827
98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2023 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import '../../elevation/elevation.js';
|
|
import '../../focus/md-focus-ring.js';
|
|
import '../../ripple/ripple.js';
|
|
|
|
import {html, LitElement, nothing} from 'lit';
|
|
import {property} from 'lit/decorators.js';
|
|
import {classMap} from 'lit/directives/class-map.js';
|
|
|
|
import {ARIAMixinStrict} from '../../internal/aria/aria.js';
|
|
import {mixinDelegatesAria} from '../../internal/aria/delegate.js';
|
|
|
|
/**
|
|
* Sizes variants available to non-extended FABs.
|
|
*/
|
|
export type FabSize = 'medium' | 'small' | 'large';
|
|
|
|
// Separate variable needed for closure.
|
|
const fabBaseClass = mixinDelegatesAria(LitElement);
|
|
|
|
// tslint:disable-next-line:enforce-comments-on-exported-symbols
|
|
export abstract class SharedFab extends fabBaseClass {
|
|
/** @nocollapse */
|
|
static override shadowRootOptions: ShadowRootInit = {
|
|
mode: 'open' as const,
|
|
delegatesFocus: true,
|
|
};
|
|
|
|
/**
|
|
* The size of the FAB.
|
|
*
|
|
* NOTE: Branded FABs cannot be sized to `small`, and Extended FABs do not
|
|
* have different sizes.
|
|
*/
|
|
@property({reflect: true}) size: FabSize = 'medium';
|
|
|
|
/**
|
|
* The text to display on the FAB.
|
|
*/
|
|
@property() label = '';
|
|
|
|
/**
|
|
* Lowers the FAB's elevation.
|
|
*/
|
|
@property({type: Boolean}) lowered = false;
|
|
|
|
protected override render() {
|
|
// Needed for closure conformance
|
|
const {ariaLabel} = this as ARIAMixinStrict;
|
|
return html`
|
|
<button
|
|
class="fab ${classMap(this.getRenderClasses())}"
|
|
aria-label=${ariaLabel || nothing}>
|
|
<md-elevation part="elevation"></md-elevation>
|
|
<md-focus-ring part="focus-ring"></md-focus-ring>
|
|
<md-ripple class="ripple"></md-ripple>
|
|
${this.renderTouchTarget()} ${this.renderIcon()} ${this.renderLabel()}
|
|
</button>
|
|
`;
|
|
}
|
|
|
|
protected getRenderClasses() {
|
|
const isExtended = !!this.label;
|
|
return {
|
|
'lowered': this.lowered,
|
|
'small': this.size === 'small' && !isExtended,
|
|
'large': this.size === 'large' && !isExtended,
|
|
'extended': isExtended,
|
|
};
|
|
}
|
|
|
|
private renderTouchTarget() {
|
|
return html`<div class="touch-target"></div>`;
|
|
}
|
|
|
|
private renderLabel() {
|
|
return this.label ? html`<span class="label">${this.label}</span>` : '';
|
|
}
|
|
|
|
private renderIcon() {
|
|
const {ariaLabel} = this as ARIAMixinStrict;
|
|
return html`<span class="icon">
|
|
<slot
|
|
name="icon"
|
|
aria-hidden=${ariaLabel || this.label
|
|
? 'true'
|
|
: (nothing as unknown as 'false')}>
|
|
<span></span>
|
|
</slot>
|
|
</span>`;
|
|
}
|
|
}
|