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`
@@ -128,13 +137,15 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
@@ -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) {