From e6f2e8058bdc475d0da913f727b6c4187475c89d Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 6 Dec 2022 17:45:24 +0100 Subject: [PATCH] Color adjustments for entity state (#14557) --- gallery/src/pages/misc/entity-state.ts | 61 +++++++++++-------- src/common/entity/color/person_color.ts | 10 +++ src/common/entity/state_color.ts | 20 ++++++ src/common/style/icon_color_css.ts | 23 ------- src/panels/lovelace/cards/hui-tile-card.ts | 12 ++++ .../cards/tile/badges/tile-badge-person.ts | 23 +++---- .../lovelace/cards/tile/badges/tile-badge.ts | 4 ++ src/resources/ha-style.ts | 9 ++- 8 files changed, 101 insertions(+), 61 deletions(-) create mode 100644 src/common/entity/color/person_color.ts diff --git a/gallery/src/pages/misc/entity-state.ts b/gallery/src/pages/misc/entity-state.ts index 280ba22976..35fe96528a 100644 --- a/gallery/src/pages/misc/entity-state.ts +++ b/gallery/src/pages/misc/entity-state.ts @@ -4,14 +4,12 @@ import { } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; -import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { computeDomain } from "../../../../src/common/entity/compute_domain"; import { computeStateDisplay } from "../../../../src/common/entity/compute_state_display"; -import { stateColorCss } from "../../../../src/common/entity/state_color"; -import { stateIconPath } from "../../../../src/common/entity/state_icon_path"; import "../../../../src/components/data-table/ha-data-table"; import type { DataTableColumnContainer } from "../../../../src/components/data-table/ha-data-table"; +import "../../../../src/components/entity/state-badge"; import "../../../../src/components/ha-chip"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import { HomeAssistant } from "../../../../src/types"; @@ -105,6 +103,12 @@ const ENTITIES: HassEntity[] = [ createEntity("alarm_control_panel.arming", "arming"), createEntity("alarm_control_panel.disarming", "disarming"), createEntity("alarm_control_panel.triggered", "triggered"), + // Alert + createEntity("alert.off", "off"), + createEntity("alert.on", "on"), + // Automation + createEntity("automation.off", "off"), + createEntity("automation.on", "on"), // Binary Sensor ...BINARY_SENSOR_DEVICE_CLASSES.map((dc) => createEntity(`binary_sensor.${dc}`, "on", dc) @@ -113,8 +117,11 @@ const ENTITIES: HassEntity[] = [ createEntity("button.restart", "unknown", "restart"), createEntity("button.update", "unknown", "update"), // Calendar - createEntity("calendar.on", "on"), createEntity("calendar.off", "off"), + createEntity("calendar.on", "on"), + // Camera + createEntity("camera.off", "off"), + createEntity("camera.on", "on"), // Climate createEntity("climate.off", "off"), createEntity("climate.heat", "heat"), @@ -124,10 +131,10 @@ const ENTITIES: HassEntity[] = [ createEntity("climate.dry", "dry"), createEntity("climate.fan_only", "fan_only"), // Cover - createEntity("cover.opening", "opening"), - createEntity("cover.open", "open"), createEntity("cover.closing", "closing"), createEntity("cover.closed", "closed"), + createEntity("cover.opening", "opening"), + createEntity("cover.open", "open"), createEntity("cover.awning", "open", "awning"), createEntity("cover.blind", "open", "blind"), createEntity("cover.curtain", "open", "curtain"), @@ -139,24 +146,27 @@ const ENTITIES: HassEntity[] = [ createEntity("cover.shutter", "open", "shutter"), createEntity("cover.window", "open", "window"), // Device tracker/person - createEntity("device_tracker.home", "home"), createEntity("device_tracker.not_home", "not_home"), + createEntity("device_tracker.home", "home"), createEntity("device_tracker.work", "work"), createEntity("person.home", "home"), createEntity("person.not_home", "not_home"), createEntity("person.work", "work"), // Fan - createEntity("fan.on", "on"), createEntity("fan.off", "off"), + createEntity("fan.on", "on"), // Humidifier - createEntity("humidifier.on", "on"), createEntity("humidifier.off", "off"), + createEntity("humidifier.on", "on"), + // Helpers + createEntity("input_boolean.off", "off"), + createEntity("input_boolean.on", "on"), // Light - createEntity("light.on", "on"), createEntity("light.off", "off"), + createEntity("light.on", "on"), // Locks - createEntity("lock.locked", "locked"), createEntity("lock.unlocked", "unlocked"), + createEntity("lock.locked", "locked"), createEntity("lock.locking", "locking"), createEntity("lock.unlocking", "unlocking"), createEntity("lock.jammed", "jammed"), @@ -180,6 +190,12 @@ const ENTITIES: HassEntity[] = [ createEntity("media_player.speaker_playing", "playing", "speaker"), createEntity("media_player.speaker_paused", "paused", "speaker"), createEntity("media_player.speaker_standby", "standby", "speaker"), + // Remote + createEntity("remote.off", "off"), + createEntity("remote.on", "on"), + // Script + createEntity("script.off", "off"), + createEntity("script.on", "on"), // Sensor ...SENSOR_DEVICE_CLASSES.map((dc) => createEntity(`sensor.${dc}`, "10", dc)), // Battery sensor @@ -196,9 +212,12 @@ const ENTITIES: HassEntity[] = [ createEntity("switch.outlet_on", "on", "outlet"), createEntity("switch.switch_off", "off", "switch"), createEntity("switch.switch_on", "on", "switch"), + // Timer + createEntity("timer.off", "off"), + createEntity("timer.on", "on"), // Vacuum - createEntity("vacuum.cleaning", "cleaning"), createEntity("vacuum.docked", "docked"), + createEntity("vacuum.cleaning", "cleaning"), createEntity("vacuum.paused", "paused"), createEntity("vacuum.idle", "idle"), createEntity("vacuum.returning", "returning"), @@ -280,18 +299,12 @@ export class DemoEntityState extends LitElement { const columns: DataTableColumnContainer = { icon: { title: "Icon", - template: (_, entry) => { - const cssColor = stateColorCss(entry.stateObj); - return html` - - - `; - }, + template: (_, entry) => html` + + `, }, entity_id: { title: "Entity id", diff --git a/src/common/entity/color/person_color.ts b/src/common/entity/color/person_color.ts new file mode 100644 index 0000000000..7f76a62893 --- /dev/null +++ b/src/common/entity/color/person_color.ts @@ -0,0 +1,10 @@ +import { HassEntity } from "home-assistant-js-websocket"; + +export const personColor = (stateObj: HassEntity): string | undefined => { + switch (stateObj.state) { + case "home": + return "person-home"; + default: + return "person-zone"; + } +}; diff --git a/src/common/entity/state_color.ts b/src/common/entity/state_color.ts index 56317027e1..96bae8ef51 100644 --- a/src/common/entity/state_color.ts +++ b/src/common/entity/state_color.ts @@ -5,6 +5,7 @@ import { alarmControlPanelColor } from "./color/alarm_control_panel_color"; import { binarySensorColor } from "./color/binary_sensor_color"; import { climateColor } from "./color/climate_color"; import { lockColor } from "./color/lock_color"; +import { personColor } from "./color/person_color"; import { sensorColor } from "./color/sensor_color"; import { computeDomain } from "./compute_domain"; import { stateActive } from "./state_active"; @@ -28,6 +29,9 @@ export const stateColor = (stateObj: HassEntity, state?: string) => { const domain = computeDomain(stateObj.entity_id); switch (domain) { + case "automation": + return "automation"; + case "alarm_control_panel": return alarmControlPanelColor(compareState); @@ -55,6 +59,10 @@ export const stateColor = (stateObj: HassEntity, state?: string) => { case "media_player": return "media-player"; + case "person": + case "device_tracker": + return personColor(stateObj); + case "sensor": return sensorColor(stateObj); @@ -68,8 +76,20 @@ export const stateColor = (stateObj: HassEntity, state?: string) => { return compareState === "above_horizon" ? "sun-day" : "sun-night"; case "switch": + case "input_boolean": return "switch"; + case "alert": + return "alert"; + + case "calendar": + case "camera": + case "remote": + case "script": + case "timer": + case "group": + return "active"; + case "update": return updateIsInstalling(stateObj as UpdateEntity) ? "update-installing" diff --git a/src/common/style/icon_color_css.ts b/src/common/style/icon_color_css.ts index bc63f3df1a..8e5f66d90c 100644 --- a/src/common/style/icon_color_css.ts +++ b/src/common/style/icon_color_css.ts @@ -1,29 +1,6 @@ import { css } from "lit"; export const iconColorCSS = css` - 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-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"] { diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 75c21f56b9..2919639891 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -128,6 +128,18 @@ export class HuiTileCard extends LitElement implements LovelaceCard { } private _computeStateColor = memoize((entity: HassEntity, color?: string) => { + if (UNAVAILABLE_STATES.includes(entity.state)) { + return undefined; + } + + // Use default color for person/device_tracker because color is on the badge + if ( + computeDomain(entity.entity_id) === "person" || + computeDomain(entity.entity_id) === "device_tracker" + ) { + return "var(--rgb-state-default-color)"; + } + if (!stateActive(entity)) { return undefined; } diff --git a/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts b/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts index 7eaa3ea340..6770366acd 100644 --- a/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts +++ b/src/panels/lovelace/cards/tile/badges/tile-badge-person.ts @@ -1,6 +1,5 @@ -import { mdiHelp, mdiHome, mdiHomeExportOutline } from "@mdi/js"; +import { mdiHome, mdiHomeExportOutline } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; -import { UNAVAILABLE_STATES } from "../../../../../data/entity"; import { HomeAssistant } from "../../../../../types"; import { ComputeBadgeFunction } from "./tile-badge"; @@ -17,20 +16,18 @@ function getZone(entity: HassEntity, hass: HomeAssistant) { function personBadgeIcon(entity: HassEntity) { const state = entity.state; - if (UNAVAILABLE_STATES.includes(state)) { - return mdiHelp; - } return state === "not_home" ? mdiHomeExportOutline : mdiHome; } -function personBadgeColor(entity: HassEntity, inZone?: boolean) { - if (inZone) { - return "var(--rgb-state-person-zone-color)"; +function personBadgeColor(entity: HassEntity) { + switch (entity.state) { + case "home": + return "var(--rgb-badge-person-home-color)"; + case "not_home": + return "var(--rgb-badge-person-not-home-color)"; + default: + return "var(--rgb-badge-person-zone-color)"; } - const state = entity.state; - return state === "not_home" - ? "var(--rgb-state-person-not-home-color)" - : "var(--rgb-state-person-home-color)"; } export const computePersonBadge: ComputeBadgeFunction = (stateObj, hass) => { @@ -39,6 +36,6 @@ export const computePersonBadge: ComputeBadgeFunction = (stateObj, hass) => { return { iconPath: personBadgeIcon(stateObj), icon: zone?.attributes.icon, - color: personBadgeColor(stateObj, Boolean(zone)), + color: personBadgeColor(stateObj), }; }; diff --git a/src/panels/lovelace/cards/tile/badges/tile-badge.ts b/src/panels/lovelace/cards/tile/badges/tile-badge.ts index eebda6b5e4..6ed8f1b422 100644 --- a/src/panels/lovelace/cards/tile/badges/tile-badge.ts +++ b/src/panels/lovelace/cards/tile/badges/tile-badge.ts @@ -1,5 +1,6 @@ import { HassEntity } from "home-assistant-js-websocket"; import { computeDomain } from "../../../../../common/entity/compute_domain"; +import { UNAVAILABLE_STATES } from "../../../../../data/entity"; import { HomeAssistant } from "../../../../../types"; import { computeClimateBadge } from "./tile-badge-climate"; import { computePersonBadge } from "./tile-badge-person"; @@ -16,6 +17,9 @@ export type ComputeBadgeFunction = ( ) => TileBadge | undefined; export const computeTileBadge: ComputeBadgeFunction = (stateObj, hass) => { + if (UNAVAILABLE_STATES.includes(stateObj.state)) { + return undefined; + } const domain = computeDomain(stateObj.entity_id); switch (domain) { case "person": diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index f0b32c00ed..24ca54f038 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -137,10 +137,13 @@ documentContainer.innerHTML = ` /* rgb state color */ --rgb-state-default-color: 68, 115, 158; + --rgb-state-active-color: var(--rgb-primary-color); --rgb-state-alarm-armed-color: var(--rgb-red-color); --rgb-state-alarm-pending-color: var(--rgb-orange-color); --rgb-state-alarm-arming-color: var(--rgb-orange-color); --rgb-state-alarm-triggered-color: var(--rgb-red-color); + --rgb-state-alert-color: var(--rgb-red-color); + --rgb-state-automation-color: var(--rgb-amber-color); --rgb-state-binary-sensor-color: var(--rgb-primary-color); --rgb-state-binary-sensor-alerting-color: var(--rgb-red-color); --rgb-state-cover-color: var(--rgb-purple-color); @@ -152,7 +155,6 @@ documentContainer.innerHTML = ` --rgb-state-lock-pending-color: var(--rgb-orange-color); --rgb-state-media-player-color: var(--rgb-indigo-color); --rgb-state-person-home-color: var(--rgb-green-color); - --rgb-state-person-not-home-color: var(--rgb-red-color); --rgb-state-person-zone-color: var(--rgb-blue-color); --rgb-state-sensor-battery-high-color: var(--rgb-green-color); --rgb-state-sensor-battery-low-color: var(--rgb-red-color); @@ -173,6 +175,11 @@ documentContainer.innerHTML = ` --rgb-state-climate-heat-cool-color: var(--rgb-state-default-color); --rgb-state-climate-idle-color: var(--rgb-disabled-color); + /* rgb state badge color */ + --rgb-badge-person-home-color: var(--rgb-state-person-home-color); + --rgb-badge-person-zone-color: var(--rgb-state-person-zone-color); + --rgb-badge-person-not-home-color: var(--rgb-red-color); + /* input components */ --input-idle-line-color: rgba(0, 0, 0, 0.42); --input-hover-line-color: rgba(0, 0, 0, 0.87);