Compare commits

...

5 Commits

Author SHA1 Message Date
Matthias de Baat
7aa235c6af Fix Discord link for designers (#29393)
* Fix Discord link for designers

Updated Discord link for designers to the correct channel.

* Update Discord link for designers in home.markdown

* Update gallery/src/pages/concepts/home.markdown

Co-authored-by: Aidan Timson <aidan@timmo.dev>

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Aidan Timson <aidan@timmo.dev>
2026-02-05 21:09:28 +01:00
Aidan Timson
e8ddae8189 Migrate join beta dialog to wa (#29439)
Migrate config-updates dialog(s) to wa
2026-02-05 21:06:38 +01:00
Paul Bottein
c26e59f19c Fix theme and sidebar on demo (#29433) 2026-02-05 15:49:27 +01:00
Petar Petrov
83aa06cb18 Fix storage apps translation keys (#29432) 2026-02-05 15:43:47 +01:00
Tom Carpenter
9d3d0dac48 Fix energy dashboard date/time tooltip date labelling (#29431)
* Use Suggested Period for Energy Tooltip

Ensure the tooltips for energy charts match energy data grouping by using getSuggestedPeriod rather than hardcoded differenceInDays.

* Make getSuggestedMax return Date()

Currently used in two places - for energy charge ECOption, and for a statistics-graph. In both places a Date is expected rather than a Number. No point converting to a Number with getTime() when they are immediately converted back to a Date.
2026-02-05 15:40:12 +01:00
8 changed files with 62 additions and 55 deletions

View File

@@ -1,14 +1,12 @@
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
let changeFunction;
let sidebarChangeCallback;
export const mockFrontend = (hass: MockHomeAssistant) => {
hass.mockWS("frontend/get_user_data", () => ({
value: null,
}));
hass.mockWS("frontend/get_user_data", () => ({ value: null }));
hass.mockWS("frontend/set_user_data", ({ key, value }) => {
if (key === "sidebar") {
changeFunction?.({
sidebarChangeCallback?.({
value: {
panelOrder: value.panelOrder || [],
hiddenPanels: value.hiddenPanels || [],
@@ -16,14 +14,11 @@ export const mockFrontend = (hass: MockHomeAssistant) => {
});
}
});
hass.mockWS("frontend/subscribe_user_data", (_msg, _hass, onChange) => {
changeFunction = onChange;
onChange?.({
value: {
panelOrder: [],
hiddenPanels: [],
},
});
hass.mockWS("frontend/subscribe_user_data", (msg, _hass, onChange) => {
if (msg.key === "sidebar") {
sidebarChangeCallback = onChange;
}
onChange?.({ value: null });
// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {};
});
@@ -48,4 +43,5 @@ export const mockFrontend = (hass: MockHomeAssistant) => {
return () => {};
});
hass.mockWS("repairs/list_issues", () => ({ issues: [] }));
hass.mockWS("frontend/get_themes", (_msg, currentHass) => currentHass.themes);
};

View File

@@ -29,6 +29,7 @@ export const mockLovelace = (
hass.mockWS("lovelace/config/save", () => Promise.resolve());
hass.mockWS("lovelace/resources", () => Promise.resolve([]));
hass.mockWS("lovelace/dashboards/list", () => Promise.resolve([]));
};
customElements.whenDefined("hui-root").then(() => {

View File

@@ -18,7 +18,7 @@ The Home Assistant interface is based on Material Design. It's a design system c
We want to make it as easy for designers to contribute as it is for developers. Theres a lot a designer can contribute to:
- Meet us at <a href="https://www.home-assistant.io/join-chat" rel="noopener noreferrer" target="_blank">devs_ux Discord</a>. Feel free to share your designs, user test or strategic ideas.
- Meet us at <a href="https://www.home-assistant.io/join-chat-design" rel="noopener noreferrer" target="_blank">Discord #designers channel</a>. If you can't see the channel, make sure you set the correct role in Channels & Roles.
- Start designing with our <a href="https://www.figma.com/community/file/967153512097289521/Home-Assistant-DesignKit" rel="noopener noreferrer" target="_blank">Figma DesignKit</a>.
- Find the latest UX <a href="https://github.com/home-assistant/frontend/discussions?discussions_q=label%3Aux" rel="noopener noreferrer" target="_blank">discussions</a> and <a href="https://github.com/home-assistant/frontend/labels/ux" rel="noopener noreferrer" target="_blank">issues</a> on GitHub. Everyone can start a new issue or discussion!

View File

@@ -3,8 +3,8 @@ import type { Panels } from "../types";
export const demoPanels: Panels = {
lovelace: {
component_name: "lovelace",
icon: null,
title: null,
icon: "mdi:view-dashboard",
title: "demo",
config: { mode: "storage" },
url_path: "lovelace",
},

View File

@@ -256,6 +256,10 @@ export const provideHass = (
darkMode: false,
theme: "default",
},
selectedTheme: {
theme: "default",
dark: false,
},
panels: demoPanels,
services: demoServices,
user: {
@@ -348,7 +352,7 @@ export const provideHass = (
mockTheme(theme) {
invalidateThemeCache();
hass().updateHass({
selectedTheme: { theme: theme ? "mock" : "default" },
selectedTheme: { theme: theme ? "mock" : "default", dark: false },
themes: {
...hass().themes,
themes: {
@@ -361,7 +365,7 @@ export const provideHass = (
document.documentElement,
themes,
selectedTheme!.theme,
undefined,
{ dark: false },
true
);
},

View File

@@ -5,7 +5,8 @@ import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import "../../../../components/ha-button";
import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-dialog-footer";
import "../../../../components/ha-wa-dialog";
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
@@ -21,14 +22,21 @@ export class DialogJoinBeta
@state() private _dialogParams?: JoinBetaDialogParams;
@state() private _open = false;
public showDialog(dialogParams: JoinBetaDialogParams): void {
this._dialogParams = dialogParams;
this._open = true;
}
public closeDialog() {
this._open = false;
return true;
}
private _dialogClosed() {
this._dialogParams = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
return true;
}
protected render() {
@@ -37,13 +45,11 @@ export class DialogJoinBeta
}
return html`
<ha-dialog
open
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
this.hass.localize("ui.dialogs.join_beta_channel.title")
)}
<ha-wa-dialog
.hass=${this.hass}
.open=${this._open}
header-title=${this.hass.localize("ui.dialogs.join_beta_channel.title")}
@closed=${this._dialogClosed}
>
<ha-alert alert-type="warning">
${this.hass.localize("ui.dialogs.join_beta_channel.backup")}
@@ -67,17 +73,19 @@ export class DialogJoinBeta
)}
<ha-svg-icon .path=${mdiOpenInNew}></ha-svg-icon>
</a>
<ha-button
appearance="plain"
slot="primaryAction"
@click=${this._cancel}
>
${this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button slot="primaryAction" @click=${this._join}>
${this.hass.localize("ui.dialogs.join_beta_channel.join")}
</ha-button>
</ha-dialog>
<ha-dialog-footer slot="footer">
<ha-button
slot="secondaryAction"
appearance="plain"
@click=${this._cancel}
>
${this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button slot="primaryAction" @click=${this._join}>
${this.hass.localize("ui.dialogs.join_beta_channel.join")}
</ha-button>
</ha-dialog-footer>
</ha-wa-dialog>
`;
}

View File

@@ -33,15 +33,15 @@ import { filterXSS } from "../../../../../common/util/xss";
import type { StatisticPeriod } from "../../../../../data/recorder";
import { getSuggestedPeriod } from "../../../../../data/energy";
export function getSuggestedMax(period: StatisticPeriod, end: Date): number {
export function getSuggestedMax(period: StatisticPeriod, end: Date): Date {
let suggestedMax = new Date(end);
if (period === "5minute") {
return suggestedMax.getTime();
return suggestedMax;
}
suggestedMax.setMinutes(0, 0, 0);
if (period === "hour") {
return suggestedMax.getTime();
return suggestedMax;
}
// Sometimes around DST we get a time of 0:59 instead of 23:59 as expected.
// Correct for this when showing days/months so we don't get an extra day.
@@ -50,11 +50,11 @@ export function getSuggestedMax(period: StatisticPeriod, end: Date): number {
}
suggestedMax.setHours(0);
if (period === "day" || period === "week") {
return suggestedMax.getTime();
return suggestedMax;
}
// period === month
suggestedMax.setDate(1);
return suggestedMax.getTime();
return suggestedMax;
}
function createYAxisLabelFormatter(locale: FrontendLocaleData) {
@@ -81,7 +81,7 @@ export function getCommonOptions(
formatTotal?: (total: number) => string,
detailedDailyData = false
): ECOption {
const dayDifference = differenceInDays(end, start);
const suggestedPeriod = getSuggestedPeriod(start, end, detailedDailyData);
const compare = compareStart !== undefined && compareEnd !== undefined;
const showCompareYear =
@@ -91,10 +91,7 @@ export function getCommonOptions(
xAxis: {
type: "time",
min: start,
max: getSuggestedMax(
getSuggestedPeriod(start, end, detailedDailyData),
end
),
max: getSuggestedMax(suggestedPeriod, end),
},
yAxis: {
type: "value",
@@ -137,7 +134,7 @@ export function getCommonOptions(
items,
locale,
config,
dayDifference,
suggestedPeriod,
compare,
showCompareYear,
unit,
@@ -151,7 +148,7 @@ export function getCommonOptions(
[params],
locale,
config,
dayDifference,
suggestedPeriod,
compare,
showCompareYear,
unit,
@@ -167,7 +164,7 @@ function formatTooltip(
params: CallbackDataParams[],
locale: FrontendLocaleData,
config: HassConfig,
dayDifference: number,
suggestedPeriod: string,
compare: boolean | null,
showCompareYear: boolean,
unit?: string,
@@ -181,9 +178,9 @@ function formatTooltip(
const date = new Date(params[0].value?.[2] ?? params[0].value?.[0]);
let period: string;
if (dayDifference >= 89) {
if (suggestedPeriod === "month") {
period = `${formatDateMonthYear(date, locale, config)}`;
} else if (dayDifference > 0) {
} else if (suggestedPeriod === "day") {
period = `${(showCompareYear ? formatDateShort : formatDateVeryShort)(date, locale, config)}`;
} else {
period = `${

View File

@@ -1,5 +1,6 @@
{
"panel": {
"demo": "Demo",
"apps": "Apps",
"energy": "Energy",
"calendar": "Calendar",
@@ -7745,8 +7746,8 @@
"used": "Used space",
"free": "Free space",
"system": "System",
"apps_data": "App data",
"apps_config": "App configuration",
"addons_data": "App data",
"addons_config": "App configuration",
"media": "Media",
"share": "Share",
"backup": "Backups",