mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Color adjustments for entity state (#14557)
This commit is contained in:
parent
83ba594cc4
commit
e6f2e8058b
@ -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",
|
||||
|
10
src/common/entity/color/person_color.ts
Normal file
10
src/common/entity/color/person_color.ts
Normal 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";
|
||||
}
|
||||
};
|
@ -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"
|
||||
|
@ -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"] {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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),
|
||||
};
|
||||
};
|
||||
|
@ -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":
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user