diff --git a/chips/_input-chip.scss b/chips/_input-chip.scss new file mode 100644 index 0000000000..3a82085ced --- /dev/null +++ b/chips/_input-chip.scss @@ -0,0 +1,6 @@ +// +// Copyright 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 +// + +@forward './lib/input-chip' show theme; diff --git a/chips/input-chip.ts b/chips/input-chip.ts new file mode 100644 index 0000000000..1a1c3abe11 --- /dev/null +++ b/chips/input-chip.ts @@ -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]; +} diff --git a/chips/input-chip_test.ts b/chips/input-chip_test.ts new file mode 100644 index 0000000000..ce3dc99a4f --- /dev/null +++ b/chips/input-chip_test.ts @@ -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('', () => { + describe('.styles', () => { + createTokenTests(MdInputChip.styles); + }); +}); diff --git a/chips/lib/_input-chip.scss b/chips/lib/_input-chip.scss new file mode 100644 index 0000000000..16934e85a1 --- /dev/null +++ b/chips/lib/_input-chip.scss @@ -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); + } +} diff --git a/chips/lib/input-chip.ts b/chips/lib/input-chip.ts new file mode 100644 index 0000000000..b6f9f2bbe6 --- /dev/null +++ b/chips/lib/input-chip.ts @@ -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` + ${this.renderContent()} + `; + } + + if (this.removeOnly) { + return html` + ${this.renderContent()} + `; + } + + return html` + + `; + } + + protected override renderTrailingAction() { + return renderRemoveButton({disabled: this.disabled}); + } +} diff --git a/chips/lib/input-styles.scss b/chips/lib/input-styles.scss new file mode 100644 index 0000000000..ec77d548ec --- /dev/null +++ b/chips/lib/input-styles.scss @@ -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; diff --git a/tokens/_md-comp-input-chip.scss b/tokens/_md-comp-input-chip.scss index 6be9ed68fc..9875e350be 100644 --- a/tokens/_md-comp-input-chip.scss +++ b/tokens/_md-comp-input-chip.scss @@ -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',