mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Restore screen readers support on pickers (#25553)
This commit is contained in:
parent
9b7db191a6
commit
3355986585
@ -317,6 +317,7 @@ export class HaEntityPicker extends LitElement {
|
||||
const secondary = [areaName, entityName ? deviceName : undefined]
|
||||
.filter(Boolean)
|
||||
.join(isRTL ? " ◂ " : " ▸ ");
|
||||
const a11yLabel = [deviceName, entityName].filter(Boolean).join(" - ");
|
||||
|
||||
return {
|
||||
id: entityId,
|
||||
@ -332,6 +333,7 @@ export class HaEntityPicker extends LitElement {
|
||||
friendlyName,
|
||||
entityId,
|
||||
].filter(Boolean) as string[],
|
||||
a11y_label: a11yLabel,
|
||||
stateObj: stateObj,
|
||||
};
|
||||
});
|
||||
|
@ -267,6 +267,7 @@ export class HaStatisticPicker extends LitElement {
|
||||
const secondary = [areaName, entityName ? deviceName : undefined]
|
||||
.filter(Boolean)
|
||||
.join(isRTL ? " ◂ " : " ▸ ");
|
||||
const a11yLabel = [deviceName, entityName].filter(Boolean).join(" - ");
|
||||
|
||||
const sortingPrefix = `${TYPE_ORDER.indexOf("entity")}`;
|
||||
output.push({
|
||||
@ -274,6 +275,7 @@ export class HaStatisticPicker extends LitElement {
|
||||
statistic_id: id,
|
||||
primary,
|
||||
secondary,
|
||||
a11y_label: a11yLabel,
|
||||
stateObj: stateObj,
|
||||
type: "entity",
|
||||
sorting_label: [sortingPrefix, deviceName, entityName].join("_"),
|
||||
|
24
src/components/ha-combo-box-textfield.ts
Normal file
24
src/components/ha-combo-box-textfield.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { HaTextField } from "./ha-textfield";
|
||||
|
||||
@customElement("ha-combo-box-textfield")
|
||||
export class HaComboBoxTextField extends HaTextField {
|
||||
@property({ type: Boolean, attribute: "disable-set-value" })
|
||||
public disableSetValue = false;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
super.willUpdate(changedProps);
|
||||
if (changedProps.has("value")) {
|
||||
if (this.disableSetValue) {
|
||||
this.value = changedProps.get("value") as string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-combo-box-textfield": HaComboBoxTextField;
|
||||
}
|
||||
}
|
@ -12,11 +12,12 @@ import type {
|
||||
import { registerStyles } from "@vaadin/vaadin-themable-mixin/register-styles";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import "./ha-combo-box-item";
|
||||
import "./ha-combo-box-textfield";
|
||||
import "./ha-icon-button";
|
||||
import "./ha-textfield";
|
||||
import type { HaTextField } from "./ha-textfield";
|
||||
@ -108,9 +109,14 @@ export class HaComboBox extends LitElement {
|
||||
@property({ type: Boolean, attribute: "hide-clear-icon" })
|
||||
public hideClearIcon = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "clear-initial-value" })
|
||||
public clearInitialValue = false;
|
||||
|
||||
@query("vaadin-combo-box-light", true) private _comboBox!: ComboBoxLight;
|
||||
|
||||
@query("ha-textfield", true) private _inputElement!: HaTextField;
|
||||
@query("ha-combo-box-textfield", true) private _inputElement!: HaTextField;
|
||||
|
||||
@state({ type: Boolean }) private _disableSetValue = false;
|
||||
|
||||
private _overlayMutationObserver?: MutationObserver;
|
||||
|
||||
@ -171,7 +177,7 @@ export class HaComboBox extends LitElement {
|
||||
@value-changed=${this._valueChanged}
|
||||
attr-for-value="value"
|
||||
>
|
||||
<ha-textfield
|
||||
<ha-combo-box-textfield
|
||||
label=${ifDefined(this.label)}
|
||||
placeholder=${ifDefined(this.placeholder)}
|
||||
?disabled=${this.disabled}
|
||||
@ -191,9 +197,10 @@ export class HaComboBox extends LitElement {
|
||||
.invalid=${this.invalid}
|
||||
.helper=${this.helper}
|
||||
helperPersistent
|
||||
.disableSetValue=${this._disableSetValue}
|
||||
>
|
||||
<slot name="icon" slot="leadingIcon"></slot>
|
||||
</ha-textfield>
|
||||
</ha-combo-box-textfield>
|
||||
${this.value && !this.hideClearIcon
|
||||
? html`<ha-svg-icon
|
||||
role="button"
|
||||
@ -249,6 +256,18 @@ export class HaComboBox extends LitElement {
|
||||
fireEvent(this, "opened-changed", { value: ev.detail.value });
|
||||
}, 0);
|
||||
|
||||
if (this.clearInitialValue) {
|
||||
this.setTextFieldValue("");
|
||||
if (opened) {
|
||||
// Wait 100ms to be sure vaddin-combo-box-light already tried to set the value
|
||||
setTimeout(() => {
|
||||
this._disableSetValue = false;
|
||||
}, 100);
|
||||
} else {
|
||||
this._disableSetValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
const overlay = document.querySelector<HTMLElement>(
|
||||
"vaadin-combo-box-overlay"
|
||||
@ -342,10 +361,10 @@ export class HaComboBox extends LitElement {
|
||||
position: relative;
|
||||
--vaadin-combo-box-overlay-max-height: calc(45vh - 56px);
|
||||
}
|
||||
ha-textfield {
|
||||
ha-combo-box-textfield {
|
||||
width: 100%;
|
||||
}
|
||||
ha-textfield > ha-icon-button {
|
||||
ha-combo-box-textfield > ha-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
|
@ -2,6 +2,7 @@ import type { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
||||
import type { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light";
|
||||
import { css, html, LitElement, nothing, type CSSResultGroup } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import "./ha-combo-box-item";
|
||||
@ -74,6 +75,7 @@ export class HaGenericPicker extends LitElement {
|
||||
<ha-picker-field
|
||||
type="button"
|
||||
compact
|
||||
aria-label=${ifDefined(this.label)}
|
||||
@click=${this.open}
|
||||
@clear=${this._clear}
|
||||
.placeholder=${this.placeholder}
|
||||
|
@ -18,6 +18,7 @@ import "./ha-icon";
|
||||
export interface PickerComboBoxItem {
|
||||
id: string;
|
||||
primary: string;
|
||||
a11y_label?: string;
|
||||
secondary?: string;
|
||||
search_labels?: string[];
|
||||
sorting_label?: string;
|
||||
@ -27,7 +28,7 @@ export interface PickerComboBoxItem {
|
||||
|
||||
// Hack to force empty label to always display empty value by default in the search field
|
||||
export interface PickerComboBoxItemWithLabel extends PickerComboBoxItem {
|
||||
label: "";
|
||||
a11y_label: string;
|
||||
}
|
||||
|
||||
const NO_MATCHING_ITEMS_FOUND_ID = "___no_matching_items_found___";
|
||||
@ -109,7 +110,7 @@ export class HaPickerComboBox extends LitElement {
|
||||
id: NO_MATCHING_ITEMS_FOUND_ID,
|
||||
primary: label || localize("ui.components.combo-box.no_match"),
|
||||
icon_path: mdiMagnify,
|
||||
label: "",
|
||||
a11y_label: label || localize("ui.components.combo-box.no_match"),
|
||||
})
|
||||
);
|
||||
|
||||
@ -118,7 +119,7 @@ export class HaPickerComboBox extends LitElement {
|
||||
|
||||
return items.map<PickerComboBoxItemWithLabel>((item) => ({
|
||||
...item,
|
||||
label: "",
|
||||
a11y_label: item.a11y_label || item.primary,
|
||||
}));
|
||||
};
|
||||
|
||||
@ -128,7 +129,7 @@ export class HaPickerComboBox extends LitElement {
|
||||
const sortedItems = items
|
||||
.map<PickerComboBoxItemWithLabel>((item) => ({
|
||||
...item,
|
||||
label: "",
|
||||
a11y_label: item.a11y_label || item.primary,
|
||||
}))
|
||||
.sort((entityA, entityB) =>
|
||||
caseInsensitiveStringCompare(
|
||||
@ -175,7 +176,8 @@ export class HaPickerComboBox extends LitElement {
|
||||
<ha-combo-box
|
||||
item-id-path="id"
|
||||
item-value-path="id"
|
||||
item-label-path="label"
|
||||
item-label-path="a11y_label"
|
||||
clear-initial-value
|
||||
.hass=${this.hass}
|
||||
.value=${this._value}
|
||||
.label=${this.label}
|
||||
|
Loading…
x
Reference in New Issue
Block a user