diff --git a/src/components/entity/ha-entity-picker.ts b/src/components/entity/ha-entity-picker.ts
index 397685a32b..5968b4a103 100644
--- a/src/components/entity/ha-entity-picker.ts
+++ b/src/components/entity/ha-entity-picker.ts
@@ -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,
};
});
diff --git a/src/components/entity/ha-statistic-picker.ts b/src/components/entity/ha-statistic-picker.ts
index 3b6e262fc3..955071a8f2 100644
--- a/src/components/entity/ha-statistic-picker.ts
+++ b/src/components/entity/ha-statistic-picker.ts
@@ -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("_"),
diff --git a/src/components/ha-combo-box-textfield.ts b/src/components/ha-combo-box-textfield.ts
new file mode 100644
index 0000000000..19c87f268c
--- /dev/null
+++ b/src/components/ha-combo-box-textfield.ts
@@ -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;
+ }
+}
diff --git a/src/components/ha-combo-box.ts b/src/components/ha-combo-box.ts
index 9804ebe774..58ed2e1f51 100644
--- a/src/components/ha-combo-box.ts
+++ b/src/components/ha-combo-box.ts
@@ -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"
>
-
-
+
${this.value && !this.hideClearIcon
? html` {
+ this._disableSetValue = false;
+ }, 100);
+ } else {
+ this._disableSetValue = true;
+ }
+ }
+
if (opened) {
const overlay = document.querySelector(
"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);
diff --git a/src/components/ha-generic-picker.ts b/src/components/ha-generic-picker.ts
index 38ba4487b1..2c699382fd 100644
--- a/src/components/ha-generic-picker.ts
+++ b/src/components/ha-generic-picker.ts
@@ -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 {
((item) => ({
...item,
- label: "",
+ a11y_label: item.a11y_label || item.primary,
}));
};
@@ -128,7 +129,7 @@ export class HaPickerComboBox extends LitElement {
const sortedItems = items
.map((item) => ({
...item,
- label: "",
+ a11y_label: item.a11y_label || item.primary,
}))
.sort((entityA, entityB) =>
caseInsensitiveStringCompare(
@@ -175,7 +176,8 @@ export class HaPickerComboBox extends LitElement {