Convert icon picker to ha-combobox (#11586)

Co-authored-by: Zack <zackbarett@hey.com>
This commit is contained in:
Bram Kragten 2022-02-07 17:43:49 +01:00 committed by GitHub
parent 869fa91ae5
commit 2cb37820df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 83 deletions

View File

@ -1,5 +1,4 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import "@material/mwc-textfield/mwc-textfield";
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js"; import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@vaadin/combo-box/theme/material/vaadin-combo-box-light"; import "@vaadin/combo-box/theme/material/vaadin-combo-box-light";
import type { ComboBoxLight } from "@vaadin/combo-box/vaadin-combo-box-light"; import type { ComboBoxLight } from "@vaadin/combo-box/vaadin-combo-box-light";
@ -11,6 +10,7 @@ import { fireEvent } from "../common/dom/fire_event";
import { PolymerChangedEvent } from "../polymer-types"; import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import "./ha-icon-button"; import "./ha-icon-button";
import "./ha-textfield";
registerStyles( registerStyles(
"vaadin-combo-box-item", "vaadin-combo-box-item",
@ -54,12 +54,22 @@ registerStyles(
@customElement("ha-combo-box") @customElement("ha-combo-box")
export class HaComboBox extends LitElement { export class HaComboBox extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property() public label?: string; @property() public label?: string;
@property() public value?: string; @property() public value?: string;
@property() public placeholder?: string;
@property() public validationMessage?: string;
@property({ attribute: "error-message" }) public errorMessage?: string;
@property({ type: Boolean }) public invalid?: boolean;
@property({ type: Boolean }) public icon?: boolean;
@property() public items?: any[]; @property() public items?: any[];
@property() public filteredItems?: any[]; @property() public filteredItems?: any[];
@ -115,27 +125,33 @@ export class HaComboBox extends LitElement {
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
attr-for-value="value" attr-for-value="value"
> >
<mwc-textfield <ha-textfield
.label=${this.label} .label=${this.label}
.placeholder=${this.placeholder}
.disabled=${this.disabled} .disabled=${this.disabled}
.validationMessage=${this.validationMessage}
.errorMessage=${this.errorMessage}
class="input" class="input"
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
autocorrect="off" autocorrect="off"
spellcheck="false" spellcheck="false"
.suffix=${html`<div style="width: 28px;"></div>`} .suffix=${html`<div style="width: 28px;"></div>`}
.icon=${this.icon}
.invalid=${this.invalid}
> >
</mwc-textfield> <slot name="icon" slot="leadingIcon"></slot>
</ha-textfield>
${this.value ${this.value
? html`<ha-svg-icon ? html`<ha-svg-icon
aria-label=${this.hass.localize("ui.components.combo-box.clear")} aria-label=${this.hass?.localize("ui.components.combo-box.clear")}
class="clear-button" class="clear-button"
.path=${mdiClose} .path=${mdiClose}
@click=${this._clearValue} @click=${this._clearValue}
></ha-svg-icon>` ></ha-svg-icon>`
: ""} : ""}
<ha-svg-icon <ha-svg-icon
aria-label=${this.hass.localize("ui.components.combo-box.show")} aria-label=${this.hass?.localize("ui.components.combo-box.show")}
class="toggle-button" class="toggle-button"
.path=${this._opened ? mdiMenuUp : mdiMenuDown} .path=${this._opened ? mdiMenuUp : mdiMenuDown}
@click=${this._toggleOpen} @click=${this._toggleOpen}
@ -198,10 +214,10 @@ export class HaComboBox extends LitElement {
vaadin-combo-box-light { vaadin-combo-box-light {
position: relative; position: relative;
} }
mwc-textfield { ha-textfield {
width: 100%; width: 100%;
} }
mwc-textfield > ha-icon-button { ha-textfield > ha-icon-button {
--mdc-icon-button-size: 24px; --mdc-icon-button-size: 24px;
padding: 2px; padding: 2px;
color: var(--secondary-text-color); color: var(--secondary-text-color);

View File

@ -1,16 +1,13 @@
import { mdiCheck, mdiMenuDown, mdiMenuUp } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-item/paper-item-body";
import "@vaadin/combo-box/theme/material/vaadin-combo-box-light";
import { css, html, LitElement, TemplateResult } from "lit"; import { css, html, LitElement, TemplateResult } from "lit";
import { ComboBoxLitRenderer, comboBoxRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "lit-vaadin-helpers";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { customIcons } from "../data/custom_icons"; import { customIcons } from "../data/custom_icons";
import { PolymerChangedEvent } from "../polymer-types"; import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types";
import "./ha-combo-box";
import type { HaComboBox } from "./ha-combo-box";
import "./ha-icon"; import "./ha-icon";
import "./ha-icon-button";
type IconItem = { type IconItem = {
icon: string; icon: string;
@ -19,35 +16,17 @@ type IconItem = {
let iconItems: IconItem[] = []; let iconItems: IconItem[] = [];
// eslint-disable-next-line lit/prefer-static-styles // eslint-disable-next-line lit/prefer-static-styles
const rowRenderer: ComboBoxLitRenderer<IconItem> = (item) => html`<style> const rowRenderer: ComboBoxLitRenderer<IconItem> = (item) => html`<mwc-list-item
paper-icon-item { graphic="avatar"
padding: 0; >
margin: -8px; <ha-icon .icon=${item.icon} slot="graphic"></ha-icon>
} ${item.icon}
#content { </mwc-list-item>`;
display: flex;
align-items: center;
}
ha-svg-icon {
padding-left: 2px;
color: var(--secondary-text-color);
}
:host(:not([selected])) ha-svg-icon {
display: none;
}
:host([selected]) paper-icon-item {
margin-left: 0;
}
</style>
<ha-svg-icon .path=${mdiCheck}></ha-svg-icon>
<paper-icon-item>
<ha-icon .icon=${item.icon} slot="item-icon"></ha-icon>
<paper-item-body>${item.icon}</paper-item-body>
</paper-icon-item>`;
@customElement("ha-icon-picker") @customElement("ha-icon-picker")
export class HaIconPicker extends LitElement { export class HaIconPicker extends LitElement {
@property() public hass?: HomeAssistant;
@property() public value?: string; @property() public value?: string;
@property() public label?: string; @property() public label?: string;
@ -64,51 +43,40 @@ export class HaIconPicker extends LitElement {
@state() private _opened = false; @state() private _opened = false;
@query("vaadin-combo-box-light", true) private comboBox!: HTMLElement; @query("ha-combo-box", true) private comboBox!: HaComboBox;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<vaadin-combo-box-light <ha-combo-box
.hass=${this.hass}
item-value-path="icon" item-value-path="icon"
item-label-path="icon" item-label-path="icon"
.value=${this._value} .value=${this._value}
allow-custom-value allow-custom-value
.filteredItems=${iconItems} .filteredItems=${iconItems}
${comboBoxRenderer(rowRenderer)} .label=${this.label}
.disabled=${this.disabled}
.placeholder=${this.placeholder}
.errorMessage=${this.errorMessage}
.invalid=${this.invalid}
.renderer=${rowRenderer}
icon
@opened-changed=${this._openedChanged} @opened-changed=${this._openedChanged}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@filter-changed=${this._filterChanged} @filter-changed=${this._filterChanged}
> >
<paper-input ${this._value || this.placeholder
.label=${this.label} ? html`
.placeholder=${this.placeholder} <ha-icon .icon=${this._value || this.placeholder} slot="icon">
.disabled=${this.disabled} </ha-icon>
class="input" `
autocapitalize="none" : this.fallbackPath
autocomplete="off" ? html`<ha-svg-icon
autocorrect="off" .path=${this.fallbackPath}
spellcheck="false" slot="icon"
.errorMessage=${this.errorMessage} ></ha-svg-icon>`
.invalid=${this.invalid} : ""}
> </ha-combo-box>
${this._value || this.placeholder
? html`
<ha-icon .icon=${this._value || this.placeholder} slot="prefix">
</ha-icon>
`
: this.fallbackPath
? html`<ha-svg-icon
.path=${this.fallbackPath}
slot="prefix"
></ha-svg-icon>`
: ""}
<ha-icon-button
.path=${this._opened ? mdiMenuUp : mdiMenuDown}
slot="suffix"
class="toggle-button"
></ha-icon-button>
</paper-input>
</vaadin-combo-box-light>
`; `;
} }
@ -150,6 +118,7 @@ export class HaIconPicker extends LitElement {
} }
private _valueChanged(ev: PolymerChangedEvent<string>) { private _valueChanged(ev: PolymerChangedEvent<string>) {
ev.stopPropagation();
this._setValue(ev.detail.value); this._setValue(ev.detail.value);
} }
@ -158,7 +127,7 @@ export class HaIconPicker extends LitElement {
fireEvent( fireEvent(
this, this,
"value-changed", "value-changed",
{ value }, { value: this._value },
{ {
bubbles: false, bubbles: false,
composed: false, composed: false,
@ -211,11 +180,6 @@ export class HaIconPicker extends LitElement {
*[slot="prefix"] { *[slot="prefix"] {
margin-right: 8px; margin-right: 8px;
} }
paper-input > ha-icon-button {
--mdc-icon-button-size: 24px;
padding: 2px;
color: var(--secondary-text-color);
}
`; `;
} }
} }

View File

@ -1,10 +1,31 @@
import { TextField } from "@material/mwc-textfield"; import { TextField } from "@material/mwc-textfield";
import { TemplateResult, html } from "lit"; import { TemplateResult, html, PropertyValues } from "lit";
import { customElement } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@customElement("ha-textfield") @customElement("ha-textfield")
export class HaTextField extends TextField { export class HaTextField extends TextField {
override renderIcon(_icon: string, isTrailingIcon = false): TemplateResult { @property({ type: Boolean }) public invalid?: boolean;
@property({ attribute: "error-message" }) public errorMessage?: string;
override updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (
(changedProperties.has("invalid") &&
(this.invalid || changedProperties.get("invalid") !== undefined)) ||
changedProperties.has("errorMessage")
) {
this.setCustomValidity(
this.invalid ? this.errorMessage || "Invalid" : ""
);
this.reportValidity();
}
}
protected override renderIcon(
_icon: string,
isTrailingIcon = false
): TemplateResult {
const type = isTrailingIcon ? "trailing" : "leading"; const type = isTrailingIcon ? "trailing" : "leading";
return html` return html`