Skip to content

Commit

Permalink
refactor(iconbutton)!: normalize toggle variant API with regular icon…
Browse files Browse the repository at this point in the history
… button

- 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
  • Loading branch information
dfreedm authored and copybara-github committed Jan 12, 2023
1 parent 36f1a1a commit 31391eb
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 71 deletions.
4 changes: 2 additions & 2 deletions iconbutton/icon-button_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ describe('icon button tests', () => {
throw new Error(
'Icon button is not instance of MdStandardIconButtonToggle.');
}
element.ariaLabelOn = 'aria label on';
element.ariaLabelOff = 'aria label off';
element.ariaLabelSelected = 'aria label on';
element.ariaLabel = 'aria label off';
await element.updateComplete;

const button = element.shadowRoot!.querySelector('button')!;
Expand Down
86 changes: 17 additions & 69 deletions iconbutton/lib/icon-button-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,24 @@ import '../../focus/focus-ring.js';
import '../../icon/icon.js';
import '../../ripple/ripple.js';

import {html, LitElement, nothing, TemplateResult} from 'lit';
import {property, queryAsync, state} from 'lit/decorators.js';
import {html, nothing, TemplateResult} from 'lit';
import {property} from 'lit/decorators.js';
import {ClassInfo, classMap} from 'lit/directives/class-map.js';
import {when} from 'lit/directives/when.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 {IconButton} from './icon-button.js';

/**
* @fires icon-button-toggle-change {CustomEvent<{selected: boolean}>}
* Dispatched whenever `selected` is changed via user click
*/
export class IconButtonToggle extends LitElement {
@ariaProperty
@property({type: String, attribute: 'data-aria-label'})
override ariaLabel!: string;

/**
* Disables the icon button and makes it non-interactive.
*/
@property({type: Boolean, reflect: true}) disabled = false;

export class IconButtonToggle extends IconButton {
/**
* The `aria-label` of the button when the toggle button is selected or "on".
*/
@property({type: String}) ariaLabelOn!: string;

/**
* The `aria-label` of the button when the toggle button is not selected or
* "off".
*/
@property({type: String}) ariaLabelOff!: string;
@property({type: String}) ariaLabelSelected!: string;

/**
* Sets the toggle button to the "on" state and displays the `onIcon`. If
Expand All @@ -53,26 +37,11 @@ export class IconButtonToggle extends LitElement {
*/
@property({type: Boolean, reflect: true}) selected = false;

@queryAsync('md-ripple') ripple!: Promise<MdRipple|null>;

@state() protected showFocusRing = false;

@state() protected showRipple = false;

protected readonly getRipple = () => {
this.showRipple = true;
return this.ripple;
};

protected readonly renderRipple = () => {
return html`<md-ripple ?disabled="${this.disabled}"></md-ripple>`;
};

protected override render(): TemplateResult {
const hasToggledAriaLabel = this.ariaLabelOn && this.ariaLabelOff;
const hasToggledAriaLabel = this.ariaLabel && this.ariaLabelSelected;
const ariaPressedValue = hasToggledAriaLabel ? nothing : this.selected;
const ariaLabelValue = hasToggledAriaLabel ?
(this.selected ? this.ariaLabelOn : this.ariaLabelOff) :
const ariaLabelValue = (hasToggledAriaLabel && this.selected) ?
this.ariaLabelSelected :
this.ariaLabel;
return html`<button
class="md3-icon-button ${classMap(this.getRenderClasses())}"
Expand All @@ -87,43 +56,22 @@ export class IconButtonToggle extends LitElement {
${this.renderFocusRing()}
${when(this.showRipple, this.renderRipple)}
${this.renderTouchTarget()}
<md-icon class="md3-icon-button__icon">
<slot name="offIcon"></slot>
</md-icon>
<md-icon class="md3-icon-button__icon md3-icon-button__icon--on">
<slot name="onIcon"></slot>
</md-icon>
${this.renderIcon()}
${this.renderSelectedIcon()}
</button>`;
}

protected getRenderClasses(): ClassInfo {
protected renderSelectedIcon() {
return html`<md-icon class="md3-icon-button__icon md3-icon-button__icon--on"><slot name="selectedIcon"></slot></md-icon>`;
}

protected override getRenderClasses(): ClassInfo {
return {
...super.getRenderClasses(),
'md3-icon-button--on': this.selected,
};
}

protected renderTouchTarget() {
return html`<span class="md3-icon-button__touch"></span>`;
}

protected renderFocusRing() {
return html`<md-focus-ring .visible="${
this.showFocusRing}"></md-focus-ring>`;
}

protected handlePointerDown(e: PointerEvent) {
pointerPress();
this.showFocusRing = shouldShowStrongFocus();
}

protected handleFocus() {
this.showFocusRing = shouldShowStrongFocus();
}

protected handleBlur() {
this.showFocusRing = false;
}

protected handleClick() {
this.selected = !this.selected;
const detail = {selected: this.selected};
Expand Down
3 changes: 3 additions & 0 deletions iconbutton/lib/icon-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ 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;

/**
Expand Down

0 comments on commit 31391eb

Please sign in to comment.