Skip to content

Commit

Permalink
feat(chips): add removable filter chips
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 530739415
  • Loading branch information
asyncLiz authored and copybara-github committed May 9, 2023
1 parent 095355d commit 748d70e
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 13 deletions.
10 changes: 4 additions & 6 deletions chips/lib/_shared.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,16 @@
border: none;
border-radius: inherit;
display: flex;
gap: 8px;
outline: none;
padding: 0;
position: relative;
text-decoration: none;
}

.action:first-of-type {
.primary.action {
padding-inline-start: 8px;
}

.action:last-of-type {
padding-inline-end: 8px;
padding-inline-end: 16px;
}

.touch {
Expand Down Expand Up @@ -131,7 +130,6 @@
display: flex;
font: var(--_label-text-type);
height: 100%;
padding: 0 8px;
text-overflow: ellipsis;
user-select: none;
white-space: nowrap;
Expand Down
33 changes: 33 additions & 0 deletions chips/lib/_trailing-icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,40 @@
// SPDX-License-Identifier: Apache-2.0
//

// go/keep-sorted start
@use '../../focus/focus-ring';
// go/keep-sorted end

@mixin styles() {
.trailing.action {
display: flex;
padding: 0 8px;

// Note: the trailing action's shape only follows the trailing end of the
// chip. For example, if the leading end is rounded, but the trailing is end
// squared, then the focus ring will be squared (not rounded+squared).
@include focus-ring.theme(
(
'shape-start-start': var(--_container-shape-start-end),
'shape-end-start': var(--_container-shape-end-end),
'shape-end-end': var(--_container-shape-end-end),
'shape-start-end': var(--_container-shape-start-end),
'offset': -2px,
)
);
}

.trailing.action md-ripple {
height: calc(4 / 3 * var(--_icon-size)); // 24px default
inset: 50% 0 0 50%;
transform: translateX(-50%) translateY(-50%);
width: calc(4 / 3 * var(--_icon-size)); // 24px default
}

:has(.trailing.action) .primary.action {
padding-inline-end: 0;
}

.trailing .icon {
color: var(--_trailing-icon-color);
}
Expand Down
4 changes: 2 additions & 2 deletions chips/lib/assist-chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class AssistChip extends Chip {
const {ariaLabel} = this as ARIAMixinStrict;
if (this.href) {
return html`
<a class="action"
<a class="primary action"
id="link"
aria-label=${ariaLabel || nothing}
href=${this.href}
Expand All @@ -55,7 +55,7 @@ export class AssistChip extends Chip {
}

return html`
<button class="action"
<button class="primary action"
id="button"
aria-label=${ariaLabel || nothing}
?disabled=${this.disabled}
Expand Down
6 changes: 2 additions & 4 deletions chips/lib/chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export abstract class Chip extends LitElement {
<md-focus-ring for=${this.focusFor}></md-focus-ring>
${ripple}
${this.renderPrimaryAction()}
${this.renderTrailingAction()}
${this.renderTrailingAction?.() || nothing}
</div>
`;
}
Expand All @@ -75,9 +75,7 @@ export abstract class Chip extends LitElement {

protected abstract renderPrimaryAction(): TemplateResult;

protected renderTrailingAction(): TemplateResult|typeof nothing {
return nothing;
}
protected renderTrailingAction?(): TemplateResult|typeof nothing;

protected renderOutline() {
return html`<span class="outline"></span>`;
Expand Down
12 changes: 11 additions & 1 deletion chips/lib/filter-chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import {ripple} from '../../ripple/directive.js';
import {ARIAMixinStrict} from '../../types/aria.js';

import {Chip} from './chip.js';
import {renderRemoveButton} from './trailing-actions.js';

/**
* A filter chip component.
*/
export class FilterChip extends Chip {
@property({type: Boolean}) elevated = false;
@property({type: Boolean}) removable = false;
@property({type: Boolean}) selected = false;

protected get focusFor() {
Expand Down Expand Up @@ -55,7 +57,7 @@ export class FilterChip extends Chip {
protected override renderPrimaryAction() {
const {ariaLabel} = this as ARIAMixinStrict;
return html`
<button class="action"
<button class="primary action"
id="option"
aria-label=${ariaLabel || nothing}
aria-selected=${this.selected}
Expand All @@ -78,6 +80,14 @@ export class FilterChip extends Chip {
`;
}

protected override renderTrailingAction() {
if (this.removable) {
return renderRemoveButton({disabled: this.disabled});
}

return nothing;
}

protected override renderOutline() {
if (this.elevated) {
return html`<md-elevation></md-elevation>`;
Expand Down
49 changes: 49 additions & 0 deletions chips/lib/trailing-actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import '../../focus/focus-ring.js';
import '../../ripple/ripple.js';

import {html} from 'lit';
import {createRef, ref} from 'lit/directives/ref.js';

import {ripple} from '../../ripple/directive.js';
import {MdRipple} from '../../ripple/ripple.js';

import {Chip} from './chip.js';

/** @protected */
export function renderRemoveButton({disabled}: {disabled: boolean}) {
const rippleRef = createRef<MdRipple>();
return html`
<button class="trailing action"
?disabled=${disabled ?? false}
@click=${handleRemoveClick}
${ripple(() => rippleRef.value || null)}
>
<md-focus-ring></md-focus-ring>
<md-ripple ${ref(rippleRef)} unbounded></md-ripple>
<svg class="icon" viewBox="0 96 960 960">
<path d="m249 849-42-42 231-231-231-231 42-42 231 231 231-231 42 42-231 231 231 231-42 42-231-231-231 231Z" />
</svg>
<span class="touch"></span>
</button>
`;
}

function handleRemoveClick(this: Chip, event: Event) {
if (this.disabled) {
return;
}

event.stopPropagation();
const preventDefault = !this.dispatchEvent(new Event('remove'));
if (preventDefault) {
return;
}

this.remove();
}

0 comments on commit 748d70e

Please sign in to comment.