Combo-box accessibility and other fixes (#13496)

This commit is contained in:
Steve Repsher 2022-08-30 21:50:04 -04:00 committed by GitHub
parent e463a997c1
commit ae4a37f23a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 54 additions and 45 deletions

View File

@ -119,7 +119,6 @@
"leaflet": "^1.7.1", "leaflet": "^1.7.1",
"leaflet-draw": "^1.0.4", "leaflet-draw": "^1.0.4",
"lit": "^2.1.2", "lit": "^2.1.2",
"lit-vaadin-helpers": "^0.3.0",
"marked": "^4.0.12", "marked": "^4.0.12",
"memoize-one": "^5.2.1", "memoize-one": "^5.2.1",
"node-vibrant": "3.2.1-alpha.1", "node-vibrant": "3.2.1-alpha.1",

View File

@ -18,7 +18,6 @@ export type LocalizeKeys =
| `ui.card.alarm_control_panel.${string}` | `ui.card.alarm_control_panel.${string}`
| `ui.card.weather.attributes.${string}` | `ui.card.weather.attributes.${string}`
| `ui.card.weather.cardinal_direction.${string}` | `ui.card.weather.cardinal_direction.${string}`
| `ui.components.combo-box.${string}`
| `ui.components.logbook.${string}` | `ui.components.logbook.${string}`
| `ui.components.selectors.file.${string}` | `ui.components.selectors.file.${string}`
| `ui.dialogs.entity_registry.editor.${string}` | `ui.dialogs.entity_registry.editor.${string}`

View File

@ -1,7 +1,7 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";

View File

@ -1,7 +1,7 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";

View File

@ -1,7 +1,7 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";

View File

@ -1,6 +1,6 @@
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";

View File

@ -1,5 +1,5 @@
import { html, LitElement, TemplateResult } from "lit"; import { html, LitElement, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { isComponentLoaded } from "../common/config/is_component_loaded"; import { isComponentLoaded } from "../common/config/is_component_loaded";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";

View File

@ -1,6 +1,6 @@
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";

View File

@ -9,8 +9,9 @@ import type {
} from "@vaadin/combo-box/vaadin-combo-box-light"; } from "@vaadin/combo-box/vaadin-combo-box-light";
import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles"; import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { ComboBoxLitRenderer, comboBoxRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer, comboBoxRenderer } from "@vaadin/combo-box/lit";
import { customElement, property, query } from "lit/decorators"; import { customElement, property, query } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import "./ha-icon-button"; import "./ha-icon-button";
@ -72,31 +73,31 @@ export class HaComboBox extends LitElement {
@property({ attribute: "error-message" }) public errorMessage?: string; @property({ attribute: "error-message" }) public errorMessage?: string;
@property({ type: Boolean }) public invalid?: boolean; @property({ type: Boolean }) public invalid = false;
@property({ type: Boolean }) public icon?: boolean; @property({ type: Boolean }) public icon = false;
@property() public items?: any[]; @property({ attribute: false }) public items?: any[];
@property() public filteredItems?: any[]; @property({ attribute: false }) public filteredItems?: any[];
@property({ attribute: "allow-custom-value", type: Boolean }) @property({ attribute: "allow-custom-value", type: Boolean })
public allowCustomValue?: boolean; public allowCustomValue = false;
@property({ attribute: "item-value-path" }) public itemValuePath?: string; @property({ attribute: "item-value-path" }) public itemValuePath = "value";
@property({ attribute: "item-label-path" }) public itemLabelPath?: string; @property({ attribute: "item-label-path" }) public itemLabelPath = "label";
@property({ attribute: "item-id-path" }) public itemIdPath?: string; @property({ attribute: "item-id-path" }) public itemIdPath?: string;
@property() public renderer?: ComboBoxLitRenderer<any>; @property() public renderer?: ComboBoxLitRenderer<any>;
@property({ type: Boolean }) public disabled?: boolean; @property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required?: boolean; @property({ type: Boolean }) public required = false;
@property({ type: Boolean, reflect: true, attribute: "opened" }) @property({ type: Boolean, reflect: true, attribute: "opened" })
private _opened?: boolean; public opened?: boolean;
@query("vaadin-combo-box-light", true) private _comboBox!: ComboBoxLight; @query("vaadin-combo-box-light", true) private _comboBox!: ComboBoxLight;
@ -149,37 +150,45 @@ export class HaComboBox extends LitElement {
attr-for-value="value" attr-for-value="value"
> >
<ha-textfield <ha-textfield
.label=${this.label} label=${ifDefined(this.label)}
.placeholder=${this.placeholder} placeholder=${ifDefined(this.placeholder)}
.disabled=${this.disabled} ?disabled=${this.disabled}
.required=${this.required} ?required=${this.required}
.validationMessage=${this.validationMessage} validationMessage=${ifDefined(this.validationMessage)}
.errorMessage=${this.errorMessage} .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;"
role="none presentation"
></div>`}
.icon=${this.icon} .icon=${this.icon}
.invalid=${this.invalid} .invalid=${this.invalid}
.helper=${this.helper} helper=${ifDefined(this.helper)}
helperPersistent helperPersistent
> >
<slot name="icon" slot="leadingIcon"></slot> <slot name="icon" slot="leadingIcon"></slot>
</ha-textfield> </ha-textfield>
${this.value ${this.value
? html`<ha-svg-icon ? html`<ha-svg-icon
aria-label=${this.hass?.localize("ui.components.combo-box.clear")} role="button"
tabindex="-1"
aria-label=${ifDefined(this.hass?.localize("ui.common.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")} role="button"
tabindex="-1"
aria-label=${ifDefined(this.label)}
aria-expanded=${this.opened ? "true" : "false"}
class="toggle-button" class="toggle-button"
.path=${this._opened ? mdiMenuUp : mdiMenuDown} .path=${this.opened ? mdiMenuUp : mdiMenuDown}
@click=${this._toggleOpen} @click=${this._toggleOpen}
></ha-svg-icon> ></ha-svg-icon>
</vaadin-combo-box-light> </vaadin-combo-box-light>
@ -199,7 +208,7 @@ export class HaComboBox extends LitElement {
} }
private _toggleOpen(ev: Event) { private _toggleOpen(ev: Event) {
if (this._opened) { if (this.opened) {
this._comboBox?.close(); this._comboBox?.close();
ev.stopPropagation(); ev.stopPropagation();
} else { } else {
@ -211,7 +220,7 @@ export class HaComboBox extends LitElement {
const opened = ev.detail.value; const opened = ev.detail.value;
// delay this so we can handle click event before setting _opened // delay this so we can handle click event before setting _opened
setTimeout(() => { setTimeout(() => {
this._opened = opened; this.opened = opened;
}, 0); }, 0);
// @ts-ignore // @ts-ignore
fireEvent(this, ev.type, ev.detail); fireEvent(this, ev.type, ev.detail);

View File

@ -1,6 +1,6 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { html, LitElement, TemplateResult } from "lit"; import { html, LitElement, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
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 { PolymerChangedEvent } from "../polymer-types"; import { PolymerChangedEvent } from "../polymer-types";

View File

@ -1,5 +1,5 @@
import { css, html, LitElement, TemplateResult } from "lit"; import { css, html, LitElement, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
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";

View File

@ -24,6 +24,7 @@ export class HaIconSelector extends LitElement {
protected render() { protected render() {
return html` return html`
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.label=${this.label} .label=${this.label}
.value=${this.value} .value=${this.value}
.required=${this.required} .required=${this.required}

View File

@ -1,5 +1,5 @@
import { html, LitElement } from "lit"; import { html, LitElement } from "lit";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { property, state } from "lit/decorators"; import { property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";

View File

@ -2,7 +2,7 @@ import "@material/mwc-button";
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { ComboBoxLitRenderer } from "lit-vaadin-helpers"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-circular-progress"; import "../../../components/ha-circular-progress";
import "../../../components/ha-combo-box"; import "../../../components/ha-combo-box";

View File

@ -315,6 +315,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
@input=${this._nameChanged} @input=${this._nameChanged}
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
@value-changed=${this._iconChanged} @value-changed=${this._iconChanged}
.label=${this.hass.localize("ui.dialogs.entity_registry.editor.icon")} .label=${this.hass.localize("ui.dialogs.entity_registry.editor.icon")}

View File

@ -82,6 +82,7 @@ class HaCounterForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -60,6 +60,7 @@ class HaInputBooleanForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -60,6 +60,7 @@ class HaInputButtonForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -74,6 +74,7 @@ class HaInputDateTimeForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -91,6 +91,7 @@ class HaInputNumberForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -72,6 +72,7 @@ class HaInputSelectForm extends LitElement {
@input=${this._valueChanged} @input=${this._valueChanged}
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -79,6 +79,7 @@ class HaInputTextForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -126,6 +126,7 @@ class HaScheduleForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -68,6 +68,7 @@ class HaTimerForm extends LitElement {
dialogInitialFocus dialogInitialFocus
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.value=${this._icon} .value=${this._icon}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -301,6 +301,7 @@ export class HaSceneEditor extends SubscribeMixin(
)} )}
></ha-textfield> ></ha-textfield>
<ha-icon-picker <ha-icon-picker
.hass=${this.hass}
.label=${this.hass.localize( .label=${this.hass.localize(
"ui.panel.config.scene.editor.icon" "ui.panel.config.scene.editor.icon"
)} )}

View File

@ -9108,7 +9108,6 @@ fsevents@^1.2.7:
lint-staged: ^13.0.3 lint-staged: ^13.0.3
lit: ^2.1.2 lit: ^2.1.2
lit-analyzer: ^1.2.1 lit-analyzer: ^1.2.1
lit-vaadin-helpers: ^0.3.0
lodash.template: ^4.5.0 lodash.template: ^4.5.0
magic-string: ^0.25.7 magic-string: ^0.25.7
map-stream: ^0.0.7 map-stream: ^0.0.7
@ -10749,15 +10748,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"lit-vaadin-helpers@npm:^0.3.0":
version: 0.3.0
resolution: "lit-vaadin-helpers@npm:0.3.0"
dependencies:
lit: ^2.0.0
checksum: c96df23272442b3f6c38273721306eb650ea27876fade53ccfbb0158eef838865b1727b9657d35a80f55d94b1418106be63794adb064b79f35dfe3014fb435ff
languageName: node
linkType: hard
"lit@npm:^2.1.2": "lit@npm:^2.1.2":
version: 2.1.2 version: 2.1.2
resolution: "lit@npm:2.1.2" resolution: "lit@npm:2.1.2"