mirror of
https://github.com/material-components/material-web.git
synced 2026-03-09 00:09:23 +08:00
- Rename `ariaLabelOn` to `ariaLabelSelected` - Merge `arialLabelOff` into `ariaLabel` - `onIcon` slot is now `selectedIcon` - `offIcon` slot is now a default slot - IconButtonToggle now extends IconButton PiperOrigin-RevId: 501414360
122 lines
3.5 KiB
TypeScript
122 lines
3.5 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2018 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
// This is required for @ariaProperty
|
|
// tslint:disable:no-new-decorators
|
|
|
|
import '../../focus/focus-ring.js';
|
|
import '../../icon/icon.js';
|
|
import '../../ripple/ripple.js';
|
|
|
|
import {html, LitElement, TemplateResult} from 'lit';
|
|
import {property, query, queryAsync, state} from 'lit/decorators.js';
|
|
import {ClassInfo, classMap} from 'lit/directives/class-map.js';
|
|
import {ifDefined} from 'lit/directives/if-defined.js';
|
|
import {when} from 'lit/directives/when.js';
|
|
|
|
import {isRtl} from '../../controller/is-rtl.js';
|
|
import {ariaProperty} from '../../decorators/aria-property.js';
|
|
import {pointerPress, shouldShowStrongFocus} from '../../focus/strong-focus.js';
|
|
import {ripple} from '../../ripple/directive.js';
|
|
import {MdRipple} from '../../ripple/ripple.js';
|
|
import {ARIAHasPopup} from '../../types/aria.js';
|
|
|
|
// tslint:disable-next-line:enforce-comments-on-exported-symbols
|
|
export class IconButton extends LitElement {
|
|
/**
|
|
* Disables the icon button and makes it non-interactive.
|
|
*/
|
|
@property({type: Boolean, reflect: true}) disabled = false;
|
|
|
|
/**
|
|
* Flips the icon if it is in an RTL context at startup.
|
|
*/
|
|
@property({type: Boolean}) flipIconInRtl = false;
|
|
|
|
@state() protected flipIcon: boolean = isRtl(this, this.flipIconInRtl);
|
|
|
|
@ariaProperty
|
|
@property({type: String, attribute: 'data-aria-label'})
|
|
override ariaLabel!: string;
|
|
|
|
@ariaProperty
|
|
@property({type: String, attribute: 'data-aria-haspopup'})
|
|
override ariaHasPopup!: ARIAHasPopup;
|
|
|
|
@query('button') protected buttonElement!: HTMLElement;
|
|
|
|
@queryAsync('md-ripple') protected ripple!: Promise<MdRipple|null>;
|
|
|
|
@state() protected showFocusRing = false;
|
|
|
|
@state() protected showRipple = false;
|
|
|
|
protected getRipple = () => {
|
|
this.showRipple = true;
|
|
return this.ripple;
|
|
};
|
|
|
|
protected readonly renderRipple = () => {
|
|
return html`<md-ripple ?disabled="${this.disabled}"></md-ripple>`;
|
|
};
|
|
|
|
protected override render(): TemplateResult {
|
|
return html`<button
|
|
class="md3-icon-button ${classMap(this.getRenderClasses())}"
|
|
aria-label="${ifDefined(this.ariaLabel)}"
|
|
aria-haspopup="${ifDefined(this.ariaHasPopup)}"
|
|
?disabled="${this.disabled}"
|
|
@focus="${this.handleFocus}"
|
|
@blur="${this.handleBlur}"
|
|
@pointerdown="${this.handlePointerDown}"
|
|
${ripple(this.getRipple)}>
|
|
${this.renderFocusRing()}
|
|
${when(this.showRipple, this.renderRipple)}
|
|
${this.renderIcon()}
|
|
${this.renderTouchTarget()}
|
|
</button>`;
|
|
}
|
|
|
|
protected getRenderClasses(): ClassInfo {
|
|
return {
|
|
'md3-icon-button--flip-icon': this.flipIcon,
|
|
};
|
|
}
|
|
|
|
protected renderIcon(): TemplateResult {
|
|
// Note, it's important not to render the icon property as a slot fallback
|
|
// to avoid any whitespace from overridding it.
|
|
return html`<md-icon class="md3-icon-button__icon"><slot></slot></md-icon>`;
|
|
}
|
|
|
|
protected renderTouchTarget(): TemplateResult {
|
|
return html`<span class="md3-icon-button__touch"></span>`;
|
|
}
|
|
|
|
protected renderFocusRing(): TemplateResult {
|
|
return html`<md-focus-ring .visible="${
|
|
this.showFocusRing}"></md-focus-ring>`;
|
|
}
|
|
|
|
override connectedCallback() {
|
|
this.flipIcon = isRtl(this, this.flipIconInRtl);
|
|
super.connectedCallback();
|
|
}
|
|
|
|
handlePointerDown() {
|
|
pointerPress();
|
|
this.showFocusRing = shouldShowStrongFocus();
|
|
}
|
|
|
|
protected handleFocus() {
|
|
this.showFocusRing = shouldShowStrongFocus();
|
|
}
|
|
|
|
protected handleBlur() {
|
|
this.showFocusRing = false;
|
|
}
|
|
}
|