Migrate chips to Material 3 chips. (#18513)

This commit is contained in:
Paul Bottein 2023-11-09 17:57:37 +01:00 committed by GitHub
parent 4933413140
commit 37b7395986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 548 additions and 365 deletions

View File

@ -1,8 +1,10 @@
import { css, html, LitElement, TemplateResult } from "lit";
import { css, html, LitElement, TemplateResult, nothing } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-chip";
import "../../../../src/components/ha-chip-set";
import "../../../../src/components/chips/ha-chip-set";
import "../../../../src/components/chips/ha-assist-chip";
import "../../../../src/components/chips/ha-input-chip";
import "../../../../src/components/chips/ha-filter-chip";
import "../../../../src/components/ha-svg-icon";
import { mdiHomeAssistant } from "../../../../src/resources/home-assistant-logo-svg";
@ -10,10 +12,6 @@ const chips: {
icon?: string;
content?: string;
}[] = [
{},
{
icon: mdiHomeAssistant,
},
{
content: "Content",
},
@ -29,31 +27,73 @@ export class DemoHaChips extends LitElement {
return html`
<ha-card header="ha-chip demo">
<div class="card-content">
${chips.map(
(chip) => html`
<ha-chip .hasIcon=${chip.icon !== undefined}>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: ""}
${chip.content}
</ha-chip>
`
)}
</div>
</ha-card>
<ha-card header="ha-chip-set demo">
<div class="card-content">
<p>Action chip</p>
<ha-chip-set>
${chips.map(
(chip) => html`
<ha-chip .hasIcon=${chip.icon !== undefined}>
<ha-assist-chip .label=${chip.content}>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: nothing}
</ha-assist-chip>
`
)}
${chips.map(
(chip) => html`
<ha-assist-chip .label=${chip.content} selected>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: nothing}
</ha-assist-chip>
`
)}
</ha-chip-set>
<p>Filter chip</p>
<ha-chip-set>
${chips.map(
(chip) => html`
<ha-filter-chip .label=${chip.content}>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: nothing}
</ha-filter-chip>
`
)}
${chips.map(
(chip) => html`
<ha-filter-chip .label=${chip.content} selected>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: nothing}
</ha-filter-chip>
`
)}
</ha-chip-set>
<p>Input chip</p>
<ha-chip-set>
${chips.map(
(chip) => html`
<ha-input-chip .label=${chip.content}>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: ""}
${chip.content}
</ha-chip>
</ha-input-chip>
`
)}
${chips.map(
(chip) => html`
<ha-input-chip .label=${chip.content} selected>
${chip.icon
? html`<ha-svg-icon slot="icon" .path=${chip.icon}>
</ha-svg-icon>`
: nothing}
</ha-input-chip>
`
)}
</ha-chip-set>
@ -68,12 +108,10 @@ export class DemoHaChips extends LitElement {
max-width: 600px;
margin: 24px auto;
}
ha-chip {
margin-bottom: 4px;
}
.card-content {
display: flex;
flex-direction: column;
align-items: flex-start;
}
`;
}

View File

@ -10,7 +10,6 @@ import { computeStateDisplay } from "../../../../src/common/entity/compute_state
import "../../../../src/components/data-table/ha-data-table";
import type { DataTableColumnContainer } from "../../../../src/components/data-table/ha-data-table";
import "../../../../src/components/entity/state-badge";
import "../../../../src/components/ha-chip";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../../src/types";

View File

