Color adjustments for entity state (#14557)

This commit is contained in:
Paul Bottein 2022-12-06 17:45:24 +01:00 committed by GitHub
parent 83ba594cc4
commit e6f2e8058b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 61 deletions

View File

@ -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<EntityRowData> = {
icon: {
title: "Icon",
template: (_, entry) => {
const cssColor = stateColorCss(entry.stateObj);
return html`
<ha-svg-icon
style=${styleMap({
color: `rgb(${cssColor})`,
})}
.path=${stateIconPath(entry.stateObj)}
>
</ha-svg-icon>
`;
},
template: (_, entry) => html`
<state-badge
.stateObj=${entry.stateObj}
.stateColor=${true}
></state-badge>
`,
},
entity_id: {
title: "Entity id",

View File

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

View File

@ -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"

View File

@ -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"] {

View File

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

View File

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

View File

@ -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":

View File

@ -137,10 +137,13 @@ documentContainer.innerHTML = `<custom-style>
/* 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 = `<custom-style>
--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 = `<custom-style>
--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);