Use new colors for state icon (#14358)

* Use new colors for state icon

* feedbacks

* Remove arming case
This commit is contained in:
Paul Bottein 2022-11-29 15:22:50 +01:00 committed by GitHub
parent fcfdad3d94
commit aeeacc6cad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 105 deletions

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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`<ha-state-icon
style=${styleMap(this._iconStyle)}
data-domain=${ifDefined(
this.stateColor || (domain === "light" && this.stateColor !== false)
? domain
: undefined
)}
data-state=${stateObj ? computeActiveState(stateObj) : ""}
?data-active=${active}
data-domain=${ifDefined(domain)}
data-state=${ifDefined(stateObj?.state)}
.icon=${this.overrideIcon}
.state=${stateObj}
></ha-state-icon>`;
@ -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 ${

View File

@ -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`
<ha-card
@ -171,19 +179,17 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
? html`
<ha-state-icon
tabindex="-1"
?data-active=${active}
data-domain=${ifDefined(
this._config.state_color && stateObj
? computeStateDomain(stateObj)
: undefined
)}
data-state=${ifDefined(
stateObj ? computeActiveState(stateObj) : undefined
stateObj ? computeStateDomain(stateObj) : undefined
)}
data-state=${ifDefined(stateObj?.state)}
.icon=${this._config.icon}
.state=${stateObj}
style=${styleMap({
filter: stateObj ? this._computeBrightness(stateObj) : "",
color: stateObj ? this._computeColor(stateObj) : "",
color: stateObj && active ? this._computeColor(stateObj) : "",
filter:
stateObj && active ? this._computeBrightness(stateObj) : "",
height: this._config.icon_height
? this._config.icon_height
: "",
@ -298,17 +304,21 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
}
private _computeBrightness(stateObj: HassEntity | LightEntity): string {
if (!stateObj.attributes.brightness || !this._config?.state_color) {
return "";
if (!stateObj.attributes.brightness) {
const brightness = stateObj.attributes.brightness;
return `brightness(${(brightness + 245) / 5}%)`;
}
const brightness = stateObj.attributes.brightness;
return `brightness(${(brightness + 245) / 5}%)`;
return "";
}
private _computeColor(stateObj: HassEntity | LightEntity): string {
if (this._config?.state_color && stateObj.attributes.rgb_color) {
if (stateObj.attributes.rgb_color) {
return `rgb(${stateObj.attributes.rgb_color.join(",")})`;
}
const iconColor = stateColor(stateObj);
if (iconColor) {
return `rgb(var(--rgb-state-${iconColor}-color))`;
}
return "";
}

View File

@ -1,3 +1,4 @@
import { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
@ -8,12 +9,14 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeActiveState } from "../../../common/entity/compute_active_state";
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 {
formatNumber,
@ -25,6 +28,7 @@ import "../../../components/ha-card";
import "../../../components/ha-icon";
import { UNAVAILABLE_STATES } from "../../../data/entity";
import { formatAttributeValue } from "../../../data/entity_attributes";
import { LightEntity } from "../../../data/light";
import { HomeAssistant } from "../../../types";
import { computeCardSize } from "../common/compute-card-size";
import { findEntities } from "../common/find-entities";
@ -120,6 +124,11 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
const name = this._config.name || computeStateName(stateObj);
const active =
(this._config.state_color ||
(domain === "light" && this._config.state_color !== false)) &&
stateActive(stateObj);
return html`
<ha-card @click=${this._handleClick} tabindex="0">
<div class="header">
@ -128,13 +137,15 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
<ha-state-icon
.icon=${this._config.icon}
.state=${stateObj}
data-domain=${ifDefined(
this._config.state_color ||
(domain === "light" && this._config.state_color !== false)
? domain
: undefined
)}
data-state=${stateObj ? computeActiveState(stateObj) : ""}
?data-active=${active}
data-domain=${ifDefined(domain)}
data-state=${stateObj.state}
style=${styleMap({
color: active ? this._computeColor(stateObj) : "",
height: this._config.icon_height
? this._config.icon_height
: "",
})}
></ha-state-icon>
</div>
</div>
@ -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) {