diff --git a/pyproject.toml b/pyproject.toml
index 2eec5c49cb..0a5a6fb847 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
-version = "20250509.0"
+version = "20250516.0"
license = "Apache-2.0"
license-files = ["LICENSE*"]
description = "The Home Assistant frontend"
diff --git a/src/components/entity/ha-entity-combo-box.ts b/src/components/entity/ha-entity-combo-box.ts
index db18168c3a..5d31baa43b 100644
--- a/src/components/entity/ha-entity-combo-box.ts
+++ b/src/components/entity/ha-entity-combo-box.ts
@@ -178,7 +178,9 @@ export class HaEntityComboBox extends LitElement {
: nothing}
${item.domain_name && !showEntityId
? html`
-
${item.domain_name}
+
+ ${item.domain_name}
+
`
: nothing}
@@ -408,7 +410,9 @@ export class HaEntityComboBox extends LitElement {
protected render(): TemplateResult {
return html`
;
- }
->;
+ };
+}>;
interface SystemHealthEventInitial {
type: "initial";
diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts
index 68833ad0bf..f27ff5b428 100644
--- a/src/dialogs/quick-bar/ha-quick-bar.ts
+++ b/src/dialogs/quick-bar/ha-quick-bar.ts
@@ -9,50 +9,50 @@ import {
mdiReload,
mdiServerNetwork,
} from "@mdi/js";
+import Fuse from "fuse.js";
import type { TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
-import Fuse from "fuse.js";
import { canShowPage } from "../../common/config/can_show_page";
import { componentsWithService } from "../../common/config/components_with_service";
import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { fireEvent } from "../../common/dom/fire_event";
+import { computeAreaName } from "../../common/entity/compute_area_name";
import {
computeDeviceName,
computeDeviceNameDisplay,
} from "../../common/entity/compute_device_name";
+import { computeDomain } from "../../common/entity/compute_domain";
+import { computeEntityName } from "../../common/entity/compute_entity_name";
+import { computeStateName } from "../../common/entity/compute_state_name";
+import { getEntityContext } from "../../common/entity/context/get_entity_context";
import { navigate } from "../../common/navigate";
import { caseInsensitiveStringCompare } from "../../common/string/compare";
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
+import { computeRTL } from "../../common/util/compute_rtl";
import { debounce } from "../../common/util/debounce";
import "../../components/ha-icon-button";
import "../../components/ha-label";
import "../../components/ha-list";
+import "../../components/ha-md-list-item";
import "../../components/ha-spinner";
import "../../components/ha-textfield";
import "../../components/ha-tip";
-import "../../components/ha-md-list-item";
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
import { domainToName } from "../../data/integration";
import { getPanelNameTranslationKey } from "../../data/panel";
import type { PageNavigation } from "../../layouts/hass-tabs-subpage";
import { configSections } from "../../panels/config/ha-panel-config";
+import { HaFuse } from "../../resources/fuse";
import { haStyleDialog, haStyleScrollbar } from "../../resources/styles";
import { loadVirtualizer } from "../../resources/virtualizer";
import type { HomeAssistant } from "../../types";
import { showConfirmationDialog } from "../generic/show-dialog-box";
import { showShortcutsDialog } from "../shortcuts/show-shortcuts-dialog";
import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar";
-import { getEntityContext } from "../../common/entity/context/get_entity_context";
-import { computeEntityName } from "../../common/entity/compute_entity_name";
-import { computeAreaName } from "../../common/entity/compute_area_name";
-import { computeRTL } from "../../common/util/compute_rtl";
-import { computeDomain } from "../../common/entity/compute_domain";
-import { computeStateName } from "../../common/entity/compute_state_name";
-import { HaFuse } from "../../resources/fuse";
interface QuickBarItem extends ScorableTextItem {
primaryText: string;
@@ -152,11 +152,6 @@ export class QuickBar extends LitElement {
}
}
- protected firstUpdated(changedProps) {
- super.firstUpdated(changedProps);
- this.hass.loadBackendTranslation("title");
- }
-
private _getItems = memoizeOne(
(
mode: QuickBarMode,
@@ -304,7 +299,8 @@ export class QuickBar extends LitElement {
} else if (this._mode === QuickBarMode.Device) {
this._deviceItems = this._deviceItems || this._generateDeviceItems();
} else {
- this._entityItems = this._entityItems || this._generateEntityItems();
+ this._entityItems =
+ this._entityItems || (await this._generateEntityItems());
}
}
@@ -386,7 +382,7 @@ export class QuickBar extends LitElement {
`
: nothing}
${item.translatedDomain && !showEntityId
- ? html`
+ ? html`
${item.translatedDomain}
`
: nothing}
@@ -581,9 +577,11 @@ export class QuickBar extends LitElement {
);
}
- private _generateEntityItems(): EntityItem[] {
+ private async _generateEntityItems(): Promise
{
const isRTL = computeRTL(this.hass);
+ await this.hass.loadBackendTranslation("title");
+
return Object.keys(this.hass.states)
.map((entityId) => {
const stateObj = this.hass.states[entityId];
@@ -1027,7 +1025,7 @@ export class QuickBar extends LitElement {
font-size: var(--ha-font-size-xs);
}
- ha-md-list-item [slot="trailing-supporting-text"] {
+ ha-md-list-item .domain {
font-size: var(--ha-font-size-s);
font-weight: var(--ha-font-weight-normal);
line-height: var(--ha-line-height-normal);
diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
index 1b2a0e88a0..a9f1a8d771 100644
--- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
+++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
@@ -57,16 +57,22 @@ export class HaVoiceCommandDialog extends LitElement {
public async showDialog(
params: Required
): Promise {
+ await this._loadPipelines();
+ const pipelinesIds = this._pipelines?.map((pipeline) => pipeline.id) || [];
if (
params.pipeline_id === "preferred" ||
(params.pipeline_id === "last_used" && !this._pipelineId)
) {
- await this._loadPipelines();
this._pipelineId = this._preferredPipeline;
} else if (!["last_used", "preferred"].includes(params.pipeline_id)) {
this._pipelineId = params.pipeline_id;
}
+ // If the pipeline id is not in the list of pipelines, set it to preferred
+ if (this._pipelineId && !pipelinesIds.includes(this._pipelineId)) {
+ this._pipelineId = this._preferredPipeline;
+ }
+
this._startListening = params.start_listening;
this._opened = true;
}
diff --git a/src/panels/config/automation/action/types/ha-automation-action-choose.ts b/src/panels/config/automation/action/types/ha-automation-action-choose.ts
index 07498c4606..2c193cc024 100644
--- a/src/panels/config/automation/action/types/ha-automation-action-choose.ts
+++ b/src/panels/config/automation/action/types/ha-automation-action-choose.ts
@@ -18,6 +18,8 @@ export class HaChooseAction extends LitElement implements ActionElement {
@property({ attribute: false }) public action!: ChooseAction;
+ @property({ type: Boolean }) public narrow = false;
+
@state() private _showDefault = false;
public static get defaultConfig(): ChooseAction {
@@ -35,6 +37,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
.disabled=${this.disabled}
@value-changed=${this._optionsChanged}
.hass=${this.hass}
+ .narrow=${this.narrow}
>
${this._showDefault || action.default
@@ -49,6 +52,7 @@ export class HaChooseAction extends LitElement implements ActionElement {
.disabled=${this.disabled}
@value-changed=${this._defaultChanged}
.hass=${this.hass}
+ .narrow=${this.narrow}
>
`
: html`
diff --git a/src/panels/config/automation/action/types/ha-automation-action-if.ts b/src/panels/config/automation/action/types/ha-automation-action-if.ts
index 2d7b8f1ecf..3b1eb99120 100644
--- a/src/panels/config/automation/action/types/ha-automation-action-if.ts
+++ b/src/panels/config/automation/action/types/ha-automation-action-if.ts
@@ -18,6 +18,8 @@ export class HaIfAction extends LitElement implements ActionElement {
@property({ attribute: false }) public action!: IfAction;
+ @property({ type: Boolean }) public narrow = false;
+
@state() private _showElse = false;
public static get defaultConfig(): IfAction {
@@ -41,6 +43,7 @@ export class HaIfAction extends LitElement implements ActionElement {
.disabled=${this.disabled}
@value-changed=${this._ifChanged}
.hass=${this.hass}
+ .narrow=${this.narrow}
>
@@ -53,6 +56,7 @@ export class HaIfAction extends LitElement implements ActionElement {
.disabled=${this.disabled}
@value-changed=${this._thenChanged}
.hass=${this.hass}
+ .narrow=${this.narrow}
>
${this._showElse || action.else
? html`
@@ -66,6 +70,7 @@ export class HaIfAction extends LitElement implements ActionElement {
.disabled=${this.disabled}
@value-changed=${this._elseChanged}
.hass=${this.hass}
+ .narrow=${this.narrow}
>
`
: html`
diff --git a/src/panels/config/automation/option/ha-automation-option-row.ts b/src/panels/config/automation/option/ha-automation-option-row.ts
index c9e97e2d46..b9e9434d63 100644
--- a/src/panels/config/automation/option/ha-automation-option-row.ts
+++ b/src/panels/config/automation/option/ha-automation-option-row.ts
@@ -183,6 +183,7 @@ export default class HaAutomationOptionRow extends LitElement {
)}
.disabled=${this.disabled}
.hass=${this.hass}
+ .narrow=${this.narrow}
@value-changed=${this._conditionChanged}
>
@@ -194,6 +195,7 @@ export default class HaAutomationOptionRow extends LitElement {
.actions=${ensureArray(this.option.sequence) || []}
.disabled=${this.disabled}
.hass=${this.hass}
+ .narrow=${this.narrow}
@value-changed=${this._actionChanged}
>
diff --git a/src/panels/config/info/ha-config-info.ts b/src/panels/config/info/ha-config-info.ts
index d58f4a858e..cb2b7fbf23 100644
--- a/src/panels/config/info/ha-config-info.ts
+++ b/src/panels/config/info/ha-config-info.ts
@@ -29,6 +29,7 @@ import { mdiHomeAssistant } from "../../../resources/home-assistant-logo-svg";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant, Route } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url";
+import { subscribeSystemHealthInfo } from "../../../data/system_health";
const JS_TYPE = __BUILD__;
const JS_VERSION = __VERSION__;
@@ -99,6 +100,8 @@ class HaConfigInfo extends LitElement {
@state() private _hassioInfo?: HassioInfo;
+ @state() private _installationMethod?: string;
+
protected render(): TemplateResult {
const hass = this.hass;
const customUiList: { name: string; url: string; version: string }[] =
@@ -127,6 +130,14 @@ class HaConfigInfo extends LitElement {
Home Assistant
+ -
+ ${this.hass.localize(
+ `ui.panel.config.info.installation_method`
+ )}
+ ${this._installationMethod || "…"}
+
-
Core
${hass.connection.haVersion}
@@ -249,6 +260,13 @@ class HaConfigInfo extends LitElement {
if (isComponentLoaded(this.hass, "hassio")) {
this._loadSupervisorInfo();
}
+
+ const unsubSystemHealth = subscribeSystemHealthInfo(this.hass, (info) => {
+ if (info?.homeassistant) {
+ this._installationMethod = info.homeassistant.info.installation_type;
+ unsubSystemHealth.then((unsub) => unsub());
+ }
+ });
}
private async _loadSupervisorInfo(): Promise {
diff --git a/src/panels/config/repairs/dialog-system-information.ts b/src/panels/config/repairs/dialog-system-information.ts
index b9666b0c57..a556d96ce9 100644
--- a/src/panels/config/repairs/dialog-system-information.ts
+++ b/src/panels/config/repairs/dialog-system-information.ts
@@ -301,7 +301,7 @@ class DialogSystemInformation extends LitElement {
} else {
const domains = Object.keys(this._systemInfo).sort(sortKeys);
for (const domain of domains) {
- const domainInfo = this._systemInfo[domain];
+ const domainInfo = this._systemInfo[domain]!;
const keys: TemplateResult[] = [];
for (const key of Object.keys(domainInfo.info)) {
@@ -387,7 +387,7 @@ class DialogSystemInformation extends LitElement {
const domainParts: string[] = [];
for (const domain of Object.keys(this._systemInfo!).sort(sortKeys)) {
- const domainInfo = this._systemInfo![domain];
+ const domainInfo = this._systemInfo![domain]!;
let first = true;
const parts = [
`${
diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
index fc987b3300..708514d836 100644
--- a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
+++ b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts
@@ -244,7 +244,10 @@ export class HuiEnergyDevicesGraphCard
chartData.sort((a: any, b: any) => b.value[0] - a.value[0]);
- chartData.length = this._config?.max_devices || chartData.length;
+ chartData.length = Math.min(
+ this._config?.max_devices || Infinity,
+ chartData.length
+ );
this._chartData = datasets;
await this.updateComplete;
diff --git a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
index e2e5aebd4e..ed1a507966 100644
--- a/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
+++ b/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts
@@ -110,11 +110,7 @@ export class HuiDialogEditCard
}
protected updated(changedProps: PropertyValues): void {
- if (
- !this._cardConfig ||
- this._documentationURL !== undefined ||
- !changedProps.has("_cardConfig")
- ) {
+ if (!this._cardConfig || !changedProps.has("_cardConfig")) {
return;
}
diff --git a/src/panels/lovelace/editor/get-dashboard-documentation-url.ts b/src/panels/lovelace/editor/get-dashboard-documentation-url.ts
index 658e1f2cec..c4e66db8aa 100644
--- a/src/panels/lovelace/editor/get-dashboard-documentation-url.ts
+++ b/src/panels/lovelace/editor/get-dashboard-documentation-url.ts
@@ -7,6 +7,23 @@ import {
import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url";
+const NON_STANDARD_URLS = {
+ "energy-date-selection": "energy/#energy-date-picker",
+ "energy-usage-graph": "energy/#energy-usage-graph",
+ "energy-solar-graph": "energy/#solar-production-graph",
+ "energy-gas-graph": "energy/#gas-consumption-graph",
+ "energy-water-graph": "energy/#water-consumption-graph",
+ "energy-distribution": "energy/#energy-distribution",
+ "energy-sources-table": "energy/#energy-sources-table",
+ "energy-grid-neutrality-gauge": "energy/#grid-neutrality-gauge",
+ "energy-solar-consumed-gauge": "energy/#solar-consumed-gauge",
+ "energy-carbon-consumed-gauge": "energy/#carbon-consumed-gauge",
+ "energy-self-sufficiency-gauge": "energy/#self-sufficiency-gauge",
+ "energy-devices-graph": "energy/#devices-energy-graph",
+ "energy-devices-detail-graph": "energy/#detail-devices-energy-graph",
+ "energy-sankey": "energy/#sankey-energy-graph",
+};
+
export const getCardDocumentationURL = (
hass: HomeAssistant,
type: string
@@ -15,7 +32,7 @@ export const getCardDocumentationURL = (
return getCustomCardEntry(stripCustomPrefix(type))?.documentationURL;
}
- return `${documentationUrl(hass, "/dashboards/")}${type}`;
+ return `${documentationUrl(hass, "/dashboards/")}${NON_STANDARD_URLS[type] || type}`;
};
export const getBadgeDocumentationURL = (
diff --git a/src/translations/en.json b/src/translations/en.json
index 11f047653f..daa4acfb7f 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -3110,6 +3110,7 @@
},
"info": {
"caption": "About",
+ "installation_method": "Installation method",
"copy_menu": "Copy menu",
"copy_raw": "Raw text",
"copy_github": "For GitHub",