diff --git a/src/common/entity/compute_active_state.ts b/src/common/entity/compute_active_state.ts
deleted file mode 100644
index fff02d2f14..0000000000
--- a/src/common/entity/compute_active_state.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { HassEntity } from "home-assistant-js-websocket";
-import { UNAVAILABLE_STATES } from "../../data/entity";
-
-export const computeActiveState = (stateObj: HassEntity): string => {
- if (UNAVAILABLE_STATES.includes(stateObj.state)) {
- return stateObj.state;
- }
-
- const domain = stateObj.entity_id.split(".")[0];
- let state = stateObj.state;
-
- if (domain === "climate") {
- state = stateObj.attributes.hvac_action;
- }
-
- return state;
-};
diff --git a/src/common/entity/state_active.ts b/src/common/entity/state_active.ts
index 2e4b788d5b..3ec7f1bad7 100644
--- a/src/common/entity/state_active.ts
+++ b/src/common/entity/state_active.ts
@@ -31,6 +31,8 @@ export function stateActive(stateObj: HassEntity, state?: string): boolean {
return !["idle", "docked", "paused"].includes(compareState);
case "plant":
return compareState === "problem";
+ case "group":
+ return ["on", "home", "open", "locked", "problem"].includes(compareState);
default:
return true;
}
diff --git a/src/common/style/icon_color_css.ts b/src/common/style/icon_color_css.ts
index cfddbe42c6..bc63f3df1a 100644
--- a/src/common/style/icon_color_css.ts
+++ b/src/common/style/icon_color_css.ts
@@ -1,60 +1,32 @@
import { css } from "lit";
export const iconColorCSS = css`
- ha-state-icon[data-domain="alert"][data-state="on"],
- ha-state-icon[data-domain="automation"][data-state="on"],
- ha-state-icon[data-domain="binary_sensor"][data-state="on"],
- ha-state-icon[data-domain="calendar"][data-state="on"],
- ha-state-icon[data-domain="camera"][data-state="streaming"],
- ha-state-icon[data-domain="cover"][data-state="open"],
- ha-state-icon[data-domain="device_tracker"][data-state="home"],
- ha-state-icon[data-domain="fan"][data-state="on"],
- ha-state-icon[data-domain="humidifier"][data-state="on"],
- ha-state-icon[data-domain="light"][data-state="on"],
- ha-state-icon[data-domain="input_boolean"][data-state="on"],
- ha-state-icon[data-domain="lock"][data-state="unlocked"],
- ha-state-icon[data-domain="media_player"][data-state="on"],
- ha-state-icon[data-domain="media_player"][data-state="paused"],
- ha-state-icon[data-domain="media_player"][data-state="playing"],
- ha-state-icon[data-domain="remote"][data-state="on"],
- ha-state-icon[data-domain="script"][data-state="on"],
- ha-state-icon[data-domain="sun"][data-state="above_horizon"],
- ha-state-icon[data-domain="switch"][data-state="on"],
- ha-state-icon[data-domain="timer"][data-state="active"],
- ha-state-icon[data-domain="vacuum"][data-state="cleaning"],
- ha-state-icon[data-domain="group"][data-state="on"],
- ha-state-icon[data-domain="group"][data-state="home"],
- ha-state-icon[data-domain="group"][data-state="open"],
- ha-state-icon[data-domain="group"][data-state="locked"],
- ha-state-icon[data-domain="group"][data-state="problem"] {
+ ha-state-icon[data-active][data-domain="alert"],
+ ha-state-icon[data-active][data-domain="automation"],
+ ha-state-icon[data-active][data-domain="binary_sensor"],
+ ha-state-icon[data-active][data-domain="calendar"],
+ ha-state-icon[data-active][data-domain="camera"],
+ ha-state-icon[data-active][data-domain="cover"],
+ ha-state-icon[data-active][data-domain="device_tracker"],
+ ha-state-icon[data-active][data-domain="fan"],
+ ha-state-icon[data-active][data-domain="humidifier"],
+ ha-state-icon[data-active][data-domain="light"],
+ ha-state-icon[data-active][data-domain="input_boolean"],
+ ha-state-icon[data-active][data-domain="lock"],
+ ha-state-icon[data-active][data-domain="media_player"],
+ ha-state-icon[data-active][data-domain="remote"],
+ ha-state-icon[data-active][data-domain="script"],
+ ha-state-icon[data-active][data-domain="sun"],
+ ha-state-icon[data-active][data-domain="switch"],
+ ha-state-icon[data-active][data-domain="timer"],
+ ha-state-icon[data-active][data-domain="vacuum"],
+ ha-state-icon[data-active][data-domain="group"] {
color: var(--paper-item-icon-active-color, #fdd835);
}
- ha-state-icon[data-domain="climate"][data-state="cooling"] {
- color: var(--cool-color, var(--state-climate-cool-color));
- }
-
- ha-state-icon[data-domain="climate"][data-state="heating"] {
- color: var(--heat-color, var(--state-climate-heat-color));
- }
-
- ha-state-icon[data-domain="climate"][data-state="drying"] {
- color: var(--dry-color, var(--state-climate-dry-color));
- }
-
- ha-state-icon[data-domain="alarm_control_panel"] {
- color: var(--alarm-color-armed, var(--label-badge-red));
- }
- ha-state-icon[data-domain="alarm_control_panel"][data-state="disarmed"] {
- color: var(--alarm-color-disarmed, var(--label-badge-green));
- }
- ha-state-icon[data-domain="alarm_control_panel"][data-state="pending"],
- ha-state-icon[data-domain="alarm_control_panel"][data-state="arming"] {
- color: var(--alarm-color-pending, var(--label-badge-yellow));
- animation: pulse 1s infinite;
- }
- ha-state-icon[data-domain="alarm_control_panel"][data-state="triggered"] {
- color: var(--alarm-color-triggered, var(--label-badge-red));
+ ha-state-icon[data-active][data-domain="alarm_control_panel"][data-state="pending"],
+ ha-state-icon[data-active][data-domain="alarm_control_panel"][data-state="arming"],
+ ha-state-icon[data-active][data-domain="alarm_control_panel"][data-state="triggered"] {
animation: pulse 1s infinite;
}
@@ -70,10 +42,6 @@ export const iconColorCSS = css`
}
}
- ha-state-icon[data-domain="plant"][data-state="problem"] {
- color: var(--state-icon-error-color);
- }
-
/* Color the icon if unavailable */
ha-state-icon[data-state="unavailable"] {
color: var(--state-unavailable-color);
diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts
index 850eeb04b9..30022f677f 100644
--- a/src/components/entity/state-badge.ts
+++ b/src/components/entity/state-badge.ts
@@ -11,9 +11,10 @@ import {
import { property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
-import { computeActiveState } from "../../common/entity/compute_active_state";
import { computeDomain } from "../../common/entity/compute_domain";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
+import { stateActive } from "../../common/entity/state_active";
+import { stateColor } from "../../common/entity/state_color";
import { iconColorCSS } from "../../common/style/icon_color_css";
import { cameraUrlWithWidthHeight } from "../../data/camera";
import type { HomeAssistant } from "../../types";
@@ -35,6 +36,13 @@ export class StateBadge extends LitElement {
@state() private _iconStyle: { [name: string]: string } = {};
+ private get _stateColor() {
+ const domain = this.stateObj
+ ? computeStateDomain(this.stateObj)
+ : undefined;
+ return this.stateColor || (domain === "light" && this.stateColor !== false);
+ }
+
protected render(): TemplateResult {
const stateObj = this.stateObj;
@@ -50,15 +58,13 @@ export class StateBadge extends LitElement {
}
const domain = stateObj ? computeStateDomain(stateObj) : undefined;
+ const active = this._stateColor && stateObj ? stateActive(stateObj) : false;
return html``;
@@ -69,7 +75,8 @@ export class StateBadge extends LitElement {
if (
!changedProps.has("stateObj") &&
!changedProps.has("overrideImage") &&
- !changedProps.has("overrideIcon")
+ !changedProps.has("overrideIcon") &&
+ !changedProps.has("stateColor")
) {
return;
}
@@ -100,11 +107,14 @@ export class StateBadge extends LitElement {
}
hostStyle.backgroundImage = `url(${imageUrl})`;
this._showIcon = false;
- } else if (stateObj.state === "on") {
- if (this.stateColor !== false && stateObj.attributes.rgb_color) {
+ } else if (stateActive(stateObj) && this._stateColor) {
+ const iconColor = stateColor(stateObj);
+ if (stateObj.attributes.rgb_color) {
iconStyle.color = `rgb(${stateObj.attributes.rgb_color.join(",")})`;
+ } else if (iconColor) {
+ iconStyle.color = `rgb(var(--rgb-state-${iconColor}-color))`;
}
- if (stateObj.attributes.brightness && this.stateColor !== false) {
+ if (stateObj.attributes.brightness) {
const brightness = stateObj.attributes.brightness;
if (typeof brightness !== "number") {
const errorMessage = `Type error: state-badge expected number, but type of ${
diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts
index bb6d54c8f8..e75e08f150 100644
--- a/src/panels/lovelace/cards/hui-button-card.ts
+++ b/src/panels/lovelace/cards/hui-button-card.ts
@@ -21,11 +21,12 @@ import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
import { DOMAINS_TOGGLE } from "../../../common/const";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
-import { computeActiveState } from "../../../common/entity/compute_active_state";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name";
+import { stateActive } from "../../../common/entity/state_active";
+import { stateColor } from "../../../common/entity/state_color";
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { iconColorCSS } from "../../../common/style/icon_color_css";
import "../../../components/ha-card";
@@ -145,6 +146,13 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
const name = this._config.show_name
? this._config.name || (stateObj ? computeStateName(stateObj) : "")
: "";
+ const domain = stateObj ? computeStateDomain(stateObj) : undefined;
+
+ const active =
+ (this._config.state_color ||
+ (domain === "light" && this._config.state_color !== false)) &&
+ stateObj &&
+ stateActive(stateObj);
return html`
@@ -174,6 +185,24 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
`;
}
+ private _computeColor(stateObj: HassEntity | LightEntity): string {
+ const domain = computeStateDomain(stateObj);
+ if (
+ !(
+ this._config?.state_color ||
+ (domain === "light" && this._config?.state_color !== false)
+ ) ||
+ !stateActive(stateObj)
+ ) {
+ return "";
+ }
+ const iconColor = stateColor(stateObj);
+ if (iconColor) {
+ return `rgb(var(--rgb-state-${iconColor}-color))`;
+ }
+ return "";
+ }
+
protected shouldUpdate(changedProps: PropertyValues): boolean {
// Side Effect used to update footer hass while keeping optimizations
if (this._footerElement) {