mirror of
https://github.com/material-components/material-web.git
synced 2024-09-11 13:46:10 +03:00
feat(chips): add input chips
PiperOrigin-RevId: 530743037
This commit is contained in:
parent
5da772981c
commit
d029b634c7
6
chips/_input-chip.scss
Normal file
6
chips/_input-chip.scss
Normal 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
31
chips/input-chip.ts
Normal 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
17
chips/input-chip_test.ts
Normal 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);
|
||||
});
|
||||
});
|
75
chips/lib/_input-chip.scss
Normal file
75
chips/lib/_input-chip.scss
Normal 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
90
chips/lib/input-chip.ts
Normal 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});
|
||||
}
|
||||
}
|
10
chips/lib/input-styles.scss
Normal file
10
chips/lib/input-styles.scss
Normal 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;
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user