Skip to content

Commit

Permalink
refactor(iconbutton)!: Make a few API improvements
Browse files Browse the repository at this point in the history
- `selectedIcon` is now optional, will fallback to default slot icon
- `icon-button-toggle-change` removed for `change` and `input` events

PiperOrigin-RevId: 502997869
  • Loading branch information
dfreedm authored and copybara-github committed Jan 18, 2023
1 parent c43ab91 commit c72e7fd
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 32 deletions.
18 changes: 18 additions & 0 deletions iconbutton/icon-button_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ describe('icon button tests', () => {
expect(element.selected).toBeFalse();
});

it('fires input and change events when clicked', async () => {
const {element, harness} =
await setUpTest('md-standard-icon-button-toggle');
if (!(element instanceof MdStandardIconButtonToggle)) {
throw new Error(
'Icon button is not instance of MdStandardIconButtonToggle.');
}
let changeEvent = false;
let inputEvent = false;
element.addEventListener('input', () => inputEvent = true);
element.addEventListener('change', () => changeEvent = true);
expect(element.selected).toBeFalse();
await harness.clickWithMouse();
expect(element.selected).toBeTrue();
expect(inputEvent).toBeTrue();
expect(changeEvent).toBeTrue();
});

it('setting `selected` updates the aria-pressed attribute on the native button element',
async () => {
const {element} = await setUpTest('md-standard-icon-button-toggle');
Expand Down
2 changes: 1 addition & 1 deletion iconbutton/lib/_filled-icon-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ $_custom-property-prefix: 'filled-icon-button';
);
}

.md3-icon-button--on {
.md3-icon-button--selected {
&:not(:disabled) {
background-color: var(--_selected-container-color);
color: var(--_toggle-selected-icon-color);
Expand Down
2 changes: 1 addition & 1 deletion iconbutton/lib/_filled-tonal-icon-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ $_custom-property-prefix: 'filled-tonal-icon-button';
);
}

.md3-icon-button--on {
.md3-icon-button--selected {
&:not(:disabled) {
background-color: var(--_selected-container-color);
color: var(--_toggle-selected-icon-color);
Expand Down
6 changes: 3 additions & 3 deletions iconbutton/lib/_outlined-icon-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ $_custom-property-prefix: 'outlined-icon-button';
}

// Selected toggle buttons have no outline.
.md3-icon-button--outlined.md3-icon-button--on::before {
.md3-icon-button--outlined.md3-icon-button--selected::before {
border-width: 0;
}

// Selected icon button toggle.
.md3-icon-button--on {
.md3-icon-button--selected {
&:not(:disabled) {
background-color: var(--_selected-container-color);
color: var(--_selected-icon-color);
Expand Down Expand Up @@ -148,7 +148,7 @@ $_custom-property-prefix: 'outlined-icon-button';

@media (forced-colors: active) {
// Selected button in HCM has an outline.
.md3-icon-button--on {
.md3-icon-button--selected {
&::before {
border-color: var(--_unselected-outline-color);
border-width: var(--_unselected-outline-width);
Expand Down
14 changes: 0 additions & 14 deletions iconbutton/lib/_shared.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,6 @@

.md3-icon-button__icon {
display: inline-flex;

&.md3-icon-button__icon--on {
display: none;
}
}

.md3-icon-button--on {
.md3-icon-button__icon {
display: none;

&.md3-icon-button__icon--on {
display: inline-flex;
}
}
}

.md3-icon-button__link {
Expand Down
2 changes: 1 addition & 1 deletion iconbutton/lib/_standard-icon-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ $_custom-property-prefix: 'icon-button';
}
}

.md3-icon-button--on {
.md3-icon-button--selected {
&:not(:disabled) {
color: var(--_selected-icon-color);

Expand Down
34 changes: 22 additions & 12 deletions iconbutton/lib/icon-button-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,22 @@ import {ripple} from '../../ripple/directive.js';
import {IconButton} from './icon-button.js';

/**
* @fires icon-button-toggle-change {CustomEvent<{selected: boolean}>}
* @fires change {Event}
* Dispatched whenever `selected` is changed via user click
*
* @fires input {InputEvent}
* Dispatched whenever `selected` is changed via user click
*/
export class IconButtonToggle extends IconButton {
/**
* The `aria-label` of the button when the toggle button is selected or "on".
* The `aria-label` of the button when the toggle button is selected.
*/
@property({type: String}) ariaLabelSelected!: string;

/**
* Sets the toggle button to the "on" state and displays the `onIcon`. If
* false, sets the toggle button to the "off" state and displays the
* `offIcon`.
* Sets the selected state. When false, displays the default icon. When true,
* displays the `selectedIcon`, or the default icon If no `selectedIcon` is
* provided.
*/
@property({type: Boolean, reflect: true}) selected = false;

Expand All @@ -56,26 +59,33 @@ export class IconButtonToggle extends IconButton {
${this.renderFocusRing()}
${when(this.showRipple, this.renderRipple)}
${this.renderTouchTarget()}
${this.renderIcon()}
${this.renderSelectedIcon()}
${!this.selected ? this.renderIcon() : nothing}
${this.selected ? this.renderSelectedIcon() : nothing}
</button>`;
}

protected renderSelectedIcon() {
return html`<md-icon class="md3-icon-button__icon md3-icon-button__icon--on"><slot name="selectedIcon"></slot></md-icon>`;
// Use default slot as fallback to not require specifying multiple icons
return html`<md-icon class="md3-icon-button__icon md3-icon-button__icon--selected"><slot name="selectedIcon"><slot></slot></slot></md-icon>`;
}

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

protected handleClick() {
if (this.disabled) {
return;
}

this.selected = !this.selected;
const detail = {selected: this.selected};
this.dispatchEvent(new CustomEvent(
'icon-button-toggle-change', {detail, bubbles: true, composed: true}));
this.dispatchEvent(
new InputEvent('input', {bubbles: true, composed: true}));
// Bubbles but does not compose to mimic native browser <input> & <select>
// Additionally, native change event is not an InputEvent.
this.dispatchEvent(new Event('change', {bubbles: true}));
}
}

0 comments on commit c72e7fd

Please sign in to comment.