diff --git a/src/panels/lovelace/cards/hui-entities-card.ts b/src/panels/lovelace/cards/hui-entities-card.ts
index ed1916e6ab94..9aa1964e55cb 100644
--- a/src/panels/lovelace/cards/hui-entities-card.ts
+++ b/src/panels/lovelace/cards/hui-entities-card.ts
@@ -8,6 +8,7 @@ import "../../../components/ha-card";
import type { HomeAssistant } from "../../../types";
import { computeCardSize } from "../common/compute-card-size";
import { findEntities } from "../common/find-entities";
+import { applyDefaultColor } from "../common/entity-color-config";
import { processConfigEntities } from "../common/process-config-entities";
import "../components/hui-entities-toggle";
import { createHeaderFooterElement } from "../create-element/create-header-footer-element";
@@ -24,7 +25,7 @@ import type {
LovelaceHeaderFooter,
} from "../types";
import { migrateEntitiesCardConfig } from "./migrate-card-config";
-import type { EntitiesCardConfig } from "./types";
+import type { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
import { haStyleScrollbar } from "../../../resources/styles";
export const computeShowHeaderToggle = <
@@ -159,7 +160,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
const migratedConfig = migrateEntitiesCardConfig(config);
const entities = processConfigEntities(migratedConfig.entities);
- this._config = migratedConfig;
+ this._config = { color: "state", ...migratedConfig };
this._configEntities = entities;
this._showHeaderToggle = computeShowHeaderToggle(migratedConfig, entities);
if (this._config.header) {
@@ -343,18 +344,18 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
`,
];
- private _renderEntity(entityConf: LovelaceRowConfig): TemplateResult {
- const element = createRowElement(
- (!("type" in entityConf) || entityConf.type === "conditional") &&
- "state_color" in this._config!
- ? ({
- state_color: this._config.state_color,
- ...(entityConf as EntityConfig),
- } as EntityConfig)
- : entityConf.type === "perform-action"
- ? { ...entityConf, type: "call-service" }
- : entityConf
+ private _rowConfig(entityConf: LovelaceRowConfig): LovelaceRowConfig {
+ if (entityConf.type === "perform-action") {
+ return { ...entityConf, type: "call-service" };
+ }
+ return applyDefaultColor(
+ entityConf as EntitiesCardEntityConfig,
+ this._config!.color
);
+ }
+
+ private _renderEntity(entityConf: LovelaceRowConfig): TemplateResult {
+ const element = createRowElement(this._rowConfig(entityConf));
if (this._hass) {
element.hass = this._hass;
}
diff --git a/src/panels/lovelace/cards/hui-glance-card.ts b/src/panels/lovelace/cards/hui-glance-card.ts
index 7fabdfbb2a6a..d091ab70a096 100644
--- a/src/panels/lovelace/cards/hui-glance-card.ts
+++ b/src/panels/lovelace/cards/hui-glance-card.ts
@@ -26,6 +26,7 @@ import { findEntities } from "../common/find-entities";
import { handleAction } from "../common/handle-action";
import { hasAction, hasAnyAction } from "../common/has-action";
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
+import { applyDefaultColor } from "../common/entity-color-config";
import { processConfigEntities } from "../common/process-config-entities";
import "../components/hui-timestamp-display";
import { createEntityNotFoundWarning } from "../components/hui-warning";
@@ -87,14 +88,19 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
show_name: true,
show_state: true,
show_icon: true,
- state_color: true,
+ color: "state",
...migratedConfig,
};
+ const cardColor = this._config.color;
const entities = processConfigEntities(migratedConfig.entities).map(
- (entityConf) => ({
- hold_action: { action: "more-info" } as MoreInfoActionConfig,
- ...entityConf,
- })
+ (entityConf) =>
+ applyDefaultColor(
+ {
+ hold_action: { action: "more-info" } as MoreInfoActionConfig,
+ ...entityConf,
+ },
+ cardColor
+ )
);
for (const entity of entities) {
@@ -294,9 +300,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
.stateObj=${stateObj}
.overrideIcon=${entityConf.icon}
.overrideImage=${entityConf.image}
- .stateColor=${
- entityConf.state_color ?? this._config!.state_color
- }
+ .color=${entityConf.color}
>
`
: ""
diff --git a/src/panels/lovelace/cards/migrate-card-config.ts b/src/panels/lovelace/cards/migrate-card-config.ts
index 50c4b6f7e7d3..8221033c391f 100644
--- a/src/panels/lovelace/cards/migrate-card-config.ts
+++ b/src/panels/lovelace/cards/migrate-card-config.ts
@@ -1,40 +1,56 @@
-import type { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
+import { migrateStateColorConfig } from "../common/entity-color-config";
+import { migrateTimeFormatConfig } from "../common/entity-time-format-config";
+import type {
+ ConditionalRowConfig,
+ LovelaceRowConfig,
+} from "../entity-rows/types";
import type {
EntitiesCardConfig,
+ EntitiesCardEntityConfig,
GlanceCardConfig,
GlanceConfigEntity,
} from "./types";
+const migrateEntitiesRowConfig = (
+ rowConf: LovelaceRowConfig | string
+): LovelaceRowConfig | string => {
+ if (typeof rowConf !== "object") {
+ return rowConf;
+ }
+ let newConf: LovelaceRowConfig = rowConf;
+ newConf = migrateTimeFormatConfig(newConf as EntitiesCardEntityConfig);
+ newConf = migrateStateColorConfig(newConf as EntitiesCardEntityConfig);
+ if (newConf.type === "conditional") {
+ const row = (newConf as ConditionalRowConfig).row;
+ if (row && typeof row === "object") {
+ let newRow = migrateTimeFormatConfig(row as EntitiesCardEntityConfig);
+ newRow = migrateStateColorConfig(newRow);
+ if (newRow !== row) {
+ newConf = { ...newConf, row: newRow } as ConditionalRowConfig;
+ }
+ }
+ }
+ return newConf;
+};
+
export const migrateEntitiesCardConfig = (
config: EntitiesCardConfig
): EntitiesCardConfig => {
let changed = false;
const newEntities = config.entities?.map((e) => {
- if (typeof e !== "object") {
- return e;
- }
- // Custom rows own their config schema and may use `format` with a
- // different meaning (e.g. custom:multiple-entity-row), so leave it
- // untouched.
- if (e.type?.startsWith("custom:")) {
- return e;
+ const newConf = migrateEntitiesRowConfig(e);
+ if (newConf !== e) {
+ changed = true;
}
- if (!("format" in e)) {
- return e;
- }
- changed = true;
- const { format, ...rest } = e;
- return {
- ...rest,
- time_format: (rest as EntityConfig).time_format ?? format,
- };
+ return newConf;
});
+ const newConfig = migrateStateColorConfig(config);
if (!changed) {
- return config;
+ return newConfig;
}
return {
- ...config,
- entities: newEntities as (LovelaceRowConfig | string)[],
+ ...newConfig,
+ entities: newEntities,
};
};
@@ -46,21 +62,20 @@ export const migrateGlanceCardConfig = (
if (typeof e !== "object") {
return e;
}
- if (!("format" in e)) {
- return e;
+ let newConf = e;
+ newConf = migrateTimeFormatConfig(newConf);
+ newConf = migrateStateColorConfig(newConf);
+ if (newConf !== e) {
+ changed = true;
}
- changed = true;
- const { format, ...rest } = e;
- return {
- ...rest,
- time_format: rest.time_format ?? format,
- };
+ return newConf;
});
+ const newConfig = migrateStateColorConfig(config);
if (!changed) {
- return config;
+ return newConfig;
}
return {
- ...config,
+ ...newConfig,
entities: newEntities as (GlanceConfigEntity | string)[],
};
};
diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts
index 6850ff49f703..919d3eac06ff 100644
--- a/src/panels/lovelace/cards/types.ts
+++ b/src/panels/lovelace/cards/types.ts
@@ -112,7 +112,9 @@ export interface EntitiesCardEntityConfig extends EntityConfig {
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
+ /** @deprecated use `color` instead */
state_color?: boolean;
+ color?: string;
show_name?: boolean;
show_icon?: boolean;
}
@@ -126,7 +128,9 @@ export interface EntitiesCardConfig extends LovelaceCardConfig {
icon?: string;
header?: LovelaceHeaderFooterConfig;
footer?: LovelaceHeaderFooterConfig;
+ /** @deprecated use `color` instead */
state_color?: boolean;
+ color?: string;
}
export type AreaCardDisplayType = "compact" | "icon" | "picture" | "camera";
@@ -330,7 +334,9 @@ export interface GlanceConfigEntity extends ConfigEntity {
show_last_changed?: boolean;
image?: string;
show_state?: boolean;
+ /** @deprecated use `color` instead */
state_color?: boolean;
+ color?: string;
time_format?: TimestampRenderingFormat;
}
@@ -342,7 +348,9 @@ export interface GlanceCardConfig extends LovelaceCardConfig {
theme?: string;
entities: (string | GlanceConfigEntity)[];
columns?: number;
+ /** @deprecated use `color` instead */
state_color?: boolean;
+ color?: string;
}
export interface HumidifierCardConfig extends LovelaceCardConfig {
diff --git a/src/panels/lovelace/common/entity-color-config.ts b/src/panels/lovelace/common/entity-color-config.ts
new file mode 100644
index 000000000000..cd2f785dfb6d
--- /dev/null
+++ b/src/panels/lovelace/common/entity-color-config.ts
@@ -0,0 +1,34 @@
+import { isCustomType } from "../../../data/lovelace_custom_cards";
+
+interface LegacyStateColorConfig {
+ type?: string;
+ color?: string;
+ state_color?: boolean;
+}
+
+export const migrateStateColorConfig =
(
+ config: T
+): T => {
+ // Custom elements own their config schema, leave them untouched
+ if (config.type !== undefined && isCustomType(config.type)) {
+ return config;
+ }
+ if (config.state_color === undefined) {
+ return config;
+ }
+ const { state_color, ...rest } = config;
+ return {
+ color: state_color ? "state" : "none",
+ ...rest,
+ } as T;
+};
+
+export const applyDefaultColor = (
+ config: T,
+ color: string | undefined
+): T =>
+ color === undefined ||
+ config.color !== undefined ||
+ (config.type !== undefined && isCustomType(config.type))
+ ? config
+ : { ...config, color };
diff --git a/src/panels/lovelace/common/entity-time-format-config.ts b/src/panels/lovelace/common/entity-time-format-config.ts
new file mode 100644
index 000000000000..46587615e518
--- /dev/null
+++ b/src/panels/lovelace/common/entity-time-format-config.ts
@@ -0,0 +1,27 @@
+import { isCustomType } from "../../../data/lovelace_custom_cards";
+import type { TimestampRenderingFormat } from "../components/types";
+
+interface LegacyTimeFormatConfig {
+ type?: string;
+ time_format?: TimestampRenderingFormat;
+ /** @deprecated use `time_format` instead */
+ format?: TimestampRenderingFormat;
+}
+
+export const migrateTimeFormatConfig = (
+ config: T
+): T => {
+ // Custom elements own their config schema and may use the same option with
+ // a different meaning (e.g. custom:multiple-entity-row), leave them untouched
+ if (config.type !== undefined && isCustomType(config.type)) {
+ return config;
+ }
+ if (config.format === undefined) {
+ return config;
+ }
+ const { format, ...rest } = config;
+ return {
+ time_format: format,
+ ...rest,
+ } as T;
+};
diff --git a/src/panels/lovelace/components/hui-generic-entity-row.ts b/src/panels/lovelace/components/hui-generic-entity-row.ts
index 0b3780736036..a038f956b8e8 100644
--- a/src/panels/lovelace/components/hui-generic-entity-row.ts
+++ b/src/panels/lovelace/components/hui-generic-entity-row.ts
@@ -86,6 +86,7 @@ export class HuiGenericEntityRow extends LitElement {
.overrideIcon=${this.config.icon}
.overrideImage=${this.config.image}
.stateColor=${this.config.state_color}
+ .color=${this.config.color}
>
${
!this.hideName
diff --git a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts
index c888ebdb2d5d..cb09148ac9a0 100644
--- a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts
@@ -22,11 +22,9 @@ import type { HASSDomEvent } from "../../../../common/dom/fire_event";
import { fireEvent } from "../../../../common/dom/fire_event";
import { customType } from "../../../../common/structs/is-custom-type";
import "../../../../components/ha-card";
-import "../../../../components/ha-formfield";
+import "../../../../components/ha-form/ha-form";
+import type { SchemaUnion } from "../../../../components/ha-form/types";
import "../../../../components/ha-icon";
-import "../../../../components/ha-switch";
-import "../../../../components/ha-theme-picker";
-import "../../../../components/input/ha-input";
import { isCustomType } from "../../../../data/lovelace_custom_cards";
import type { HomeAssistant } from "../../../../types";
import {
@@ -90,6 +88,7 @@ const conditionalEntitiesRowConfigStruct = object({
type: literal("conditional"),
row: any(),
conditions: array(any()),
+ color: optional(string()),
});
const dividerEntitiesRowConfigStruct = object({
@@ -181,6 +180,22 @@ const entitiesRowConfigStruct = dynamic((value) => {
return entitiesConfigStruct;
});
+const SCHEMA = [
+ { name: "title", selector: { text: {} } },
+ { name: "theme", selector: { theme: {} } },
+ {
+ name: "color",
+ selector: {
+ ui_color: {
+ default_color: "state",
+ include_state: true,
+ include_none: true,
+ },
+ },
+ },
+ { name: "show_header_toggle", selector: { boolean: {} } },
+] as const;
+
const cardConfigStruct = assign(
baseLovelaceCardConfig,
object({
@@ -189,7 +204,7 @@ const cardConfigStruct = assign(
theme: optional(string()),
icon: optional(string()),
show_header_toggle: optional(boolean()),
- state_color: optional(boolean()),
+ color: optional(string()),
entities: array(entitiesRowConfigStruct),
header: optional(headerFooterConfigStructs),
footer: optional(headerFooterConfigStructs),
@@ -226,14 +241,6 @@ export class HuiEntitiesCardEditor
);
});
- get _title(): string {
- return this._config!.title || "";
- }
-
- get _theme(): string {
- return this._config!.theme || "";
- }
-
protected render() {
if (!this.hass || !this._config) {
return nothing;
@@ -251,52 +258,20 @@ export class HuiEntitiesCardEditor
`;
}
+ const data = {
+ ...this._config,
+ show_header_toggle: this._showHeaderToggle(this._config),
+ };
+
return html`
-
-
-
-
-
-
-
-
-
-
+
) => {
+ switch (schema.name) {
+ case "title":
+ case "theme":
+ return `${this.hass!.localize(
+ `ui.panel.lovelace.editor.card.generic.${schema.name}`
+ )} (${this.hass!.localize(
+ "ui.panel.lovelace.editor.card.config.optional"
+ )})`;
+ case "show_header_toggle":
+ return this.hass!.localize(
+ "ui.panel.lovelace.editor.card.entities.show_header_toggle"
+ );
+ default:
+ return this.hass!.localize(
+ `ui.panel.lovelace.editor.card.generic.${schema.name}`
+ );
+ }
+ };
+
private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation();
if (!this._config || !this.hass) {
@@ -330,17 +342,7 @@ export class HuiEntitiesCardEditor
const target = ev.target! as EditorTarget;
const configValue =
target.configValue || this._subElementEditorConfig?.type;
- const value =
- target.checked !== undefined
- ? target.checked
- : target.value || ev.detail.config || ev.detail.value;
-
- if (
- (configValue === "title" && target.value === this._title) ||
- (configValue === "theme" && target.value === this._theme)
- ) {
- return;
- }
+ const value = ev.detail.config ?? ev.detail.value;
if (configValue === "row" || (ev.detail && ev.detail.entities)) {
const newConfigEntities =
@@ -359,7 +361,7 @@ export class HuiEntitiesCardEditor
this._config = { ...this._config!, entities: newConfigEntities };
this._configEntities = processEditorEntities(this._config!.entities);
} else if (configValue) {
- if (value === "") {
+ if (value === "" || value === undefined) {
this._config = { ...this._config };
delete this._config[configValue!];
} else {
@@ -435,10 +437,6 @@ export class HuiEntitiesCardEditor
hui-header-footer-editor {
padding-top: var(--ha-space-1);
}
-
- ha-input {
- --ha-input-padding-bottom: var(--ha-space-4);
- }
`,
];
}
diff --git a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
index 8bc1bd43d743..25677aacb094 100644
--- a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts
@@ -59,13 +59,28 @@ export class HuiGenericEntityRowEditor
context: { entity: "entity" },
},
{
- name: "icon",
- selector: {
- icon: {},
- },
- context: {
- icon_entity: "entity",
- },
+ name: "",
+ type: "grid",
+ schema: [
+ {
+ name: "icon",
+ selector: {
+ icon: {},
+ },
+ context: {
+ icon_entity: "entity",
+ },
+ },
+ {
+ name: "color",
+ selector: {
+ ui_color: {
+ include_state: true,
+ include_none: true,
+ },
+ },
+ },
+ ],
},
{
name: "secondary_info",
diff --git a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts
index 1952089dab85..c9006db633ff 100644
--- a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts
@@ -44,7 +44,7 @@ const cardConfigStruct = assign(
show_name: optional(boolean()),
show_state: optional(boolean()),
show_icon: optional(boolean()),
- state_color: optional(boolean()),
+ color: optional(string()),
entities: array(entitiesConfigStruct),
})
);
@@ -69,7 +69,16 @@ const SCHEMA = [
{ name: "show_state", selector: { boolean: {} } },
],
},
- { name: "state_color", selector: { boolean: {} } },
+ {
+ name: "color",
+ selector: {
+ ui_color: {
+ default_color: "state",
+ include_state: true,
+ include_none: true,
+ },
+ },
+ },
] as const;
@customElement("hui-glance-card-editor")
@@ -115,6 +124,15 @@ export class HuiGlanceCardEditor
icon_entity: "entity",
},
},
+ {
+ name: "color",
+ selector: {
+ ui_color: {
+ include_state: true,
+ include_none: true,
+ },
+ },
+ },
{ name: "show_last_changed", selector: { boolean: {} } },
{ name: "show_state", selector: { boolean: {} }, default: true },
],
diff --git a/src/panels/lovelace/editor/structs/entities-struct.ts b/src/panels/lovelace/editor/structs/entities-struct.ts
index f6ec8277ff72..4db3552c837e 100644
--- a/src/panels/lovelace/editor/structs/entities-struct.ts
+++ b/src/panels/lovelace/editor/structs/entities-struct.ts
@@ -14,7 +14,7 @@ export const entitiesConfigStruct = union([
image: optional(string()),
secondary_info: optional(string()),
time_format: optional(timeFormatConfigStruct),
- state_color: optional(boolean()),
+ color: optional(string()),
tap_action: optional(actionConfigStruct),
hold_action: optional(actionConfigStruct),
double_tap_action: optional(actionConfigStruct),
diff --git a/src/panels/lovelace/special-rows/hui-conditional-row.ts b/src/panels/lovelace/special-rows/hui-conditional-row.ts
index 879e4d27da1f..752ac66b3da3 100644
--- a/src/panels/lovelace/special-rows/hui-conditional-row.ts
+++ b/src/panels/lovelace/special-rows/hui-conditional-row.ts
@@ -1,12 +1,9 @@
import { customElement } from "lit/decorators";
-import type { EntityCardConfig } from "../cards/types";
+import type { EntitiesCardEntityConfig } from "../cards/types";
+import { applyDefaultColor } from "../common/entity-color-config";
import { HuiConditionalBase } from "../components/hui-conditional-base";
import { createRowElement } from "../create-element/create-row-element";
-import type {
- ConditionalRowConfig,
- EntityConfig,
- LovelaceRow,
-} from "../entity-rows/types";
+import type { ConditionalRowConfig, LovelaceRow } from "../entity-rows/types";
import { fireEvent } from "../../../common/dom/fire_event";
declare global {
@@ -23,13 +20,10 @@ class HuiConditionalRow extends HuiConditionalBase implements LovelaceRow {
throw new Error("No row configured");
}
+ const { color } = config as EntitiesCardEntityConfig;
+
this._element = createRowElement(
- (config as EntityCardConfig).state_color
- ? ({
- state_color: true,
- ...(config.row as EntityConfig),
- } as EntityConfig)
- : config.row
+ applyDefaultColor(config.row as EntitiesCardEntityConfig, color)
) as LovelaceRow;
}
diff --git a/test/panels/lovelace/cards/migrate-card-config.test.ts b/test/panels/lovelace/cards/migrate-card-config.test.ts
index 37767e9c72a2..544611df4b9b 100644
--- a/test/panels/lovelace/cards/migrate-card-config.test.ts
+++ b/test/panels/lovelace/cards/migrate-card-config.test.ts
@@ -83,6 +83,87 @@ describe("migrateEntitiesCardConfig", () => {
time_format: "datetime",
});
});
+
+ it("migrates card and entity level state_color to color", () => {
+ expect(
+ migrateEntitiesCardConfig({
+ type: "entities",
+ state_color: true,
+ entities: [
+ "light.bed_light",
+ { entity: "switch.ac", state_color: false },
+ {
+ entity: "sensor.humidity",
+ type: "simple-entity",
+ state_color: true,
+ },
+ ],
+ } as unknown as EntitiesCardConfig)
+ ).toEqual({
+ type: "entities",
+ color: "state",
+ entities: [
+ "light.bed_light",
+ { entity: "switch.ac", color: "none" },
+ { entity: "sensor.humidity", type: "simple-entity", color: "state" },
+ ],
+ });
+ });
+
+ it("keeps an explicit color over the legacy state_color", () => {
+ expect(
+ migrateEntitiesCardConfig({
+ type: "entities",
+ entities: [{ entity: "switch.ac", state_color: true, color: "red" }],
+ } as unknown as EntitiesCardConfig)
+ ).toEqual({
+ type: "entities",
+ entities: [{ entity: "switch.ac", color: "red" }],
+ });
+ });
+
+ it("keeps state_color on custom rows untouched", () => {
+ const customRow = {
+ entity: "sensor.power",
+ type: "custom:multiple-entity-row",
+ state_color: true,
+ };
+ const config = {
+ type: "entities",
+ entities: [customRow],
+ } as unknown as EntitiesCardConfig;
+
+ const result = migrateEntitiesCardConfig(config);
+
+ expect(result).toBe(config);
+ expect(result.entities[0]).toEqual(customRow);
+ });
+
+ it("migrates conditional rows and their inner rows", () => {
+ expect(
+ migrateEntitiesCardConfig({
+ type: "entities",
+ entities: [
+ {
+ type: "conditional",
+ state_color: false,
+ conditions: [],
+ row: { entity: "light.bed_light", state_color: true },
+ },
+ ],
+ } as unknown as EntitiesCardConfig)
+ ).toEqual({
+ type: "entities",
+ entities: [
+ {
+ type: "conditional",
+ color: "none",
+ conditions: [],
+ row: { entity: "light.bed_light", color: "state" },
+ },
+ ],
+ });
+ });
});
describe("migrateGlanceCardConfig", () => {
@@ -124,4 +205,21 @@ describe("migrateGlanceCardConfig", () => {
time_format: "datetime",
});
});
+
+ it("migrates card and entity level state_color to color", () => {
+ expect(
+ migrateGlanceCardConfig({
+ type: "glance",
+ state_color: false,
+ entities: [
+ "light.bed_light",
+ { entity: "switch.ac", state_color: true },
+ ],
+ } as unknown as GlanceCardConfig)
+ ).toEqual({
+ type: "glance",
+ color: "none",
+ entities: ["light.bed_light", { entity: "switch.ac", color: "state" }],
+ });
+ });
});
diff --git a/test/panels/lovelace/common/entity-color-config.test.ts b/test/panels/lovelace/common/entity-color-config.test.ts
new file mode 100644
index 000000000000..fad6ab14294b
--- /dev/null
+++ b/test/panels/lovelace/common/entity-color-config.test.ts
@@ -0,0 +1,34 @@
+import { describe, expect, it } from "vitest";
+
+import { applyDefaultColor } from "../../../../src/panels/lovelace/common/entity-color-config";
+
+describe("applyDefaultColor", () => {
+ interface TestEntityConfig {
+ entity: string;
+ type?: string;
+ color?: string;
+ }
+
+ it("applies the default color when none is set", () => {
+ const config: TestEntityConfig = { entity: "light.a" };
+ expect(applyDefaultColor(config, "state")).toEqual({
+ entity: "light.a",
+ color: "state",
+ });
+ });
+
+ it("keeps an explicit color", () => {
+ const config: TestEntityConfig = { entity: "light.a", color: "red" };
+ expect(applyDefaultColor(config, "state")).toBe(config);
+ });
+
+ it("returns the same object without a default color", () => {
+ const config: TestEntityConfig = { entity: "light.a" };
+ expect(applyDefaultColor(config, undefined)).toBe(config);
+ });
+
+ it("keeps custom elements untouched", () => {
+ const config: TestEntityConfig = { entity: "light.a", type: "custom:foo" };
+ expect(applyDefaultColor(config, "state")).toBe(config);
+ });
+});