Compare commits

..

2 Commits

Author SHA1 Message Date
Simon Lamon
3995ab6219 Migrate analytics dropdown 2025-11-21 20:35:06 +00:00
Petar Petrov
be319503f7 Update color scheme in ZHA network visualization (#28032) 2025-11-21 19:09:37 +01:00
7 changed files with 20 additions and 242 deletions

View File

@@ -1,167 +0,0 @@
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { storage } from "../common/decorators/storage";
import type { HomeAssistant } from "../types";
interface Snowflake {
id: number;
left: number;
size: number;
duration: number;
delay: number;
blur: number;
}
@customElement("ha-snowflakes")
export class HaSnowflakes extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ type: Boolean }) public narrow = false;
@storage({ key: "winter-mode", state: true, subscribe: true })
@state()
private _enabled = true;
@state() private _snowflakes: Snowflake[] = [];
private _maxSnowflakes = 50;
private _generateSnowflakes() {
if (!this._enabled) {
this._snowflakes = [];
return;
}
const snowflakes: Snowflake[] = [];
for (let i = 0; i < this._maxSnowflakes; i++) {
snowflakes.push({
id: i,
left: Math.random() * 100, // Random position from 0-100%
size: Math.random() * 12 + 8, // Random size between 8-20px
duration: Math.random() * 8 + 8, // Random duration between 8-16s
delay: Math.random() * 8, // Random delay between 0-8s
blur: Math.random() * 1, // Random blur between 0-1px
});
}
this._snowflakes = snowflakes;
}
protected willUpdate(changedProps: Map<string, unknown>) {
super.willUpdate(changedProps);
if (changedProps.has("_enabled")) {
this._generateSnowflakes();
}
}
protected render() {
if (!this._enabled) {
return nothing;
}
const isDark = this.hass?.themes.darkMode ?? false;
return html`
<div class="snowflakes ${isDark ? "dark" : "light"}" aria-hidden="true">
${this._snowflakes.map(
(flake) => html`
<div
class="snowflake ${this.narrow && flake.id >= 30
? "hide-narrow"
: ""}"
style="
left: ${flake.left}%;
font-size: ${flake.size}px;
animation-duration: ${flake.duration}s;
animation-delay: ${flake.delay}s;
filter: blur(${flake.blur}px);
"
>
</div>
`
)}
</div>
`;
}
static readonly styles = css`
:host {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
overflow: hidden;
}
.snowflakes {
position: absolute;
top: -10%;
left: 0;
width: 100%;
height: 110%;
pointer-events: none;
}
.snowflake {
position: absolute;
top: -10%;
opacity: 0.7;
user-select: none;
pointer-events: none;
animation: fall linear infinite;
}
.light .snowflake {
color: #00bcd4;
text-shadow:
0 0 5px #00bcd4,
0 0 10px #00e5ff;
}
.dark .snowflake {
color: #fff;
text-shadow:
0 0 5px rgba(255, 255, 255, 0.8),
0 0 10px rgba(255, 255, 255, 0.5);
}
.snowflake.hide-narrow {
display: none;
}
@keyframes fall {
0% {
transform: translateY(-10vh) translateX(0);
}
25% {
transform: translateY(30vh) translateX(10px);
}
50% {
transform: translateY(60vh) translateX(-10px);
}
75% {
transform: translateY(85vh) translateX(10px);
}
100% {
transform: translateY(120vh) translateX(0);
}
}
@media (prefers-reduced-motion: reduce) {
.snowflake {
animation: none;
display: none;
}
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"ha-snowflakes": HaSnowflakes;
}
}

View File

@@ -7,7 +7,6 @@ import { listenMediaQuery } from "../common/dom/media_query";
import { toggleAttribute } from "../common/dom/toggle_attribute";
import { computeRTLDirection } from "../common/util/compute_rtl";
import "../components/ha-drawer";
import "../components/ha-snowflakes";
import { showNotificationDrawer } from "../dialogs/notifications/show-notification-drawer";
import type { HomeAssistant, Route } from "../types";
import "./partial-panel-resolver";
@@ -51,7 +50,6 @@ export class HomeAssistantMain extends LitElement {
this.hass.panels && this.hass.userData && this.hass.systemData;
return html`
<ha-snowflakes .hass=${this.hass} .narrow=${this.narrow}></ha-snowflakes>
<ha-drawer
.type=${sidebarNarrow ? "modal" : ""}
.open=${sidebarNarrow ? this._drawerOpen : false}