@ -31,8 +31,8 @@ import { navigate } from "../../../../src/common/navigate";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-alert";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-chip";
import "../../../../src/components/ha-chip-set";
import "../../../../src/components/chips/ha-chip-set";
import "../../../../src/components/chips/ha-assist-chip";
import "../../../../src/components/ha-markdown";
import "../../../../src/components/ha-settings-row";
import "../../../../src/components/ha-svg-icon";
@ -78,6 +78,7 @@ import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-has
import { hassioStyle } from "../../resources/hassio-style";
import "../../update-available/update-available-card";
import { addonArchIsSupported, extractChangelog } from "../../util/addon";
import { capitalizeFirstLetter } from "../../../../src/common/string/capitalize-first-letter";
const STAGE_ICON = {
stable: mdiCheckCircle,
@ -234,28 +235,32 @@ class HassioAddonInfo extends LitElement {
<ha-chip-set class="capabilities">
${this.addon.stage !== "stable"
? html` <ha-chip
hasIcon
class=${classMap({
yellow: this.addon.stage === "experimental",
red: this.addon.stage === "deprecated",
})}
@click=${this._showMoreInfo}
id="stage"
>
<ha-svg-icon
slot="icon"
.path=${STAGE_ICON[this.addon.stage]}
? html`
<ha-assist-chip
filled
class=${classMap({
yellow: this.addon.stage === "experimental",
red: this.addon.stage === "deprecated",
})}
@click=${this._showMoreInfo}
id="stage"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
`addon.dashboard.capability.stages.${this.addon.stage}`
)
)}
>
</ha-svg-icon>
${this.supervisor.localize(
`addon.dashboard.capability.stages.${this.addon.stage}`
)}
</ha-chip>`
<ha-svg-icon
slot="icon"
.path=${STAGE_ICON[this.addon.stage]}
>
</ha-svg-icon>
</ha-assist-chip>
`
: ""}
<ha-chip
hasIcon
<ha-assist-chip
filled
class=${classMap({
green: Number(this.addon.rating) >= 6,
yellow: [3, 4, 5].includes(Number(this.addon.rating)),
@ -263,138 +268,183 @@ class HassioAddonInfo extends LitElement {
})}
@click=${this._showMoreInfo}
id="rating"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.rating"
)
)}
>
<ha-svg-icon slot="icon" .path=${RATING_ICON[this.addon.rating]}>
</ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.rating"
)}
</ha-chip>
</ha-assist-chip>
${this.addon.host_network
? html`
<ha-chip
hasIcon
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="host_network"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.host"
)
)}
>
<ha-svg-icon slot="icon" .path=${mdiNetwork}> </ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.host"
)}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this.addon.full_access
? html`
<ha-chip
hasIcon
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="full_access"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.hardware"
)
)}
>
<ha-svg-icon slot="icon" .path=${mdiChip}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.hardware"
)}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this.addon.homeassistant_api
? html`
<ha-chip
hasIcon
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="homeassistant_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.core"
)
)}
>
<ha-svg-icon
slot="icon"
.path=${mdiHomeAssistant}
></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.core"
)}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this._computeHassioApi
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="hassio_api">
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="hassio_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
`addon.dashboard.capability.role.${this.addon.hassio_role}`
) || this.addon.hassio_role
)}
>
<ha-svg-icon
slot="icon"
.path=${mdiHomeAssistant}
></ha-svg-icon>
${this.supervisor.localize(
`addon.dashboard.capability.role.${this.addon.hassio_role}`
) || this.addon.hassio_role}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this.addon.docker_api
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="docker_api">
<ha-svg-icon slot="icon" .path=${mdiDocker}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.docker"
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="docker_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.docker"
)
)}
</ha-chip>
>
<ha-svg-icon slot="icon" .path=${mdiDocker}></ha-svg-icon>
</ha-assist-chip>
`
: ""}
${this.addon.host_pid
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="host_pid">
<ha-svg-icon slot="icon" .path=${mdiPound}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.host_pid"
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="host_pid"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.host_pid"
)
)}
</ha-chip>
>
<ha-svg-icon slot="icon" .path=${mdiPound}></ha-svg-icon>
</ha-assist-chip>
`
: ""}
${this.addon.apparmor !== "default"
? html`
<ha-chip
hasIcon
<ha-assist-chip
filled
@click=${this._showMoreInfo}
class=${this._computeApparmorClassName}
id="apparmor"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.apparmor"
)
)}
>
<ha-svg-icon slot="icon" .path=${mdiShield}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.apparmor"
)}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this.addon.auth_api
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="auth_api">
<ha-svg-icon slot="icon" .path=${mdiKey}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.auth"
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="auth_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.auth"
)
)}
</ha-chip>
>
<ha-svg-icon slot="icon" .path=${mdiKey}></ha-svg-icon>
</ha-assist-chip>
`
: ""}
${this.addon.ingress
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="ingress">
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="ingress"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.ingress"
)
)}
>
<ha-svg-icon
slot="icon"
.path=${mdiCursorDefaultClickOutline}
></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.ingress"
)}
</ha-chip>
</ha-assist-chip>
`
: ""}
${this.addon.signed
? html`
<ha-chip hasIcon @click=${this._showMoreInfo} id="signed">
<ha-svg-icon slot="icon" .path=${mdiLinkLock}></ha-svg-icon>
${this.supervisor.localize(
"addon.dashboard.capability.label.signed"
<ha-assist-chip
filled
@click=${this._showMoreInfo}
id="signed"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.signed"
)
)}
</ha-chip>
>
<ha-svg-icon slot="icon" .path=${mdiLinkLock}></ha-svg-icon>
</ha-assist-chip>
`
: ""}
</ha-chip-set>
@ -1185,23 +1235,35 @@ class HassioAddonInfo extends LitElement {
.description a {
color: var(--primary-color);
}
ha-chip {
text-transform: capitalize;
--ha-chip-text-color: var(--text-primary-color);
--ha-chip-background-color: var(--primary-color);
ha-assist-chip {
--md-sys-color-primary: var(--text-primary-color);
--md-sys-color-on-surface: var(--text-primary-color);
--ha-assist-chip-filled-container-color: var(--primary-color);
}
.red {
--ha-chip-background-color: var(--label-badge-red, #df4c1e);
--ha-assist-chip-filled-container-color: var(
--label-badge-red,
#df4c1e
);
}
.blue {
--ha-chip-background-color: var(--label-badge-blue, #039be5);
--ha-assist-chip-filled-container-color: var(
--label-badge-blue,
#039be5
);
}
.green {
--ha-chip-background-color: var(--label-badge-green, #0da035);
--ha-assist-chip-filled-container-color: var(
--label-badge-green,
#0da035
);
}
.yellow {
--ha-chip-background-color: var(--label-badge-yellow, #f4b400);
--ha-assist-chip-filled-container-color: var(
--label-badge-yellow,
#f4b400
);
}
.capabilities {
margin-bottom: 16px;
@ -1260,9 +1322,6 @@ class HassioAddonInfo extends LitElement {
}
@media (max-width: 720px) {
ha-chip {
line-height: 36px;
}
.addon-options {
max-width: 100%;
}

View File

@ -0,0 +1,53 @@
import { MdAssistChip } from "@material/web/chips/assist-chip";
import { css, html } from "lit";
import { customElement, property } from "lit/decorators";
@customElement("ha-assist-chip")
export class HaAssistChip extends MdAssistChip {
@property({ type: Boolean, reflect: true }) filled = false;
static override styles = [
...super.styles,
css`
:host {
--md-sys-color-primary: var(--primary-text-color);
--md-sys-color-on-surface: var(--primary-text-color);
--md-assist-chip-container-shape: 16px;
--md-assist-chip-outline-color: var(--outline-color);
--md-assist-chip-label-text-weight: 400;
--ha-assist-chip-filled-container-color: rgba(
var(--rgb-primary-text-color),
0.15
);
}
/** Material 3 doesn't have a filled chip, so we have to make our own **/
.filled {
display: flex;
pointer-events: none;
border-radius: inherit;
inset: 0;
position: absolute;
background-color: var(--ha-assist-chip-filled-container-color);
}
/** Set the size of mdc icons **/
::slotted([slot="icon"]) {
display: flex;
--mdc-icon-size: var(--md-input-chip-icon-size, 18px);
}
`,
];
protected override renderOutline() {
if (this.filled) {
return html`<span class="filled"></span>`;
}
return super.renderOutline();
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-assist-chip": HaAssistChip;
}
}

View File

@ -0,0 +1,11 @@
import { MdChipSet } from "@material/web/chips/chip-set";
import { customElement } from "lit/decorators";
@customElement("ha-chip-set")
export class HaChipSet extends MdChipSet {}
declare global {
interface HTMLElementTagNameMap {
"ha-chip-set": HaChipSet;
}
}

View File

@ -0,0 +1,41 @@
import { MdFilterChip } from "@material/web/chips/filter-chip";
import { css, html } from "lit";
import { customElement, property } from "lit/decorators";
@customElement("ha-filter-chip")
export class HaFilterChip extends MdFilterChip {
@property({ type: Boolean, reflect: true, attribute: "no-leading-icon" })
noLeadingIcon = false;
static override styles = [
...super.styles,
css`
:host {
--md-sys-color-primary: var(--primary-text-color);
--md-sys-color-on-surface: var(--primary-text-color);
--md-sys-color-on-surface-variant: var(--primary-text-color);
--md-sys-color-on-secondary-container: var(--primary-text-color);
--md-filter-chip-container-shape: 16px;
--md-filter-chip-outline-color: var(--outline-color);
--md-filter-chip-selected-container-color: rgba(
var(--rgb-primary-text-color),
0.15
);
}
`,
];
protected renderLeadingIcon() {
if (this.noLeadingIcon) {
// eslint-disable-next-line lit/prefer-nothing
return html``;
}
return super.renderLeadingIcon();
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-filter-chip": HaFilterChip;
}
}

View File

@ -0,0 +1,35 @@
import { MdInputChip } from "@material/web/chips/input-chip";
import { css } from "lit";
import { customElement } from "lit/decorators";
@customElement("ha-input-chip")
export class HaInputChip extends MdInputChip {
static override styles = [
...super.styles,
css`
:host {
--md-sys-color-primary: var(--primary-text-color);
--md-sys-color-on-surface: var(--primary-text-color);
--md-sys-color-on-surface-variant: var(--primary-text-color);
--md-sys-color-on-secondary-container: var(--primary-text-color);
--md-input-chip-container-shape: 16px;
--md-input-chip-outline-color: var(--outline-color);
--md-input-chip-selected-container-color: rgba(
var(--rgb-primary-text-color),
0.15
);
}
/** Set the size of mdc icons **/
::slotted([slot="icon"]) {
display: flex;
--mdc-icon-size: var(--md-input-chip-icon-size, 18px);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
"ha-input-chip": HaInputChip;
}
}

View File

@ -1,38 +0,0 @@
// @ts-ignore
import chipStyles from "@material/chips/dist/mdc.chips.min.css";
import {
css,
CSSResultGroup,
html,
LitElement,
TemplateResult,
unsafeCSS,
} from "lit";
import { customElement } from "lit/decorators";
@customElement("ha-chip-set")
export class HaChipSet extends LitElement {
protected render(): TemplateResult {
return html`
<div class="mdc-chip-set">
<slot></slot>
</div>
`;
}
static get styles(): CSSResultGroup {
return css`
${unsafeCSS(chipStyles)}
slot::slotted(ha-chip) {
margin: 4px 4px 4px 0;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-chip-set": HaChipSet;
}
}

View File

@ -1,85 +0,0 @@
// @ts-ignore
import chipStyles from "@material/chips/dist/mdc.chips.min.css";
import { css, CSSResultGroup, html, LitElement, nothing, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators";
@customElement("ha-chip")
export class HaChip extends LitElement {
@property({ type: Boolean }) public hasIcon = false;
@property({ type: Boolean }) public hasTrailingIcon = false;
@property({ type: Boolean }) public noText = false;
protected render() {
return html`
<div class="mdc-chip ${this.noText ? "no-text" : ""}">
${this.hasIcon
? html`<div class="mdc-chip__icon mdc-chip__icon--leading">
<slot name="icon"></slot>
</div>`
: nothing}
<div class="mdc-chip__ripple"></div>
<span role="gridcell">
<span role="button" tabindex="0" class="mdc-chip__primary-action">
<span class="mdc-chip__text"><slot></slot></span>
</span>
</span>
${this.hasTrailingIcon
? html`<div class="mdc-chip__icon mdc-chip__icon--trailing">
<slot name="trailing-icon"></slot>
</div>`
: nothing}
</div>
`;
}
static get styles(): CSSResultGroup {
return css`
${unsafeCSS(chipStyles)}
.mdc-chip {
background-color: var(
--ha-chip-background-color,
rgba(var(--rgb-primary-text-color), 0.15)
);
color: var(--ha-chip-text-color, var(--primary-text-color));
}
.mdc-chip.no-text {
padding: 0 10px;
}
.mdc-chip:hover {
color: var(--ha-chip-text-color, var(--primary-text-color));
}
.mdc-chip__icon--leading,
.mdc-chip__icon--trailing {
--mdc-icon-size: 18px;
line-height: 14px;
color: var(--ha-chip-icon-color, var(--ha-chip-text-color));
}
.mdc-chip.mdc-chip--selected .mdc-chip__checkmark,
.mdc-chip .mdc-chip__icon--leading:not(.mdc-chip__icon--leading-hidden) {
margin-right: -4px;
margin-inline-start: -4px;
margin-inline-end: 4px;
direction: var(--direction);
}
span[role="gridcell"] {
line-height: 14px;
}
:host {
outline: none;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-chip": HaChip;
}
}

View File

@ -0,0 +1,60 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
@customElement("ha-label")
class HaLabel extends LitElement {
protected render(): TemplateResult {
return html`
<span class="label">
<slot name="icon"></slot>
<slot></slot>
</div>
`;
}
static get styles(): CSSResultGroup {
return [
css`
:host {
--ha-label-text-color: var(--primary-text-color);
--ha-label-icon-color: var(--primary-text-color);
--ha-label-background-color: rgba(
var(--rgb-primary-text-color),
0.15
);
}
.label {
display: inline-flex;
flex-direction: row;
align-items: center;
font-size: 12px;
font-weight: 500;
line-height: 16px;
letter-spacing: 0.1px;
vertical-align: middle;
height: 32px;
padding: 0 16px;
border-radius: 18px;
background-color: var(--ha-label-background-color);
color: var(--ha-label-text-color);
--mdc-icon-size: 18px;
}
::slotted([slot="icon"]) {
margin-right: 8px;
margin-left: -8px;
display: flex;
color: var(--ha-label-icon-color);
}
span {
display: inline-flex;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-label": HaLabel;
}
}

View File

@ -1,5 +1,5 @@
import "@material/mwc-list/mwc-list-item";
import { mdiClose, mdiDrag } from "@mdi/js";
import { mdiDrag } from "@mdi/js";
import { LitElement, PropertyValues, css, html, nothing } from "lit";
import { customElement, property, query } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
@ -12,9 +12,9 @@ import type { SelectOption, SelectSelector } from "../../data/selector";
import { sortableStyles } from "../../resources/ha-sortable-style";
import { SortableInstance } from "../../resources/sortable";
import type { HomeAssistant } from "../../types";
import "../chips/ha-chip-set";
import "../chips/ha-input-chip";
import "../ha-checkbox";
import "../ha-chip";
import "../ha-chip-set";
import "../ha-combo-box";
import type { HaComboBox } from "../ha-combo-box";
import "../ha-formfield";
@ -65,7 +65,7 @@ export class HaSelectSelector extends LitElement {
{
animation: 150,
fallbackClass: "sortable-fallback",
draggable: "ha-chip",
draggable: "ha-input-chip",
onChoose: (evt: SortableEvent) => {
(evt.item as any).placeholder =
document.createComment("sort-placeholder");
@ -199,30 +199,31 @@ export class HaSelectSelector extends LitElement {
${repeat(
value,
(item) => item,
(item, idx) => html`
<ha-chip
hasTrailingIcon
.hasIcon=${this.selector.select?.reorder}
>
${this.selector.select?.reorder
? html`
<ha-svg-icon
slot="icon"
.path=${mdiDrag}
data-handle
></ha-svg-icon>
`
: nothing}
${options.find((option) => option.value === item)
?.label || item}
<ha-svg-icon
slot="trailing-icon"
.path=${mdiClose}
(item, idx) => {
const label =
options.find((option) => option.value === item)?.label ||
item;
return html`
<ha-input-chip
.idx=${idx}
@click=${this._removeItem}
></ha-svg-icon>
</ha-chip>
`
@remove=${this._removeItem}
.label=${label}
selected
>
${this.selector.select?.reorder
? html`
<ha-svg-icon
slot="icon"
.path=${mdiDrag}
data-handle
></ha-svg-icon>
`
: nothing}
${options.find((option) => option.value === item)
?.label || item}
</ha-input-chip>
`;
}
)}
</ha-chip-set>
`
@ -354,6 +355,7 @@ export class HaSelectSelector extends LitElement {
}
private async _removeItem(ev) {
ev.stopPropagation();
const value: string[] = [...ensureArray(this.value!)];
value.splice(ev.target.idx, 1);
@ -431,6 +433,9 @@ export class HaSelectSelector extends LitElement {
mwc-list-item[disabled] {
--mdc-theme-text-primary-on-background: var(--disabled-text-color);
}
ha-chip-set {
padding: 8px 0;
}
`,
];
}

View File

@ -27,7 +27,7 @@ import {
fuzzyFilterSort,
} from "../../common/string/filter/sequence-matching";
import { debounce } from "../../common/util/debounce";
import "../../components/ha-chip";
import "../../components/ha-label";
import "../../components/ha-circular-progress";
import "../../components/ha-icon-button";
import "../../components/ha-list-item";
@ -326,19 +326,17 @@ export class QuickBar extends LitElement {
hasMeta
>
<span>
<ha-chip
<ha-label
.label=${item.categoryText}
hasIcon
class="command-category ${item.categoryKey}"
>
${item.iconPath
? html`<ha-svg-icon
.path=${item.iconPath}
slot="icon"
></ha-svg-icon>`
: ""}
${item.categoryText}</ha-chip
>
? html`
<ha-svg-icon .path=${item.iconPath} slot="icon"></ha-svg-icon>
`
: nothing}
${item.categoryText}
</ha-label>
</span>
<span class="command-text">${item.primaryText}</span>
@ -816,20 +814,20 @@ export class QuickBar extends LitElement {
}
.command-category {
--ha-chip-icon-color: #585858;
--ha-chip-text-color: #212121;
--ha-label-icon-color: #585858;
--ha-label-text-color: #212121;
}
.command-category.reload {
--ha-chip-background-color: #cddc39;
--ha-label-background-color: #cddc39;
}
.command-category.navigation {
--ha-chip-background-color: var(--light-primary-color);
--ha-label-background-color: var(--light-primary-color);
}
.command-category.server_control {
--ha-chip-background-color: var(--warning-color);
--ha-label-background-color: var(--warning-color);
}
span.command-text {

View File

@ -584,6 +584,10 @@ class DialogCalendarEventEditor extends LitElement {
return [
haStyleDialog,
css`
ha-dialog {
--mdc-dialog-min-width: min(600px, 95vw);
--mdc-dialog-max-width: min(600px, 95vw);
}
state-info {
line-height: 40px;
}

View File

@ -1,14 +1,14 @@
import type { SelectedDetail } from "@material/mwc-list";
import { formatInTimeZone, toDate } from "date-fns-tz";
import { css, html, LitElement, PropertyValues, nothing } from "lit";
import { LitElement, PropertyValues, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import type { Options, WeekdayStr } from "rrule";
import { ByWeekday, RRule, Weekday } from "rrule";
import { firstWeekdayIndex } from "../../common/datetime/first_weekday";
import { stopPropagation } from "../../common/dom/stop_propagation";
import { LocalizeKeys } from "../../common/translations/localize";
import "../../components/ha-chip";
import "../../components/chips/ha-chip-set";
import "../../components/chips/ha-filter-chip";
import "../../components/ha-date-input";
import "../../components/ha-list-item";
import "../../components/ha-select";
@ -16,17 +16,17 @@ import type { HaSelect } from "../../components/ha-select";
import "../../components/ha-textfield";
import { HomeAssistant } from "../../types";
import {
DEFAULT_COUNT,
MonthlyRepeatItem,
RepeatEnd,
RepeatFrequency,
convertFrequency,
convertRepeatFrequency,
DEFAULT_COUNT,
getMonthdayRepeatFromRule,
getMonthlyRepeatItems,
getMonthlyRepeatWeekdayFromRule,
getWeekday,
getWeekdays,
MonthlyRepeatItem,
RepeatEnd,
RepeatFrequency,
ruleByWeekDay,
untilValue,
} from "./recurrence";
@ -240,22 +240,24 @@ export class RecurrenceRuleEditor extends LitElement {
renderWeekly() {
return html`
${this.renderInterval()}
<div class="weekdays">
<ha-chip-set class="weekdays">
${this._allWeekdays!.map(
(item) => html`
<ha-chip
<ha-filter-chip
no-leading-icon
.value=${item}
class=${classMap({ active: this._weekday.has(item) })}
.selected=${this._weekday.has(item)}
@click=${this._onWeekdayToggle}
>${this.hass.localize(
.label=${this.hass.localize(
`ui.components.calendar.event.repeat.weekly.weekday.${
item.toLowerCase() as Lowercase<WeekdayStr>
}`
)}</ha-chip
)}
>
</ha-filter-chip>
`
)}
</div>
</ha-chip-set>
`;
}
@ -379,10 +381,10 @@ export class RecurrenceRuleEditor extends LitElement {
private _onWeekdayToggle(e: MouseEvent) {
const target = e.currentTarget as any;
const value = target.value as WeekdayStr;
if (!target.classList.contains("active")) {
this._weekday.add(value);
} else {
if (this._weekday.has(value)) {
this._weekday.delete(value);
} else {
this._weekday.add(value);
}
this.requestUpdate("_weekday");
}
@ -504,8 +506,6 @@ export class RecurrenceRuleEditor extends LitElement {
margin-bottom: 16px;
}
.weekdays {
display: flex;
justify-content: space-between;
margin-bottom: 16px;
}
ha-textfield:last-child,
@ -513,11 +513,6 @@ export class RecurrenceRuleEditor extends LitElement {
.weekdays:last-child {
margin-bottom: 0;
}
.active {
--ha-chip-background-color: var(--primary-color);
--ha-chip-text-color: var(--text-primary-color);
}
`;
}

View File

@ -27,7 +27,7 @@ import type {
RowClickedEvent,
} from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu";
import "../../../components/ha-chip";
import "../../../components/ha-label";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-overflow-menu";
@ -202,11 +202,11 @@ class HaAutomationPicker extends LitElement {
template: (automation) =>
automation.disabled
? html`
<ha-chip>
<ha-label>
${this.hass.localize(
"ui.panel.config.automation.picker.disabled"
)}
</ha-chip>
</ha-label>
`
: "",
};

View File

@ -8,16 +8,17 @@ import {
} from "@mdi/js";
import { HassEntities, UnsubscribeFunc } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
css,
html,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import "../../../components/chips/ha-assist-chip";
import "../../../components/ha-button-menu";
import "../../../components/ha-card";
import "../../../components/ha-icon-button";
@ -34,9 +35,9 @@ import {
subscribeRepairsIssueRegistry,
} from "../../../data/repairs";
import {
UpdateEntity,
checkForEntityUpdates,
filterUpdateEntitiesWithInstall,
UpdateEntity,
} from "../../../data/update";
import { showQuickBar } from "../../../dialogs/quick-bar/show-dialog-quick-bar";
import { showRestartDialog } from "../../../dialogs/restart/show-dialog-restart";
@ -231,15 +232,17 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) {
></ha-config-repairs>
${totalRepairIssues > repairsIssues.length
? html`
<a class="button" href="/config/repairs">
${this.hass.localize(
<ha-assist-chip
href="/config/repairs"
.label=${this.hass.localize(
"ui.panel.config.repairs.more_repairs",
{
count:
totalRepairIssues - repairsIssues.length,
}
)}
</a>
>
</ha-assist-chip>
`
: ""}
`
@ -257,15 +260,17 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) {
></ha-config-updates>
${totalUpdates > canInstallUpdates.length
? html`
<a class="button" href="/config/updates">
${this.hass.localize(
<ha-assist-chip
href="/config/updates"
label=${this.hass.localize(
"ui.panel.config.updates.more_updates",
{
count:
totalUpdates - canInstallUpdates.length,
}
)}
</a>
>
</ha-assist-chip>
`
: ""}
`
@ -349,13 +354,8 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) {
text-decoration: none;
color: var(--primary-text-color);
}
a.button {
display: inline-block;
color: var(--primary-text-color);
padding: 6px 16px;
ha-assist-chip {
margin: 8px 16px 16px 16px;
border-radius: 32px;
border: 1px solid var(--divider-color);
}
.title {
font-size: 16px;

View File

@ -1,8 +1,8 @@
import { css, html, LitElement, nothing } from "lit";
import { property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-chip";
import "../../../../components/ha-chip-set";
import "../../../../components/chips/ha-assist-chip";
import "../../../../components/chips/ha-chip-set";
import { showAutomationEditor } from "../../../../data/automation";
import {
DeviceAction,
@ -77,17 +77,18 @@ export abstract class HaDeviceAutomationCard<
<ha-chip-set>
${automations.map(
(automation, idx) => html`
<ha-chip
<ha-assist-chip
filled
.index=${idx}
@click=${this._handleAutomationClicked}
class=${automation.metadata?.secondary ? "secondary" : ""}
>
${this._localizeDeviceAutomation(
.label=${this._localizeDeviceAutomation(
this.hass,
this.entityReg!,
automation
)}
</ha-chip>
>
</ha-assist-chip>
`
)}
</ha-chip-set>
@ -128,7 +129,10 @@ export abstract class HaDeviceAutomationCard<
color: var(--primary-text-color);
}
.secondary {
--ha-chip-background-color: rgba(var(--rgb-primary-text-color), 0.07);
--ha-assist-chip-filled-container-color: rgba(
var(--rgb-primary-text-color),
0.07
);
}
button.link {
color: var(--primary-color);

View File

@ -1,14 +1,13 @@
import "@material/mwc-button";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { computeRTLDirection } from "../../../common/util/compute_rtl";
import "../../../components/ha-chip";
import "../../../components/ha-chip-set";
import { createCloseHeading } from "../../../components/ha-dialog";
import "../../../components/ha-formfield";
import "../../../components/ha-help-tooltip";
import "../../../components/ha-label";
import "../../../components/ha-svg-icon";
import "../../../components/ha-switch";
import "../../../components/ha-textfield";
@ -76,16 +75,16 @@ class DialogUserDetail extends LitElement {
${badges.length === 0
? ""
: html`
<ha-chip-set>
<div class="badge-container">
${badges.map(
([icon, label]) => html`
<ha-chip hasIcon>
<ha-label>
<ha-svg-icon slot="icon" .path=${icon}></ha-svg-icon>
${label}
</ha-chip>
</ha-label>
`
)}
</ha-chip-set>
</div>
`}
<div class="form">
<ha-textfield
@ -286,10 +285,15 @@ class DialogUserDetail extends LitElement {
.secondary {
color: var(--secondary-text-color);
}
ha-chip-set,
ha-textfield {
display: block;
}
.badge-container {
margin-top: 4px;
}
.badge-container > * {
margin: 4px 4px 4px 0;
}
.state {
background-color: rgba(var(--rgb-primary-text-color), 0.15);
border-radius: 16px;

View File

@ -1,28 +1,29 @@
import { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
css,
html,
nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { HassEntity } from "home-assistant-js-websocket";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event";
import { alarmPanelIcon } from "../../../common/entity/alarm_panel_icon";
import { stateColorCss } from "../../../common/entity/state_color";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/chips/ha-assist-chip";
import "../../../components/ha-card";
import "../../../components/ha-chip";
import "../../../components/ha-textfield";
import type { HaTextField } from "../../../components/ha-textfield";
import {
callAlarmAction,
FORMAT_NUMBER,
ALARM_MODES,
AlarmMode,
FORMAT_NUMBER,
callAlarmAction,
} from "../../../data/alarm_control_panel";
import { UNAVAILABLE } from "../../../data/entity";
import type { HomeAssistant } from "../../../types";
@ -30,7 +31,6 @@ import { findEntities } from "../common/find-entities";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import type { LovelaceCard } from "../types";
import { AlarmPanelCardConfig, AlarmPanelCardConfigState } from "./types";
import { supportsFeature } from "../../../common/entity/supports-feature";
const BUTTONS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "clear"];
@ -190,18 +190,18 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
${this._config.name ||
stateObj.attributes.friendly_name ||
stateLabel}
<ha-chip
hasIcon
<ha-assist-chip
filled
style=${styleMap({
"--alarm-state-color": stateColorCss(stateObj),
})}
class=${classMap({ [stateObj.state]: true })}
@click=${this._handleMoreInfo}
.label=${stateLabel}
>
<ha-svg-icon slot="icon" .path=${alarmPanelIcon(stateObj.state)}>
</ha-svg-icon>
${stateLabel}
</ha-chip>
</ha-assist-chip>
</h1>
<div id="armActions" class="actions">
${(stateObj.state === "disarmed"
@ -312,10 +312,9 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
--alarm-state-color: var(--state-inactive-color);
}
ha-chip {
--ha-chip-background-color: var(--alarm-state-color);
ha-assist-chip {
--ha-assist-chip-filled-container-color: var(--alarm-state-color);
--primary-text-color: var(--text-primary-color);
line-height: initial;
}
.card-header {

View File

@ -9,7 +9,8 @@ import { computeTooltip } from "../common/compute-tooltip";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import "../../../components/ha-chip";
import "../../../components/chips/ha-assist-chip";
import "../../../components/chips/ha-chip-set";
import { haStyleScrollbar } from "../../../resources/styles";
@customElement("hui-buttons-base")
@ -20,7 +21,7 @@ export class HuiButtonsBase extends LitElement {
protected render(): TemplateResult {
return html`
<div class="ha-scrollbar">
<ha-chip-set class="ha-scrollbar">
${(this.configEntities || []).map((entityConf) => {
const stateObj = this.hass.states[entityConf.entity];
@ -31,7 +32,8 @@ export class HuiButtonsBase extends LitElement {
: "";
return html`
<ha-chip
<ha-assist-chip
filled
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(entityConf.hold_action),
@ -39,8 +41,7 @@ export class HuiButtonsBase extends LitElement {
})}
.config=${entityConf}
tabindex="0"
.hasIcon=${entityConf.show_icon !== false}
.noText=${!name}
.label=${name}
>
${entityConf.show_icon !== false
? html`
@ -56,11 +57,10 @@ export class HuiButtonsBase extends LitElement {
></state-badge>
`
: ""}
${name}
</ha-chip>
</ha-assist-chip>
`;
})}
</div>
</ha-chip-set>
`;
}
@ -74,7 +74,7 @@ export class HuiButtonsBase extends LitElement {
haStyleScrollbar,
css`
.ha-scrollbar {
padding: 8px;
padding: 12px;
padding-top: var(--padding-top, 8px);
padding-bottom: var(--padding-bottom, 8px);
width: 100%;
@ -102,8 +102,9 @@ export class HuiButtonsBase extends LitElement {
margin-left: -3px;
margin-top: -3px;
}
ha-chip {
padding: 4px;
ha-assist-chip state-badge {
margin-right: -4px;
--mdc-icon-size: 18px;
}
@media all and (max-width: 450px), all and (max-height: 500px) {
.ha-scrollbar {