feat(chips): add input chips

PiperOrigin-RevId: 530743037
This commit is contained in:
Elizabeth Mitchell 2023-05-09 16:24:39 -07:00 committed by Copybara-Service
parent 5da772981c
commit d029b634c7
7 changed files with 230 additions and 1 deletions

6
chips/_input-chip.scss Normal file
View File

@ -0,0 +1,6 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
@forward './lib/input-chip' show theme;

31
chips/input-chip.ts Normal file
View File

@ -0,0 +1,31 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {customElement} from 'lit/decorators.js';
import {InputChip} from './lib/input-chip.js';
import {styles} from './lib/input-styles.css.js';
import {styles as selectableStyles} from './lib/selectable-styles.css.js';
import {styles as sharedStyles} from './lib/shared-styles.css.js';
import {styles as trailingIconStyles} from './lib/trailing-icon-styles.css.js';
declare global {
interface HTMLElementTagNameMap {
'md-input-chip': MdInputChip;
}
}
/**
* TODO(b/243982145): add docs
*
* @final
* @suppress {visibility}
*/
@customElement('md-input-chip')
export class MdInputChip extends InputChip {
static override styles =
[sharedStyles, trailingIconStyles, selectableStyles, styles];
}

17
chips/input-chip_test.ts Normal file
View File

@ -0,0 +1,17 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
// import 'jasmine'; (google3-only)
import {createTokenTests} from '../testing/tokens.js';
import {MdInputChip} from './input-chip.js';
describe('<md-input-chip>', () => {
describe('.styles', () => {
createTokenTests(MdInputChip.styles);
});
});

View File

@ -0,0 +1,75 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// go/keep-sorted start
@use 'sass:list';
// go/keep-sorted end
// go/keep-sorted start
@use '../../tokens';
// go/keep-sorted end
@mixin theme($tokens) {
$supported-tokens: list.join(
tokens.$md-comp-input-chip-supported-tokens,
(
'container-shape-start-start',
'container-shape-start-end',
'container-shape-end-end',
'container-shape-end-start'
)
);
@each $token, $value in $tokens {
@if list.index($supported-tokens, $token) == null {
@error 'Token `#{$token}` is not a supported token.';
}
@if $value {
--md-input-chip-#{$token}: #{$value};
}
}
}
@mixin styles() {
$tokens: tokens.md-comp-input-chip-values();
:host {
@each $token, $value in $tokens {
--_#{$token}: var(--md-input-chip-#{$token}, #{$value});
}
// Support logical shape properties
--_container-shape-start-start: var(
--md-input-chip-container-shape-start-start,
var(--_container-shape)
);
--_container-shape-start-end: var(
--md-input-chip-container-shape-start-end,
var(--_container-shape)
);
--_container-shape-end-end: var(
--md-input-chip-container-shape-end-end,
var(--_container-shape)
);
--_container-shape-end-start: var(
--md-input-chip-container-shape-end-start,
var(--_container-shape)
);
}
.avatar .primary.action {
padding-inline-start: 4px;
}
.avatar .leading.icon ::slotted(:first-child) {
border-radius: var(--_avatar-shape);
height: var(--_avatar-size);
width: var(--_avatar-size);
}
.disabled.avatar .leading.icon {
opacity: var(--_disabled-avatar-opacity);
}
}

90
chips/lib/input-chip.ts Normal file
View File

@ -0,0 +1,90 @@
/**
* @license
* Copyright 2023 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {html, nothing} from 'lit';
import {property} from 'lit/decorators.js';
import {ripple} from '../../ripple/directive.js';
import {ARIAMixinStrict} from '../../types/aria.js';
import {Chip} from './chip.js';
import {renderRemoveButton} from './trailing-actions.js';
/**
* An input chip component.
*/
export class InputChip extends Chip {
@property({type: Boolean}) avatar = false;
@property() href = '';
@property() target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property({type: Boolean, attribute: 'remove-only'}) removeOnly = false;
@property({type: Boolean}) selected = false;
protected get focusFor() {
if (this.href) {
return 'link';
}
if (this.removeOnly) {
return 'text';
}
return 'button';
}
protected override get rippleDisabled() {
// Link chips cannot be disabled
return !this.href && this.disabled;
}
protected override getContainerClasses() {
return {
...super.getContainerClasses(),
avatar: this.avatar,
// Link chips cannot be disabled
disabled: !this.href && this.disabled,
selected: this.selected,
};
}
protected override renderPrimaryAction() {
const {ariaLabel} = this as ARIAMixinStrict;
if (this.href) {
return html`
<a class="primary action"
id="link"
aria-label=${ariaLabel || nothing}
href=${this.href}
target=${this.target || nothing}
${ripple(this.getRipple)}
>${this.renderContent()}</a>
`;
}
if (this.removeOnly) {
return html`
<span class="primary action"
id="text"
aria-label=${ariaLabel || nothing}
>${this.renderContent()}</span>
`;
}
return html`
<button class="primary action"
id="button"
aria-label=${ariaLabel || nothing}
?disabled=${this.disabled}
type="button"
${ripple(this.getRipple)}
>${this.renderContent()}</button>
`;
}
protected override renderTrailingAction() {
return renderRemoveButton({disabled: this.disabled});
}
}

View File

@ -0,0 +1,10 @@
//
// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0
//
// go/keep-sorted start
@use './input-chip';
// go/keep-sorted end
@include input-chip.styles;

View File

@ -20,7 +20,6 @@ $supported-tokens: (
// go/keep-sorted start
'avatar-shape',
'avatar-size',
'container-elevation',
'container-height',
'container-shape',
'disabled-avatar-opacity',
@ -82,6 +81,7 @@ $supported-tokens: (
$unsupported-tokens: (
// go/keep-sorted start
'container-elevation',
'dragged-container-elevation',
'dragged-label-text-color',
'dragged-leading-icon-color',