View File

@@ -14,6 +14,8 @@ import {
downloadFileSupported,
fileDownload,
} from "../../../util/file_download";
import "../../../components/ha-dropdown-item";
import "../../../components/ha-dropdown";
@customElement("ha-config-section-analytics")
class HaConfigSectionAnalytics extends LitElement {
@@ -33,22 +35,19 @@ class HaConfigSectionAnalytics extends LitElement {
>
${downloadFileSupported(this.hass)
? html`
<ha-button-menu
@action=${this._handleOverflowAction}
<ha-dropdown
@wa-select=${this._handleOverflowAction}
slot="toolbar-icon"
>
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
</ha-icon-button>
<ha-list-item graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiDownload}
></ha-svg-icon>
<ha-dropdown-item .value=${"download_device_info"}>
<ha-svg-icon slot="icon" .path=${mdiDownload}></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.analytics.download_device_info"
)}
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
`
: nothing}
<div class="content">
@@ -58,9 +57,16 @@ class HaConfigSectionAnalytics extends LitElement {
`;
}
private async _handleOverflowAction(): Promise<void> {
const signedPath = await getSignedPath(this.hass, "/api/analytics/devices");
fileDownload(signedPath.path);
private async _handleOverflowAction(
ev: CustomEvent<{ item: { value: string } }>
): Promise<void> {
if (ev.detail.item.value === "download_device_info") {
const signedPath = await getSignedPath(
this.hass,
"/api/analytics/devices"
);
fileDownload(signedPath.path);
}
}
static styles = css`

View File

@@ -295,7 +295,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
color:
route.route_status === "Active"
? primaryColor
: style.getPropertyValue("--disabled-color"),
: style.getPropertyValue("--dark-primary-color"),
type: ["Child", "Parent"].includes(neighbor.relationship)
? "solid"
: "dotted",
@@ -335,7 +335,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
symbolSize: 5,
lineStyle: {
width: 1,
color: style.getPropertyValue("--disabled-color"),
color: style.getPropertyValue("--dark-primary-color"),
type: "dotted",
},
ignoreForceLayout: true,

View File

@@ -31,7 +31,6 @@ import "./ha-pick-time-zone-row";
import "./ha-push-notifications-row";
import "./ha-set-suspend-row";
import "./ha-set-vibrate-row";
import "./ha-set-winter-mode-row";
@customElement("ha-profile-section-general")
class HaProfileSectionGeneral extends LitElement {
@@ -241,10 +240,6 @@ class HaProfileSectionGeneral extends LitElement {
.narrow=${this.narrow}
.hass=${this.hass}
></ha-set-suspend-row>
<ha-set-winter-mode-row
.narrow=${this.narrow}
.hass=${this.hass}
></ha-set-winter-mode-row>
${!isMobileClient
? html`
<ha-enable-shortcuts-row

View File

@@ -1,50 +0,0 @@
import type { TemplateResult } from "lit";
import { html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { storage } from "../../common/decorators/storage";
import "../../components/ha-settings-row";
import "../../components/ha-switch";
import type { HaSwitch } from "../../components/ha-switch";
import type { HomeAssistant } from "../../types";
@customElement("ha-set-winter-mode-row")
class HaSetWinterModeRow extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow = false;
@storage({ key: "winter-mode", state: true, subscribe: true })
@state()
private _winterMode = true;
protected render(): TemplateResult {
return html`
<ha-settings-row .narrow=${this.narrow}>
<span slot="heading">
${this.hass.localize("ui.panel.profile.winter_mode.header")}
</span>
<span slot="description">
${this.hass.localize("ui.panel.profile.winter_mode.description")}
</span>
<ha-switch
.checked=${this._winterMode}
@change=${this._checkedChanged}
></ha-switch>
</ha-settings-row>
`;
}
private _checkedChanged(ev: Event) {
const winterMode = (ev.target as HaSwitch).checked;
if (winterMode === this._winterMode) {
return;
}
this._winterMode = winterMode;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-set-winter-mode-row": HaSetWinterModeRow;
}
}

View File

@@ -8618,10 +8618,6 @@
"header": "Vibrate",
"description": "Enable or disable vibration on this device when controlling devices."
},
"winter_mode": {
"header": "Winter mode",
"description": "Add a seasonal touch to your Home Assistant interface."
},
"enable_shortcuts": {
"header": "Keyboard shortcuts",
"description": "Enable or disable keyboard shortcuts for performing various actions in the UI."