Convert default state icons (#10223)

* Convert default state icons

* update

* Update cast/src/launcher/layout/hc-cast.ts

Co-authored-by: Philip Allgaier <mail@spacegaier.de>

* Update ha-config-core.js

* Update

* Finish

* Add siren icon

* FIx

* Add curtain icons

Co-authored-by: Philip Allgaier <mail@spacegaier.de>
This commit is contained in:
Bram Kragten 2021-10-20 11:10:16 +02:00 committed by GitHub
parent b760e543b0
commit 667fd39147
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 829 additions and 573 deletions

View File

@ -1,4 +1,5 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import { mdiCast, mdiCastConnected } from "@mdi/js";
import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-listbox/paper-listbox";
import { Auth, Connection } from "home-assistant-js-websocket"; import { Auth, Connection } from "home-assistant-js-websocket";
@ -17,6 +18,7 @@ import {
import { atLeastVersion } from "../../../../src/common/config/version"; import { atLeastVersion } from "../../../../src/common/config/version";
import { toggleAttribute } from "../../../../src/common/dom/toggle_attribute"; import { toggleAttribute } from "../../../../src/common/dom/toggle_attribute";
import "../../../../src/components/ha-icon"; import "../../../../src/components/ha-icon";
import "../../../../src/components/ha-svg-icon";
import { import {
getLegacyLovelaceCollection, getLegacyLovelaceCollection,
getLovelaceCollection, getLovelaceCollection,
@ -73,7 +75,7 @@ class HcCast extends LitElement {
? html` ? html`
<p class="center-item"> <p class="center-item">
<mwc-button raised @click=${this._handleLaunch}> <mwc-button raised @click=${this._handleLaunch}>
<ha-icon icon="hass:cast"></ha-icon> <ha-svg-icon .path=${mdiCast}></ha-svg-icon>
Start Casting Start Casting
</mwc-button> </mwc-button>
</p> </p>
@ -111,7 +113,7 @@ class HcCast extends LitElement {
${this.castManager.status ${this.castManager.status
? html` ? html`
<mwc-button @click=${this._handleLaunch}> <mwc-button @click=${this._handleLaunch}>
<ha-icon icon="hass:cast-connected"></ha-icon> <ha-svg-icon .path=${mdiCastConnected}></ha-svg-icon>
Manage Manage
</mwc-button> </mwc-button>
` `
@ -233,7 +235,7 @@ class HcCast extends LitElement {
color: var(--secondary-text-color); color: var(--secondary-text-color);
} }
mwc-button ha-icon { mwc-button ha-svg-icon {
margin-right: 8px; margin-right: 8px;
height: 18px; height: 18px;
} }

View File

@ -1,4 +1,5 @@
import "@material/mwc-button"; import "@material/mwc-button";
import { mdiCastConnected, mdiCast } from "@mdi/js";
import "@polymer/paper-input/paper-input"; import "@polymer/paper-input/paper-input";
import { import {
Auth, Auth,
@ -19,7 +20,7 @@ import {
loadTokens, loadTokens,
saveTokens, saveTokens,
} from "../../../../src/common/auth/token_storage"; } from "../../../../src/common/auth/token_storage";
import "../../../../src/components/ha-icon"; import "../../../../src/components/ha-svg-icon";
import "../../../../src/layouts/hass-loading-screen"; import "../../../../src/layouts/hass-loading-screen";
import { registerServiceWorker } from "../../../../src/util/register-service-worker"; import { registerServiceWorker } from "../../../../src/util/register-service-worker";
import "./hc-layout"; import "./hc-layout";
@ -127,11 +128,11 @@ export class HcConnect extends LitElement {
<div class="card-actions"> <div class="card-actions">
<mwc-button @click=${this._handleDemo}> <mwc-button @click=${this._handleDemo}>
Show Demo Show Demo
<ha-icon <ha-svg-icon
.icon=${this.castManager.castState === "CONNECTED" .path=${this.castManager.castState === "CONNECTED"
? "hass:cast-connected" ? mdiCastConnected
: "hass:cast"} : mdiCast}
></ha-icon> ></ha-svg-icon>
</mwc-button> </mwc-button>
<div class="spacer"></div> <div class="spacer"></div>
<mwc-button @click=${this._handleConnect}>Authorize</mwc-button> <mwc-button @click=${this._handleConnect}>Authorize</mwc-button>
@ -307,7 +308,7 @@ export class HcConnect extends LitElement {
color: darkred; color: darkred;
} }
mwc-button ha-icon { mwc-button ha-svg-icon {
margin-left: 8px; margin-left: 8px;
} }

View File

@ -1,3 +1,4 @@
import { mdiTelevision } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators"; import { customElement, state } from "lit/decorators";
import { CastManager } from "../../../src/cast/cast_manager"; import { CastManager } from "../../../src/cast/cast_manager";
@ -27,7 +28,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
return html``; return html``;
} }
return html` return html`
<ha-icon icon="hademo:television"></ha-icon> <ha-svg-icon .path=${mdiTelevision}></ha-svg-icon>
<div class="flex"> <div class="flex">
<div class="name">Show Chromecast interface</div> <div class="name">Show Chromecast interface</div>
<google-cast-launcher></google-cast-launcher> <google-cast-launcher></google-cast-launcher>
@ -72,7 +73,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
display: flex; display: flex;
align-items: center; align-items: center;
} }
ha-icon { ha-svg-icon {
padding: 8px; padding: 8px;
color: var(--paper-item-icon-color); color: var(--paper-item-icon-color);
} }

View File

@ -1,88 +1,146 @@
/** Constants to be used in the frontend. */ /** Constants to be used in the frontend. */
import {
mdiAccount,
mdiAirFilter,
mdiAlert,
mdiAngleAcute,
mdiAppleSafari,
mdiBell,
mdiBookmark,
mdiBrightness5,
mdiBullhorn,
mdiCalendar,
mdiCalendarClock,
mdiCash,
mdiClock,
mdiCloudUpload,
mdiCog,
mdiCommentAlert,
mdiCounter,
mdiCurrentAc,
mdiEye,
mdiFan,
mdiFlash,
mdiFlower,
mdiFormatListBulleted,
mdiFormTextbox,
mdiGasCylinder,
mdiGauge,
mdiGoogleAssistant,
mdiGoogleCirclesCommunities,
mdiHomeAssistant,
mdiHomeAutomation,
mdiImageFilterFrames,
mdiLightbulb,
mdiLightningBolt,
mdiMailbox,
mdiMapMarkerRadius,
mdiMolecule,
mdiMoleculeCo,
mdiMoleculeCo2,
mdiPalette,
mdiRayVertex,
mdiRemote,
mdiRobot,
mdiRobotVacuum,
mdiScriptText,
mdiSineWave,
mdiTextToSpeech,
mdiThermometer,
mdiThermostat,
mdiTimerOutline,
mdiToggleSwitchOutline,
mdiVideo,
mdiWaterPercent,
mdiWeatherCloudy,
mdiWhiteBalanceSunny,
mdiWifi,
} from "@mdi/js";
// Constants should be alphabetically sorted by name. // Constants should be alphabetically sorted by name.
// Arrays with values should be alphabetically sorted if order doesn't matter. // Arrays with values should be alphabetically sorted if order doesn't matter.
// Each constant should have a description what it is supposed to be used for. // Each constant should have a description what it is supposed to be used for.
/** Icon to use when no icon specified for domain. */ /** Icon to use when no icon specified for domain. */
export const DEFAULT_DOMAIN_ICON = "hass:bookmark"; export const DEFAULT_DOMAIN_ICON = mdiBookmark;
/** Icons for each domain */ /** Icons for each domain */
export const FIXED_DOMAIN_ICONS = { export const FIXED_DOMAIN_ICONS = {
alert: "hass:alert", alert: mdiAlert,
alexa: "hass:amazon-alexa", air_quality: mdiAirFilter,
air_quality: "hass:air-filter", automation: mdiRobot,
automation: "hass:robot", calendar: mdiCalendar,
calendar: "hass:calendar", camera: mdiVideo,
camera: "hass:video", climate: mdiThermostat,
climate: "hass:thermostat", configurator: mdiCog,
configurator: "hass:cog", conversation: mdiTextToSpeech,
conversation: "hass:text-to-speech", counter: mdiCounter,
counter: "hass:counter", device_tracker: mdiAccount,
device_tracker: "hass:account", fan: mdiFan,
fan: "hass:fan", google_assistant: mdiGoogleAssistant,
google_assistant: "hass:google-assistant", group: mdiGoogleCirclesCommunities,
group: "hass:google-circles-communities", homeassistant: mdiHomeAssistant,
homeassistant: "hass:home-assistant", homekit: mdiHomeAutomation,
homekit: "hass:home-automation", image_processing: mdiImageFilterFrames,
image_processing: "hass:image-filter-frames", input_boolean: mdiToggleSwitchOutline,
input_boolean: "hass:toggle-switch-outline", input_datetime: mdiCalendarClock,
input_datetime: "hass:calendar-clock", input_number: mdiRayVertex,
input_number: "hass:ray-vertex", input_select: mdiFormatListBulleted,
input_select: "hass:format-list-bulleted", input_text: mdiFormTextbox,
input_text: "hass:form-textbox", light: mdiLightbulb,
light: "hass:lightbulb", mailbox: mdiMailbox,
mailbox: "hass:mailbox", notify: mdiCommentAlert,
notify: "hass:comment-alert", number: mdiRayVertex,
number: "hass:ray-vertex", persistent_notification: mdiBell,
persistent_notification: "hass:bell", person: mdiAccount,
person: "hass:account", plant: mdiFlower,
plant: "hass:flower", proximity: mdiAppleSafari,
proximity: "hass:apple-safari", remote: mdiRemote,
remote: "hass:remote", scene: mdiPalette,
scene: "hass:palette", script: mdiScriptText,
script: "hass:script-text", select: mdiFormatListBulleted,
select: "hass:format-list-bulleted", sensor: mdiEye,
sensor: "hass:eye", siren: mdiBullhorn,
simple_alarm: "hass:bell", simple_alarm: mdiBell,
sun: "hass:white-balance-sunny", sun: mdiWhiteBalanceSunny,
switch: "hass:flash", switch: mdiFlash,
timer: "hass:timer-outline", timer: mdiTimerOutline,
updater: "hass:cloud-upload", updater: mdiCloudUpload,
vacuum: "hass:robot-vacuum", vacuum: mdiRobotVacuum,
water_heater: "hass:thermometer", water_heater: mdiThermometer,
weather: "hass:weather-cloudy", weather: mdiWeatherCloudy,
zone: "hass:map-marker-radius", zone: mdiMapMarkerRadius,
}; };
export const FIXED_DEVICE_CLASS_ICONS = { export const FIXED_DEVICE_CLASS_ICONS = {
aqi: "hass:air-filter", aqi: mdiAirFilter,
// battery: "hass:battery", => not included by design since `sensorIcon()` will dynamically determine the icon // battery: mdiBattery, => not included by design since `sensorIcon()` will dynamically determine the icon
carbon_dioxide: "mdi:molecule-co2", carbon_dioxide: mdiMoleculeCo2,
carbon_monoxide: "mdi:molecule-co", carbon_monoxide: mdiMoleculeCo,
current: "hass:current-ac", current: mdiCurrentAc,
date: "hass:calendar", date: mdiCalendar,
energy: "hass:lightning-bolt", energy: mdiLightningBolt,
gas: "hass:gas-cylinder", gas: mdiGasCylinder,
humidity: "hass:water-percent", humidity: mdiWaterPercent,
illuminance: "hass:brightness-5", illuminance: mdiBrightness5,
monetary: "mdi:cash", monetary: mdiCash,
nitrogen_dioxide: "mdi:molecule", nitrogen_dioxide: mdiMolecule,
nitrogen_monoxide: "mdi:molecule", nitrogen_monoxide: mdiMolecule,
nitrous_oxide: "mdi:molecule", nitrous_oxide: mdiMolecule,
ozone: "mdi:molecule", ozone: mdiMolecule,
pm1: "mdi:molecule", pm1: mdiMolecule,
pm10: "mdi:molecule", pm10: mdiMolecule,
pm25: "mdi:molecule", pm25: mdiMolecule,
power: "hass:flash", power: mdiFlash,
power_factor: "hass:angle-acute", power_factor: mdiAngleAcute,
pressure: "hass:gauge", pressure: mdiGauge,
signal_strength: "hass:wifi", signal_strength: mdiWifi,
sulphur_dioxide: "mdi:molecule", sulphur_dioxide: mdiMolecule,
temperature: "hass:thermometer", temperature: mdiThermometer,
timestamp: "hass:clock", timestamp: mdiClock,
volatile_organic_compounds: "mdi:molecule", volatile_organic_compounds: mdiMolecule,
voltage: "hass:sine-wave", voltage: mdiSineWave,
}; };
/** Domains that have a state card. */ /** Domains that have a state card. */

View File

@ -1,24 +1,36 @@
/** Return an icon representing a alarm panel state. */ /** Return an icon representing a alarm panel state. */
import {
mdiShieldLock,
mdiShieldAirplane,
mdiShieldHome,
mdiShieldMoon,
mdiSecurity,
mdiShieldOutline,
mdiBellRing,
mdiShieldOff,
mdiShield,
} from "@mdi/js";
export const alarmPanelIcon = (state?: string) => { export const alarmPanelIcon = (state?: string) => {
switch (state) { switch (state) {
case "armed_away": case "armed_away":
return "hass:shield-lock"; return mdiShieldLock;
case "armed_vacation": case "armed_vacation":
return "hass:shield-airplane"; return mdiShieldAirplane;
case "armed_home": case "armed_home":
return "hass:shield-home"; return mdiShieldHome;
case "armed_night": case "armed_night":
return "hass:shield-moon"; return mdiShieldMoon;
case "armed_custom_bypass": case "armed_custom_bypass":
return "hass:security"; return mdiSecurity;
case "pending": case "pending":
return "hass:shield-outline"; return mdiShieldOutline;
case "triggered": case "triggered":
return "hass:bell-ring"; return mdiBellRing;
case "disarmed": case "disarmed":
return "hass:shield-off"; return mdiShieldOff;
default: default:
return "hass:shield"; return mdiShield;
} }
}; };

View File

@ -1,35 +1,92 @@
/** Return an icon representing a battery state. */ /** Return an icon representing a battery state. */
import {
mdiBattery,
mdiBattery10,
mdiBattery20,
mdiBattery30,
mdiBattery40,
mdiBattery50,
mdiBattery60,
mdiBattery70,
mdiBattery80,
mdiBattery90,
mdiBatteryAlert,
mdiBatteryAlertVariantOutline,
mdiBatteryCharging,
mdiBatteryCharging10,
mdiBatteryCharging20,
mdiBatteryCharging30,
mdiBatteryCharging40,
mdiBatteryCharging50,
mdiBatteryCharging60,
mdiBatteryCharging70,
mdiBatteryCharging80,
mdiBatteryCharging90,
mdiBatteryChargingOutline,
mdiBatteryUnknown,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
export const batteryIcon = ( const BATTERY_ICONS = {
10: mdiBattery10,
20: mdiBattery20,
30: mdiBattery30,
40: mdiBattery40,
50: mdiBattery50,
60: mdiBattery60,
70: mdiBattery70,
80: mdiBattery80,
90: mdiBattery90,
100: mdiBattery,
};
const BATTERY_CHARGING_ICONS = {
10: mdiBatteryCharging10,
20: mdiBatteryCharging20,
30: mdiBatteryCharging30,
40: mdiBatteryCharging40,
50: mdiBatteryCharging50,
60: mdiBatteryCharging60,
70: mdiBatteryCharging70,
80: mdiBatteryCharging80,
90: mdiBatteryCharging90,
100: mdiBatteryCharging,
};
export const batteryStateIcon = (
batteryState: HassEntity, batteryState: HassEntity,
batteryChargingState?: HassEntity batteryChargingState?: HassEntity
) => { ) => {
const battery = Number(batteryState.state); const battery = batteryState.state;
const battery_charging = const batteryCharging =
batteryChargingState && batteryChargingState.state === "on"; batteryChargingState && batteryChargingState.state === "on";
let icon = "hass:battery";
if (isNaN(battery)) { return batteryIcon(battery, batteryCharging);
if (batteryState.state === "off") { };
icon += "-full";
} else if (batteryState.state === "on") { export const batteryIcon = (
icon += "-alert"; batteryState: number | string,
} else { batteryCharging?: boolean
icon += "-unknown"; ) => {
} const batteryValue = Number(batteryState);
return icon; if (isNaN(batteryValue)) {
} if (batteryState === "off") {
return mdiBattery;
const batteryRound = Math.round(battery / 10) * 10; }
if (battery_charging && battery > 10) { if (batteryState === "on") {
icon += `-charging-${batteryRound}`; return mdiBatteryAlert;
} else if (battery_charging) { }
icon += "-outline"; return mdiBatteryUnknown;
} else if (battery <= 5) { }
icon += "-alert";
} else if (battery > 5 && battery < 95) { const batteryRound = Math.round(batteryValue / 10) * 10;
icon += `-${batteryRound}`; if (batteryCharging && batteryValue >= 10) {
} return BATTERY_CHARGING_ICONS[batteryRound];
return icon; }
if (batteryCharging) {
return mdiBatteryChargingOutline;
}
if (batteryValue <= 5) {
return mdiBatteryAlertVariantOutline;
}
return BATTERY_ICONS[batteryRound];
}; };

View File

@ -1,3 +1,44 @@
import {
mdiBattery,
mdiBatteryOutline,
mdiBatteryCharging,
mdiThermometer,
mdiSnowflake,
mdiServerNetworkOff,
mdiServerNetwork,
mdiDoorClosed,
mdiDoorOpen,
mdiGarage,
mdiGarageOpen,
mdiPowerPlugOff,
mdiPowerPlug,
mdiCheckCircle,
mdiAlertCircle,
mdiSmoke,
mdiFire,
mdiBrightness5,
mdiBrightness7,
mdiLock,
mdiLockOpen,
mdiWaterOff,
mdiWater,
mdiWalk,
mdiRun,
mdiHomeOutline,
mdiHome,
mdiSquare,
mdiSquareOutline,
mdiMusicNoteOff,
mdiMusicNote,
mdiPackage,
mdiPackageUp,
mdiCropPortrait,
mdiVibrate,
mdiWindowClosed,
mdiWindowOpen,
mdiRadioboxBlank,
mdiCheckboxMarkedCircle,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
/** Return an icon representing a binary sensor state. */ /** Return an icon representing a binary sensor state. */
@ -6,53 +47,53 @@ export const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {
const is_off = state === "off"; const is_off = state === "off";
switch (stateObj?.attributes.device_class) { switch (stateObj?.attributes.device_class) {
case "battery": case "battery":
return is_off ? "hass:battery" : "hass:battery-outline"; return is_off ? mdiBattery : mdiBatteryOutline;
case "battery_charging": case "battery_charging":
return is_off ? "hass:battery" : "hass:battery-charging"; return is_off ? mdiBattery : mdiBatteryCharging;
case "cold": case "cold":
return is_off ? "hass:thermometer" : "hass:snowflake"; return is_off ? mdiThermometer : mdiSnowflake;
case "connectivity": case "connectivity":
return is_off ? "hass:server-network-off" : "hass:server-network"; return is_off ? mdiServerNetworkOff : mdiServerNetwork;
case "door": case "door":
return is_off ? "hass:door-closed" : "hass:door-open"; return is_off ? mdiDoorClosed : mdiDoorOpen;
case "garage_door": case "garage_door":
return is_off ? "hass:garage" : "hass:garage-open"; return is_off ? mdiGarage : mdiGarageOpen;
case "power": case "power":
return is_off ? "hass:power-plug-off" : "hass:power-plug"; return is_off ? mdiPowerPlugOff : mdiPowerPlug;
case "gas": case "gas":
case "problem": case "problem":
case "safety": case "safety":
case "tamper": case "tamper":
return is_off ? "hass:check-circle" : "hass:alert-circle"; return is_off ? mdiCheckCircle : mdiAlertCircle;
case "smoke": case "smoke":
return is_off ? "hass:check-circle" : "hass:smoke"; return is_off ? mdiCheckCircle : mdiSmoke;
case "heat": case "heat":
return is_off ? "hass:thermometer" : "hass:fire"; return is_off ? mdiThermometer : mdiFire;
case "light": case "light":
return is_off ? "hass:brightness-5" : "hass:brightness-7"; return is_off ? mdiBrightness5 : mdiBrightness7;
case "lock": case "lock":
return is_off ? "hass:lock" : "hass:lock-open"; return is_off ? mdiLock : mdiLockOpen;
case "moisture": case "moisture":
return is_off ? "hass:water-off" : "hass:water"; return is_off ? mdiWaterOff : mdiWater;
case "motion": case "motion":
return is_off ? "hass:walk" : "hass:run"; return is_off ? mdiWalk : mdiRun;
case "occupancy": case "occupancy":
return is_off ? "hass:home-outline" : "hass:home"; return is_off ? mdiHomeOutline : mdiHome;
case "opening": case "opening":
return is_off ? "hass:square" : "hass:square-outline"; return is_off ? mdiSquare : mdiSquareOutline;
case "plug": case "plug":
return is_off ? "hass:power-plug-off" : "hass:power-plug"; return is_off ? mdiPowerPlugOff : mdiPowerPlug;
case "presence": case "presence":
return is_off ? "hass:home-outline" : "hass:home"; return is_off ? mdiHomeOutline : mdiHome;
case "sound": case "sound":
return is_off ? "hass:music-note-off" : "hass:music-note"; return is_off ? mdiMusicNoteOff : mdiMusicNote;
case "update": case "update":
return is_off ? "mdi:package" : "mdi:package-up"; return is_off ? mdiPackage : mdiPackageUp;
case "vibration": case "vibration":
return is_off ? "hass:crop-portrait" : "hass:vibrate"; return is_off ? mdiCropPortrait : mdiVibrate;
case "window": case "window":
return is_off ? "hass:window-closed" : "hass:window-open"; return is_off ? mdiWindowClosed : mdiWindowOpen;
default: default:
return is_off ? "hass:radiobox-blank" : "hass:checkbox-marked-circle"; return is_off ? mdiRadioboxBlank : mdiCheckboxMarkedCircle;
} }
}; };

View File

@ -1,4 +1,30 @@
/** Return an icon representing a cover state. */ /** Return an icon representing a cover state. */
import {
mdiArrowUpBox,
mdiArrowDownBox,
mdiGarage,
mdiGarageOpen,
mdiGateArrowRight,
mdiGate,
mdiGateOpen,
mdiDoorOpen,
mdiDoorClosed,
mdiCircle,
mdiWindowShutter,
mdiWindowShutterOpen,
mdiBlinds,
mdiBlindsOpen,
mdiWindowClosed,
mdiWindowOpen,
mdiArrowExpandHorizontal,
mdiArrowUp,
mdiArrowCollapseHorizontal,
mdiArrowDown,
mdiCircleSlice8,
mdiArrowSplitVertical,
mdiCurtains,
mdiCurtainsClosed,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
export const coverIcon = (state?: string, stateObj?: HassEntity): string => { export const coverIcon = (state?: string, stateObj?: HassEntity): string => {
@ -8,74 +34,84 @@ export const coverIcon = (state?: string, stateObj?: HassEntity): string => {
case "garage": case "garage":
switch (state) { switch (state) {
case "opening": case "opening":
return "hass:arrow-up-box"; return mdiArrowUpBox;
case "closing": case "closing":
return "hass:arrow-down-box"; return mdiArrowDownBox;
case "closed": case "closed":
return "hass:garage"; return mdiGarage;
default: default:
return "hass:garage-open"; return mdiGarageOpen;
} }
case "gate": case "gate":
switch (state) { switch (state) {
case "opening": case "opening":
case "closing": case "closing":
return "hass:gate-arrow-right"; return mdiGateArrowRight;
case "closed": case "closed":
return "hass:gate"; return mdiGate;
default: default:
return "hass:gate-open"; return mdiGateOpen;
} }
case "door": case "door":
return open ? "hass:door-open" : "hass:door-closed"; return open ? mdiDoorOpen : mdiDoorClosed;
case "damper": case "damper":
return open ? "hass:circle" : "hass:circle-slice-8"; return open ? mdiCircle : mdiCircleSlice8;
case "shutter": case "shutter":
switch (state) { switch (state) {
case "opening": case "opening":
return "hass:arrow-up-box"; return mdiArrowUpBox;
case "closing": case "closing":
return "hass:arrow-down-box"; return mdiArrowDownBox;
case "closed": case "closed":
return "hass:window-shutter"; return mdiWindowShutter;
default: default:
return "hass:window-shutter-open"; return mdiWindowShutterOpen;
}
case "curtain":
switch (state) {
case "opening":
return mdiArrowSplitVertical;
case "closing":
return mdiArrowCollapseHorizontal;
case "closed":
return mdiCurtainsClosed;
default:
return mdiCurtains;
} }
case "blind": case "blind":
case "curtain":
case "shade": case "shade":
switch (state) { switch (state) {
case "opening": case "opening":
return "hass:arrow-up-box"; return mdiArrowUpBox;
case "closing": case "closing":
return "hass:arrow-down-box"; return mdiArrowDownBox;
case "closed": case "closed":
return "hass:blinds"; return mdiBlinds;
default: default:
return "hass:blinds-open"; return mdiBlindsOpen;
} }
case "window": case "window":
switch (state) { switch (state) {
case "opening": case "opening":
return "hass:arrow-up-box"; return mdiArrowUpBox;
case "closing": case "closing":
return "hass:arrow-down-box"; return mdiArrowDownBox;
case "closed": case "closed":
return "hass:window-closed"; return mdiWindowClosed;
default: default:
return "hass:window-open"; return mdiWindowOpen;
} }
} }
switch (state) { switch (state) {
case "opening": case "opening":
return "hass:arrow-up-box"; return mdiArrowUpBox;
case "closing": case "closing":
return "hass:arrow-down-box"; return mdiArrowDownBox;
case "closed": case "closed":
return "hass:window-closed"; return mdiWindowClosed;
default: default:
return "hass:window-open"; return mdiWindowOpen;
} }
}; };
@ -84,9 +120,9 @@ export const computeOpenIcon = (stateObj: HassEntity): string => {
case "awning": case "awning":
case "door": case "door":
case "gate": case "gate":
return "hass:arrow-expand-horizontal"; return mdiArrowExpandHorizontal;
default: default:
return "hass:arrow-up"; return mdiArrowUp;
} }
}; };
@ -95,8 +131,8 @@ export const computeCloseIcon = (stateObj: HassEntity): string => {
case "awning": case "awning":
case "door": case "door":
case "gate": case "gate":
return "hass:arrow-collapse-horizontal"; return mdiArrowCollapseHorizontal;
default: default:
return "hass:arrow-down"; return mdiArrowDown;
} }
}; };

View File

@ -1,3 +1,20 @@
import {
mdiAirHumidifierOff,
mdiAirHumidifier,
mdiLockOpen,
mdiLockAlert,
mdiLockClock,
mdiLock,
mdiCastConnected,
mdiCast,
mdiEmoticonDead,
mdiSleep,
mdiTimerSand,
mdiZWave,
mdiClock,
mdiCalendar,
mdiWeatherNight,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
/** /**
* Return the icon to be used for a domain. * Return the icon to be used for a domain.
@ -28,36 +45,34 @@ export const domainIcon = (
return coverIcon(compareState, stateObj); return coverIcon(compareState, stateObj);
case "humidifier": case "humidifier":
return state && state === "off" return state && state === "off" ? mdiAirHumidifierOff : mdiAirHumidifier;
? "hass:air-humidifier-off"
: "hass:air-humidifier";
case "lock": case "lock":
switch (compareState) { switch (compareState) {
case "unlocked": case "unlocked":
return "hass:lock-open"; return mdiLockOpen;
case "jammed": case "jammed":
return "hass:lock-alert"; return mdiLockAlert;
case "locking": case "locking":
case "unlocking": case "unlocking":
return "hass:lock-clock"; return mdiLockClock;
default: default:
return "hass:lock"; return mdiLock;
} }
case "media_player": case "media_player":
return compareState === "playing" ? "hass:cast-connected" : "hass:cast"; return compareState === "playing" ? mdiCastConnected : mdiCast;
case "zwave": case "zwave":
switch (compareState) { switch (compareState) {
case "dead": case "dead":
return "hass:emoticon-dead"; return mdiEmoticonDead;
case "sleeping": case "sleeping":
return "hass:sleep"; return mdiSleep;
case "initializing": case "initializing":
return "hass:timer-sand"; return mdiTimerSand;
default: default:
return "hass:z-wave"; return mdiZWave;
} }
case "sensor": { case "sensor": {
@ -71,17 +86,17 @@ export const domainIcon = (
case "input_datetime": case "input_datetime":
if (!stateObj?.attributes.has_date) { if (!stateObj?.attributes.has_date) {
return "hass:clock"; return mdiClock;
} }
if (!stateObj.attributes.has_time) { if (!stateObj.attributes.has_time) {
return "hass:calendar"; return mdiCalendar;
} }
break; break;
case "sun": case "sun":
return stateObj?.state === "above_horizon" return stateObj?.state === "above_horizon"
? FIXED_DOMAIN_ICONS[domain] ? FIXED_DOMAIN_ICONS[domain]
: "hass:weather-night"; : mdiWeatherNight;
} }
if (domain in FIXED_DOMAIN_ICONS) { if (domain in FIXED_DOMAIN_ICONS) {

View File

@ -1,8 +1,9 @@
/** Return an icon representing a sensor state. */ /** Return an icon representing a sensor state. */
import { mdiBattery, mdiThermometer } from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { FIXED_DEVICE_CLASS_ICONS, UNIT_C, UNIT_F } from "../const";
import { batteryIcon } from "./battery_icon";
import { SENSOR_DEVICE_CLASS_BATTERY } from "../../data/sensor"; import { SENSOR_DEVICE_CLASS_BATTERY } from "../../data/sensor";
import { FIXED_DEVICE_CLASS_ICONS, UNIT_C, UNIT_F } from "../const";
import { batteryStateIcon } from "./battery_icon";
export const sensorIcon = (stateObj?: HassEntity): string | undefined => { export const sensorIcon = (stateObj?: HassEntity): string | undefined => {
const dclass = stateObj?.attributes.device_class; const dclass = stateObj?.attributes.device_class;
@ -12,12 +13,12 @@ export const sensorIcon = (stateObj?: HassEntity): string | undefined => {
} }
if (dclass === SENSOR_DEVICE_CLASS_BATTERY) { if (dclass === SENSOR_DEVICE_CLASS_BATTERY) {
return stateObj ? batteryIcon(stateObj) : "hass:battery"; return stateObj ? batteryStateIcon(stateObj) : mdiBattery;
} }
const unit = stateObj?.attributes.unit_of_measurement; const unit = stateObj?.attributes.unit_of_measurement;
if (unit === UNIT_C || unit === UNIT_F) { if (unit === UNIT_C || unit === UNIT_F) {
return "hass:thermometer"; return mdiThermometer;
} }
return undefined; return undefined;

View File

@ -4,13 +4,9 @@ import { DEFAULT_DOMAIN_ICON } from "../const";
import { computeDomain } from "./compute_domain"; import { computeDomain } from "./compute_domain";
import { domainIcon } from "./domain_icon"; import { domainIcon } from "./domain_icon";
export const stateIcon = (state?: HassEntity) => { export const stateIconPath = (state?: HassEntity) => {
if (!state) { if (!state) {
return DEFAULT_DOMAIN_ICON; return DEFAULT_DOMAIN_ICON;
} }
if (state.attributes.icon) {
return state.attributes.icon;
}
return domainIcon(computeDomain(state.entity_id), state); return domainIcon(computeDomain(state.entity_id), state);
}; };

View File

@ -1,57 +1,57 @@
import { css } from "lit"; import { css } from "lit";
export const iconColorCSS = css` export const iconColorCSS = css`
ha-icon[data-domain="alert"][data-state="on"], ha-state-icon[data-domain="alert"][data-state="on"],
ha-icon[data-domain="automation"][data-state="on"], ha-state-icon[data-domain="automation"][data-state="on"],
ha-icon[data-domain="binary_sensor"][data-state="on"], ha-state-icon[data-domain="binary_sensor"][data-state="on"],
ha-icon[data-domain="calendar"][data-state="on"], ha-state-icon[data-domain="calendar"][data-state="on"],
ha-icon[data-domain="camera"][data-state="streaming"], ha-state-icon[data-domain="camera"][data-state="streaming"],
ha-icon[data-domain="cover"][data-state="open"], ha-state-icon[data-domain="cover"][data-state="open"],
ha-icon[data-domain="fan"][data-state="on"], ha-state-icon[data-domain="fan"][data-state="on"],
ha-icon[data-domain="humidifier"][data-state="on"], ha-state-icon[data-domain="humidifier"][data-state="on"],
ha-icon[data-domain="light"][data-state="on"], ha-state-icon[data-domain="light"][data-state="on"],
ha-icon[data-domain="input_boolean"][data-state="on"], ha-state-icon[data-domain="input_boolean"][data-state="on"],
ha-icon[data-domain="lock"][data-state="unlocked"], ha-state-icon[data-domain="lock"][data-state="unlocked"],
ha-icon[data-domain="media_player"][data-state="on"], ha-state-icon[data-domain="media_player"][data-state="on"],
ha-icon[data-domain="media_player"][data-state="paused"], ha-state-icon[data-domain="media_player"][data-state="paused"],
ha-icon[data-domain="media_player"][data-state="playing"], ha-state-icon[data-domain="media_player"][data-state="playing"],
ha-icon[data-domain="script"][data-state="on"], ha-state-icon[data-domain="script"][data-state="on"],
ha-icon[data-domain="sun"][data-state="above_horizon"], ha-state-icon[data-domain="sun"][data-state="above_horizon"],
ha-icon[data-domain="switch"][data-state="on"], ha-state-icon[data-domain="switch"][data-state="on"],
ha-icon[data-domain="timer"][data-state="active"], ha-state-icon[data-domain="timer"][data-state="active"],
ha-icon[data-domain="vacuum"][data-state="cleaning"], ha-state-icon[data-domain="vacuum"][data-state="cleaning"],
ha-icon[data-domain="group"][data-state="on"], ha-state-icon[data-domain="group"][data-state="on"],
ha-icon[data-domain="group"][data-state="home"], ha-state-icon[data-domain="group"][data-state="home"],
ha-icon[data-domain="group"][data-state="open"], ha-state-icon[data-domain="group"][data-state="open"],
ha-icon[data-domain="group"][data-state="locked"], ha-state-icon[data-domain="group"][data-state="locked"],
ha-icon[data-domain="group"][data-state="problem"] { ha-state-icon[data-domain="group"][data-state="problem"] {
color: var(--paper-item-icon-active-color, #fdd835); color: var(--paper-item-icon-active-color, #fdd835);
} }
ha-icon[data-domain="climate"][data-state="cooling"] { ha-state-icon[data-domain="climate"][data-state="cooling"] {
color: var(--cool-color, var(--state-climate-cool-color)); color: var(--cool-color, var(--state-climate-cool-color));
} }
ha-icon[data-domain="climate"][data-state="heating"] { ha-state-icon[data-domain="climate"][data-state="heating"] {
color: var(--heat-color, var(--state-climate-heat-color)); color: var(--heat-color, var(--state-climate-heat-color));
} }
ha-icon[data-domain="climate"][data-state="drying"] { ha-state-icon[data-domain="climate"][data-state="drying"] {
color: var(--dry-color, var(--state-climate-dry-color)); color: var(--dry-color, var(--state-climate-dry-color));
} }
ha-icon[data-domain="alarm_control_panel"] { ha-state-icon[data-domain="alarm_control_panel"] {
color: var(--alarm-color-armed, var(--label-badge-red)); color: var(--alarm-color-armed, var(--label-badge-red));
} }
ha-icon[data-domain="alarm_control_panel"][data-state="disarmed"] { ha-state-icon[data-domain="alarm_control_panel"][data-state="disarmed"] {
color: var(--alarm-color-disarmed, var(--label-badge-green)); color: var(--alarm-color-disarmed, var(--label-badge-green));
} }
ha-icon[data-domain="alarm_control_panel"][data-state="pending"], ha-state-icon[data-domain="alarm_control_panel"][data-state="pending"],
ha-icon[data-domain="alarm_control_panel"][data-state="arming"] { ha-state-icon[data-domain="alarm_control_panel"][data-state="arming"] {
color: var(--alarm-color-pending, var(--label-badge-yellow)); color: var(--alarm-color-pending, var(--label-badge-yellow));
animation: pulse 1s infinite; animation: pulse 1s infinite;
} }
ha-icon[data-domain="alarm_control_panel"][data-state="triggered"] { ha-state-icon[data-domain="alarm_control_panel"][data-state="triggered"] {
color: var(--alarm-color-triggered, var(--label-badge-red)); color: var(--alarm-color-triggered, var(--label-badge-red));
animation: pulse 1s infinite; animation: pulse 1s infinite;
} }
@ -68,13 +68,13 @@ export const iconColorCSS = css`
} }
} }
ha-icon[data-domain="plant"][data-state="problem"], ha-state-icon[data-domain="plant"][data-state="problem"],
ha-icon[data-domain="zwave"][data-state="dead"] { ha-state-icon[data-domain="zwave"][data-state="dead"] {
color: var(--state-icon-error-color); color: var(--state-icon-error-color);
} }
/* Color the icon if unavailable */ /* Color the icon if unavailable */
ha-icon[data-state="unavailable"] { ha-state-icon[data-state="unavailable"] {
color: var(--state-unavailable-color); color: var(--state-unavailable-color);
} }
`; `;

View File

@ -747,10 +747,16 @@ export class HaDataTable extends LitElement {
text-align: right; text-align: right;
} }
.mdc-data-table__cell--icon:first-child ha-icon { .mdc-data-table__cell--icon:first-child ha-icon,
.mdc-data-table__cell--icon:first-child ha-state-icon,
.mdc-data-table__cell--icon:first-child ha-svg-icon {
margin-left: 8px; margin-left: 8px;
} }
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-icon { :host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-icon,
:host([dir="rtl"])
.mdc-data-table__cell--icon:first-child
ha-state-icon,
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-svg-icon {
margin-left: auto; margin-left: auto;
margin-right: 8px; margin-right: 8px;
} }

View File

@ -1,7 +1,7 @@
import { html, LitElement } from "lit"; import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { batteryIcon } from "../../common/entity/battery_icon"; import { batteryStateIcon } from "../../common/entity/battery_icon";
import "../ha-icon"; import "../ha-svg-icon";
@customElement("ha-battery-icon") @customElement("ha-battery-icon")
export class HaBatteryIcon extends LitElement { export class HaBatteryIcon extends LitElement {
@ -11,9 +11,18 @@ export class HaBatteryIcon extends LitElement {
protected render() { protected render() {
return html` return html`
<ha-icon <ha-svg-icon
.icon=${batteryIcon(this.batteryStateObj, this.batteryChargingStateObj)} .path=${batteryStateIcon(
></ha-icon> this.batteryStateObj,
this.batteryChargingStateObj
)}
></ha-svg-icon>
`; `;
} }
} }
declare global {
interface HTMLElementTagNameMap {
"ha-battery-icon": HaBatteryIcon;
}
}

View File

@ -14,19 +14,18 @@ import secondsToDuration from "../../common/datetime/seconds_to_duration";
import { computeStateDisplay } from "../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../common/entity/compute_state_display";
import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { computeStateName } from "../../common/entity/compute_state_name"; import { computeStateName } from "../../common/entity/compute_state_name";
import { stateIcon } from "../../common/entity/state_icon";
import { formatNumber } from "../../common/number/format_number"; import { formatNumber } from "../../common/number/format_number";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity"; import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { timerTimeRemaining } from "../../data/timer"; import { timerTimeRemaining } from "../../data/timer";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import "../ha-label-badge"; import "../ha-label-badge";
import "../ha-icon"; import "../ha-state-icon";
@customElement("ha-state-label-badge") @customElement("ha-state-label-badge")
export class HaStateLabelBadge extends LitElement { export class HaStateLabelBadge extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property() public state?: HassEntity; @property({ attribute: false }) public state?: HassEntity;
@property() public name?: string; @property() public name?: string;
@ -76,15 +75,16 @@ export class HaStateLabelBadge extends LitElement {
// 4. Icon determined via entity state // 4. Icon determined via entity state
// 5. Value string as fallback // 5. Value string as fallback
const domain = computeStateDomain(entityState); const domain = computeStateDomain(entityState);
const icon = this.icon ? this.icon : this._computeIcon(domain, entityState);
const image = this.icon const showIcon = this.icon || this._computeShowIcon(domain, entityState);
const image = showIcon
? "" ? ""
: this.image : this.image
? this.image ? this.image
: entityState.attributes.entity_picture_local || : entityState.attributes.entity_picture_local ||
entityState.attributes.entity_picture; entityState.attributes.entity_picture;
const value = const value =
!image && !icon ? this._computeValue(domain, entityState) : undefined; !image && !showIcon ? this._computeValue(domain, entityState) : undefined;
return html` return html`
<ha-label-badge <ha-label-badge
@ -101,8 +101,13 @@ export class HaStateLabelBadge extends LitElement {
)} )}
.description=${this.name ?? computeStateName(entityState)} .description=${this.name ?? computeStateName(entityState)}
> >
${!image && icon ? html`<ha-icon .icon=${icon}></ha-icon>` : ""} ${!image && showIcon
${value && !icon && !image ? html`<ha-state-icon
.icon=${this.icon}
.state=${entityState}
></ha-state-icon>`
: ""}
${value && !image && !showIcon
? html`<span class=${value && value.length > 4 ? "big" : ""} ? html`<span class=${value && value.length > 4 ? "big" : ""}
>${value}</span >${value}</span
>` >`
@ -150,9 +155,9 @@ export class HaStateLabelBadge extends LitElement {
} }
} }
private _computeIcon(domain: string, entityState: HassEntity) { private _computeShowIcon(domain: string, entityState: HassEntity): boolean {
if (entityState.state === UNAVAILABLE) { if (entityState.state === UNAVAILABLE) {
return null; return false;
} }
switch (domain) { switch (domain) {
case "alarm_control_panel": case "alarm_control_panel":
@ -162,17 +167,13 @@ export class HaStateLabelBadge extends LitElement {
case "person": case "person":
case "scene": case "scene":
case "sun": case "sun":
return stateIcon(entityState); return true;
case "timer": case "timer":
return entityState.state === "active" return true;
? "hass:timer-outline"
: "hass:timer-off-outline";
case "sensor": case "sensor":
return entityState.attributes.device_class === "moon__phase" return entityState.attributes.device_class === "moon__phase";
? stateIcon(entityState)
: null;
default: default:
return null; return false;
} }
} }

View File

@ -1,3 +1,4 @@
import { mdiAlert } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { import {
css, css,
@ -12,10 +13,9 @@ import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { computeActiveState } from "../../common/entity/compute_active_state"; import { computeActiveState } from "../../common/entity/compute_active_state";
import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { stateIcon } from "../../common/entity/state_icon";
import { iconColorCSS } from "../../common/style/icon_color_css"; import { iconColorCSS } from "../../common/style/icon_color_css";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import "../ha-icon"; import "../ha-state-icon";
export class StateBadge extends LitElement { export class StateBadge extends LitElement {
public hass?: HomeAssistant; public hass?: HomeAssistant;
@ -39,7 +39,7 @@ export class StateBadge extends LitElement {
// We either need a `stateObj` or one override // We either need a `stateObj` or one override
if (!stateObj && !this.overrideIcon && !this.overrideImage) { if (!stateObj && !this.overrideIcon && !this.overrideImage) {
return html`<div class="missing"> return html`<div class="missing">
<ha-icon icon="hass:alert"></ha-icon> <ha-svg-icon .path=${mdiAlert}></ha-svg-icon>
</div>`; </div>`;
} }
@ -49,18 +49,17 @@ export class StateBadge extends LitElement {
const domain = stateObj ? computeStateDomain(stateObj) : undefined; const domain = stateObj ? computeStateDomain(stateObj) : undefined;
return html` return html`<ha-state-icon
<ha-icon style=${styleMap(this._iconStyle)}
style=${styleMap(this._iconStyle)} data-domain=${ifDefined(
data-domain=${ifDefined( this.stateColor || (domain === "light" && this.stateColor !== false)
this.stateColor || (domain === "light" && this.stateColor !== false) ? domain
? domain : undefined
: undefined )}
)} data-state=${stateObj ? computeActiveState(stateObj) : ""}
data-state=${stateObj ? computeActiveState(stateObj) : ""} .icon=${this.overrideIcon}
.icon=${this.overrideIcon || (stateObj ? stateIcon(stateObj) : "")} .state=${stateObj}
></ha-icon> ></ha-state-icon>`;
`;
} }
public willUpdate(changedProps: PropertyValues) { public willUpdate(changedProps: PropertyValues) {
@ -154,7 +153,7 @@ export class StateBadge extends LitElement {
:host([icon]:focus) { :host([icon]:focus) {
background: var(--divider-color); background: var(--divider-color);
} }
ha-icon { ha-state-icon {
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out; transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
} }
.missing { .missing {

View File

@ -14,7 +14,6 @@ import { computeCloseIcon, computeOpenIcon } from "../common/entity/cover_icon";
import { UNAVAILABLE } from "../data/entity"; import { UNAVAILABLE } from "../data/entity";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
import CoverEntity from "../util/cover-model"; import CoverEntity from "../util/cover-model";
import "./ha-icon";
import "./ha-icon-button"; import "./ha-icon-button";
@customElement("ha-cover-controls") @customElement("ha-cover-controls")
@ -49,8 +48,8 @@ class HaCoverControls extends LitElement {
)} )}
@click=${this._onOpenTap} @click=${this._onOpenTap}
.disabled=${this._computeOpenDisabled()} .disabled=${this._computeOpenDisabled()}
.path=${computeOpenIcon(this.stateObj)}
> >
<ha-icon .icon=${computeOpenIcon(this.stateObj)}></ha-icon>
</ha-icon-button> </ha-icon-button>
<ha-icon-button <ha-icon-button
class=${classMap({ class=${classMap({
@ -72,8 +71,8 @@ class HaCoverControls extends LitElement {
)} )}
@click=${this._onCloseTap} @click=${this._onCloseTap}
.disabled=${this._computeClosedDisabled()} .disabled=${this._computeClosedDisabled()}
.path=${computeCloseIcon(this.stateObj)}
> >
<ha-icon .icon=${computeCloseIcon(this.stateObj)}></ha-icon>
</ha-icon-button> </ha-icon-button>
</div> </div>
`; `;

View File

@ -1,63 +0,0 @@
import "@polymer/paper-input/paper-input";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import "./ha-icon";
@customElement("ha-icon-input")
export class HaIconInput extends LitElement {
@property() public value?: string;
@property() public label?: string;
@property() public placeholder?: string;
@property({ attribute: "error-message" }) public errorMessage?: string;
@property({ type: Boolean }) public disabled = false;
protected render(): TemplateResult {
return html`
<paper-input
.value=${this.value}
.label=${this.label}
.placeholder=${this.placeholder}
@value-changed=${this._valueChanged}
.disabled=${this.disabled}
auto-validate
.errorMessage=${this.errorMessage}
pattern="^\\S+:\\S+$"
>
${this.value || this.placeholder
? html`
<ha-icon .icon=${this.value || this.placeholder} slot="suffix">
</ha-icon>
`
: ""}
</paper-input>
`;
}
private _valueChanged(ev: CustomEvent) {
this.value = ev.detail.value;
fireEvent(
this,
"value-changed",
{ value: ev.detail.value },
{
bubbles: false,
composed: false,
}
);
}
static get styles() {
return css`
ha-icon {
position: absolute;
bottom: 2px;
right: 0;
}
`;
}
}

View File

@ -46,14 +46,14 @@ export class HaIconPicker extends LitElement {
@property() public placeholder?: string; @property() public placeholder?: string;
@property() public fallbackPath?: string;
@property({ attribute: "error-message" }) public errorMessage?: string; @property({ attribute: "error-message" }) public errorMessage?: string;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
@query("vaadin-combo-box-light", true) private comboBox!: HTMLElement; @query("vaadin-combo-box-light", true) private comboBox!: HTMLElement;
@property({ type: Boolean }) private _opened = false;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<vaadin-combo-box-light <vaadin-combo-box-light
@ -63,7 +63,6 @@ export class HaIconPicker extends LitElement {
.allowCustomValue=${true} .allowCustomValue=${true}
.filteredItems=${[]} .filteredItems=${[]}
${comboBoxRenderer(rowRenderer)} ${comboBoxRenderer(rowRenderer)}
@opened-changed=${this._openedChanged}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@filter-changed=${this._filterChanged} @filter-changed=${this._filterChanged}
> >
@ -77,21 +76,22 @@ export class HaIconPicker extends LitElement {
autocorrect="off" autocorrect="off"
spellcheck="false" spellcheck="false"
> >
${!this._opened && (this._value || this.placeholder) ${this._value || this.placeholder
? html` ? html`
<ha-icon .icon=${this._value || this.placeholder} slot="suffix"> <ha-icon .icon=${this._value || this.placeholder} slot="suffix">
</ha-icon> </ha-icon>
` `
: this.fallbackPath
? html`<ha-svg-icon
.path=${this.fallbackPath}
slot="suffix"
></ha-svg-icon>`
: ""} : ""}
</paper-input> </paper-input>
</vaadin-combo-box-light> </vaadin-combo-box-light>
`; `;
} }
private _openedChanged(ev: PolymerChangedEvent<boolean>) {
this._opened = ev.detail.value;
}
private _valueChanged(ev: PolymerChangedEvent<string>) { private _valueChanged(ev: PolymerChangedEvent<string>) {
this._setValue(ev.detail.value); this._setValue(ev.detail.value);
} }
@ -132,10 +132,10 @@ export class HaIconPicker extends LitElement {
static get styles() { static get styles() {
return css` return css`
ha-icon { ha-icon,
position: absolute; ha-svg-icon {
position: relative;
bottom: 2px; bottom: 2px;
right: 0;
} }
`; `;
} }

View File

@ -1,26 +1,27 @@
import { mdiStar } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-tooltip/paper-tooltip";
import { import {
css, css,
CSSResultGroup, CSSResultGroup,
html, html,
nothing,
LitElement, LitElement,
nothing,
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, state, property } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import { import {
Adapter, Adapter,
NetworkConfig,
IPv6ConfiguredAddress,
IPv4ConfiguredAddress, IPv4ConfiguredAddress,
IPv6ConfiguredAddress,
NetworkConfig,
} from "../data/network"; } from "../data/network";
import { fireEvent } from "../common/dom/fire_event";
import { haStyle } from "../resources/styles"; import { haStyle } from "../resources/styles";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import "./ha-checkbox"; import "./ha-checkbox";
import type { HaCheckbox } from "./ha-checkbox"; import type { HaCheckbox } from "./ha-checkbox";
import "./ha-settings-row"; import "./ha-settings-row";
import "./ha-icon"; import "./ha-svg-icon";
const format_addresses = ( const format_addresses = (
addresses: IPv6ConfiguredAddress[] | IPv4ConfiguredAddress[] addresses: IPv6ConfiguredAddress[] | IPv4ConfiguredAddress[]
@ -92,7 +93,8 @@ export class HaNetwork extends LitElement {
<span slot="heading"> <span slot="heading">
Adapter: ${adapter.name} Adapter: ${adapter.name}
${adapter.default ${adapter.default
? html`<ha-icon .icon="hass:star"></ha-icon> (Default)` ? html`<ha-svg-icon .path=${mdiStar}></ha-svg-icon>
(Default)`
: ""} : ""}
</span> </span>
<span slot="description"> <span slot="description">

View File

@ -0,0 +1,27 @@
import { HassEntity } from "home-assistant-js-websocket";
import { html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { stateIconPath } from "../common/entity/state_icon_path";
import "./ha-icon";
import "./ha-svg-icon";
@customElement("ha-state-icon")
export class HaStateIcon extends LitElement {
@property({ attribute: false }) public state?: HassEntity;
@property() public icon?: string;
protected render(): TemplateResult {
if (this.icon || this.state?.attributes.icon) {
return html`<ha-icon
.icon=${this.icon || this.state?.attributes.icon}
></ha-icon>`;
}
return html`<ha-svg-icon .path=${stateIconPath(this.state)}></ha-svg-icon>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-state-icon": HaStateIcon;
}
}

View File

@ -10,6 +10,7 @@ import {
} from "@mdi/js"; } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-tooltip/paper-tooltip";
import { import {
HassEntity,
HassServiceTarget, HassServiceTarget,
UnsubscribeFunc, UnsubscribeFunc,
} from "home-assistant-js-websocket"; } from "home-assistant-js-websocket";
@ -20,7 +21,6 @@ import { fireEvent } from "../common/dom/fire_event";
import { ensureArray } from "../common/ensure-array"; import { ensureArray } from "../common/ensure-array";
import { computeDomain } from "../common/entity/compute_domain"; import { computeDomain } from "../common/entity/compute_domain";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import { stateIcon } from "../common/entity/state_icon";
import { import {
AreaRegistryEntry, AreaRegistryEntry,
subscribeAreaRegistry, subscribeAreaRegistry,
@ -41,15 +41,14 @@ import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
import "./entity/ha-entity-picker"; import "./entity/ha-entity-picker";
import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker"; import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker";
import "./ha-area-picker"; import "./ha-area-picker";
import "./ha-icon";
import "./ha-icon-button"; import "./ha-icon-button";
import "./ha-svg-icon"; import "./ha-svg-icon";
@customElement("ha-target-picker") @customElement("ha-target-picker")
export class HaTargetPicker extends SubscribeMixin(LitElement) { export class HaTargetPicker extends SubscribeMixin(LitElement) {
@property() public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public value?: HassServiceTarget; @property({ attribute: false }) public value?: HassServiceTarget;
@property() public label?: string; @property() public label?: string;
@ -147,7 +146,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
"entity_id", "entity_id",
entity_id, entity_id,
entity ? computeStateName(entity) : entity_id, entity ? computeStateName(entity) : entity_id,
entity ? stateIcon(entity) : undefined entity
); );
}) })
: ""} : ""}
@ -230,7 +229,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
type: string, type: string,
id: string, id: string,
name: string, name: string,
icon?: string, entityState?: HassEntity,
iconPath?: string iconPath?: string
) { ) {
return html` return html`
@ -245,11 +244,11 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
.path=${iconPath} .path=${iconPath}
></ha-svg-icon>` ></ha-svg-icon>`
: ""} : ""}
${icon ${entityState
? html`<ha-icon ? html`<ha-state-icon
class="mdc-chip__icon mdc-chip__icon--leading" class="mdc-chip__icon mdc-chip__icon--leading"
.icon=${icon} .state=${entityState}
></ha-icon>` ></ha-state-icon>`
: ""} : ""}
<span role="gridcell"> <span role="gridcell">
<span role="button" tabindex="0" class="mdc-chip__primary-action"> <span role="button" tabindex="0" class="mdc-chip__primary-action">

View File

@ -10,8 +10,15 @@ import {
mdiImage, mdiImage,
mdiMovie, mdiMovie,
mdiMusic, mdiMusic,
mdiPause,
mdiPlay,
mdiPlaylistMusic, mdiPlaylistMusic,
mdiPlayPause,
mdiPodcast, mdiPodcast,
mdiPower,
mdiSkipNext,
mdiSkipPrevious,
mdiStop,
mdiTelevisionClassic, mdiTelevisionClassic,
mdiVideo, mdiVideo,
mdiWeb, mdiWeb,
@ -246,7 +253,7 @@ export const computeMediaControls = (
return supportsFeature(stateObj, SUPPORT_TURN_ON) return supportsFeature(stateObj, SUPPORT_TURN_ON)
? [ ? [
{ {
icon: "hass:power", icon: mdiPower,
action: "turn_on", action: "turn_on",
}, },
] ]
@ -257,7 +264,7 @@ export const computeMediaControls = (
if (supportsFeature(stateObj, SUPPORT_TURN_OFF)) { if (supportsFeature(stateObj, SUPPORT_TURN_OFF)) {
buttons.push({ buttons.push({
icon: "hass:power", icon: mdiPower,
action: "turn_off", action: "turn_off",
}); });
} }
@ -267,7 +274,7 @@ export const computeMediaControls = (
supportsFeature(stateObj, SUPPORT_PREVIOUS_TRACK) supportsFeature(stateObj, SUPPORT_PREVIOUS_TRACK)
) { ) {
buttons.push({ buttons.push({
icon: "hass:skip-previous", icon: mdiSkipPrevious,
action: "media_previous_track", action: "media_previous_track",
}); });
} }
@ -285,12 +292,12 @@ export const computeMediaControls = (
buttons.push({ buttons.push({
icon: icon:
state === "on" state === "on"
? "hass:play-pause" ? mdiPlayPause
: state !== "playing" : state !== "playing"
? "hass:play" ? mdiPlay
: supportsFeature(stateObj, SUPPORT_PAUSE) : supportsFeature(stateObj, SUPPORT_PAUSE)
? "hass:pause" ? mdiPause
: "hass:stop", : mdiStop,
action: action:
state !== "playing" state !== "playing"
? "media_play" ? "media_play"
@ -305,7 +312,7 @@ export const computeMediaControls = (
supportsFeature(stateObj, SUPPORT_NEXT_TRACK) supportsFeature(stateObj, SUPPORT_NEXT_TRACK)
) { ) {
buttons.push({ buttons.push({
icon: "hass:skip-next", icon: mdiSkipNext,
action: "media_next_track", action: "media_next_track",
}); });
} }

View File

@ -1,4 +1,5 @@
import { import {
mdiAlertCircleOutline,
mdiGauge, mdiGauge,
mdiWaterPercent, mdiWaterPercent,
mdiWeatherFog, mdiWeatherFog,
@ -12,7 +13,6 @@ import {
import { css, html, svg, SVGTemplateResult, TemplateResult } from "lit"; import { css, html, svg, SVGTemplateResult, TemplateResult } from "lit";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { formatNumber } from "../common/number/format_number"; import { formatNumber } from "../common/number/format_number";
import "../components/ha-icon";
import "../components/ha-svg-icon"; import "../components/ha-svg-icon";
import type { HomeAssistant } from "../types"; import type { HomeAssistant } from "../types";
@ -57,7 +57,7 @@ export const weatherSVGs = new Set<string>([
]); ]);
export const weatherIcons = { export const weatherIcons = {
exceptional: "hass:alert-circle-outline", exceptional: mdiAlertCircleOutline,
}; };
export const weatherAttrIcons = { export const weatherAttrIcons = {
@ -433,7 +433,10 @@ export const getWeatherStateIcon = (
if (state in weatherIcons) { if (state in weatherIcons) {
return html` return html`
<ha-icon class="weather-icon" .icon=${weatherIcons[state]}></ha-icon> <ha-svg-icon
class="weather-icon"
.path=${weatherIcons[state]}
></ha-svg-icon>
`; `;
} }

View File

@ -1,5 +1,7 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import { import {
mdiLoginVariant,
mdiMusicNote,
mdiPlayBoxMultiple, mdiPlayBoxMultiple,
mdiSend, mdiSend,
mdiVolumeHigh, mdiVolumeHigh,
@ -15,8 +17,8 @@ import { customElement, property, query } from "lit/decorators";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { supportsFeature } from "../../../common/entity/supports-feature"; import { supportsFeature } from "../../../common/entity/supports-feature";
import { computeRTLDirection } from "../../../common/util/compute_rtl"; import { computeRTLDirection } from "../../../common/util/compute_rtl";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-svg-icon";
import "../../../components/ha-paper-dropdown-menu"; import "../../../components/ha-paper-dropdown-menu";
import "../../../components/ha-slider"; import "../../../components/ha-slider";
import { showMediaBrowserDialog } from "../../../components/media-player/show-media-browser-dialog"; import { showMediaBrowserDialog } from "../../../components/media-player/show-media-browser-dialog";
@ -62,8 +64,8 @@ class MoreInfoMediaPlayer extends LitElement {
<ha-icon-button <ha-icon-button
action=${control.action} action=${control.action}
@click=${this._handleClick} @click=${this._handleClick}
.path=${control.icon}
> >
<ha-icon .icon=${control.icon}></ha-icon>
</ha-icon-button> </ha-icon-button>
` `
)} )}
@ -130,7 +132,10 @@ class MoreInfoMediaPlayer extends LitElement {
stateObj.attributes.source_list?.length stateObj.attributes.source_list?.length
? html` ? html`
<div class="source-input"> <div class="source-input">
<ha-icon class="source-input" icon="hass:login-variant"></ha-icon> <ha-svg-icon
class="source-input"
.path=${mdiLoginVariant}
></ha-svg-icon>
<ha-paper-dropdown-menu <ha-paper-dropdown-menu
.label=${this.hass.localize("ui.card.media_player.source")} .label=${this.hass.localize("ui.card.media_player.source")}
> >
@ -155,7 +160,7 @@ class MoreInfoMediaPlayer extends LitElement {
stateObj.attributes.sound_mode_list?.length stateObj.attributes.sound_mode_list?.length
? html` ? html`
<div class="sound-input"> <div class="sound-input">
<ha-icon icon="hass:music-note"></ha-icon> <ha-svg-icon .path=${mdiMusicNote}></ha-svg-icon>
<ha-paper-dropdown-menu <ha-paper-dropdown-menu
dynamic-align dynamic-align
label-float label-float
@ -228,8 +233,8 @@ class MoreInfoMediaPlayer extends LitElement {
justify-content: space-between; justify-content: space-between;
} }
.source-input ha-icon, .source-input ha-svg-icon,
.sound-input ha-icon { .sound-input ha-svg-icon {
padding: 7px; padding: 7px;
margin-top: 24px; margin-top: 24px;
} }

View File

@ -1,4 +1,5 @@
import { import {
mdiFan,
mdiHomeMapMarker, mdiHomeMapMarker,
mdiMapMarker, mdiMapMarker,
mdiPause, mdiPause,
@ -195,7 +196,7 @@ class MoreInfoVacuum extends LitElement {
style="justify-content: center; align-self: center; padding-top: 1.3em" style="justify-content: center; align-self: center; padding-top: 1.3em"
> >
<span> <span>
<ha-icon icon="hass:fan"></ha-icon> <ha-svg-icon .path=${mdiFan}></ha-svg-icon>
${stateObj.attributes.fan_speed} ${stateObj.attributes.fan_speed}
</span> </span>
</div> </div>

View File

@ -386,10 +386,14 @@ export class QuickBar extends LitElement {
private _generateEntityItems(): EntityItem[] { private _generateEntityItems(): EntityItem[] {
return Object.keys(this.hass.states) return Object.keys(this.hass.states)
.map((entityId) => { .map((entityId) => {
const entityState = this.hass.states[entityId];
const entityItem = { const entityItem = {
primaryText: computeStateName(this.hass.states[entityId]), primaryText: computeStateName(entityState),
altText: entityId, altText: entityId,
icon: domainIcon(computeDomain(entityId), this.hass.states[entityId]), icon: entityState.attributes.icon,
iconPath: entityState.attributes.icon
? undefined
: domainIcon(computeDomain(entityId), entityState),
action: () => fireEvent(this, "hass-more-info", { entityId }), action: () => fireEvent(this, "hass-more-info", { entityId }),
}; };

View File

@ -1,6 +1,6 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import "../components/ha-icon"; import "../components/ha-svg-icon";
@customElement("action-badge") @customElement("action-badge")
class ActionBadge extends LitElement { class ActionBadge extends LitElement {
@ -15,9 +15,12 @@ class ActionBadge extends LitElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<div class="icon"> <div class="icon">
<ha-icon .icon=${this.icon}></ha-icon> <ha-svg-icon .path=${this.icon}></ha-svg-icon>
${this.badgeIcon ${this.badgeIcon
? html` <ha-icon class="badge" .icon=${this.badgeIcon}></ha-icon> ` ? html`<ha-svg-icon
class="badge"
.path=${this.badgeIcon}
></ha-svg-icon>`
: ""} : ""}
</div> </div>
<div class="title">${this.title}</div> <div class="title">${this.title}</div>

View File

@ -1,6 +1,6 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import "../components/ha-icon"; import "../components/ha-svg-icon";
import { brandsUrl } from "../util/brands-url"; import { brandsUrl } from "../util/brands-url";
@customElement("integration-badge") @customElement("integration-badge")
@ -27,7 +27,10 @@ class IntegrationBadge extends LitElement {
referrerpolicy="no-referrer" referrerpolicy="no-referrer"
/> />
${this.badgeIcon ${this.badgeIcon
? html` <ha-icon class="badge" .icon=${this.badgeIcon}></ha-icon> ` ? html`<ha-svg-icon
class="badge"
.path=${this.badgeIcon}
></ha-svg-icon>`
: ""} : ""}
</div> </div>
<div class="title">${this.title}</div> <div class="title">${this.title}</div>

View File

@ -8,6 +8,7 @@ import {
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { mdiCheck, mdiDotsHorizontal } from "@mdi/js";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { stringCompare } from "../common/string/compare"; import { stringCompare } from "../common/string/compare";
import { isComponentLoaded } from "../common/config/is_component_loaded"; import { isComponentLoaded } from "../common/config/is_component_loaded";
@ -79,7 +80,7 @@ class OnboardingIntegrations extends LitElement {
<integration-badge <integration-badge
.domain=${entry.domain} .domain=${entry.domain}
.title=${title} .title=${title}
badgeIcon="hass:check" .badgeIcon=${mdiCheck}
.darkOptimizedIcon=${this.hass.selectedTheme?.dark} .darkOptimizedIcon=${this.hass.selectedTheme?.dark}
></integration-badge> ></integration-badge>
`, `,
@ -120,7 +121,7 @@ class OnboardingIntegrations extends LitElement {
title=${this.onboardingLocalize( title=${this.onboardingLocalize(
"ui.panel.page-onboarding.integration.more_integrations" "ui.panel.page-onboarding.integration.more_integrations"
)} )}
icon="hass:dots-horizontal" .icon=${mdiDotsHorizontal}
></action-badge> ></action-badge>
</button> </button>
</div> </div>

View File

@ -3,7 +3,6 @@ import "@polymer/app-layout/app-toolbar/app-toolbar";
import { html } from "@polymer/polymer/lib/utils/html-tag"; import { html } from "@polymer/polymer/lib/utils/html-tag";
/* eslint-plugin-disable lit */ /* eslint-plugin-disable lit */
import { PolymerElement } from "@polymer/polymer/polymer-element"; import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../components/ha-icon-button";
import "../../../layouts/hass-tabs-subpage"; import "../../../layouts/hass-tabs-subpage";
import LocalizeMixin from "../../../mixins/localize-mixin"; import LocalizeMixin from "../../../mixins/localize-mixin";
import "../../../styles/polymer-ha-style"; import "../../../styles/polymer-ha-style";

View File

@ -132,10 +132,10 @@ export class HaDeviceEntitiesCard extends LitElement {
private _renderEntry(entry: EntityRegistryStateEntry): TemplateResult { private _renderEntry(entry: EntityRegistryStateEntry): TemplateResult {
return html` return html`
<paper-icon-item .entry=${entry} @click=${this._openEditEntry}> <paper-icon-item .entry=${entry} @click=${this._openEditEntry}>
<ha-icon <ha-svg-icon
slot="item-icon" slot="item-icon"
.icon=${domainIcon(computeDomain(entry.entity_id))} .path=${domainIcon(computeDomain(entry.entity_id))}
></ha-icon> ></ha-svg-icon>
<paper-item-body> <paper-item-body>
<div class="name">${entry.stateName || entry.entity_id}</div> <div class="name">${entry.stateName || entry.entity_id}</div>
</paper-item-body> </paper-item-body>

View File

@ -4,9 +4,9 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { computeStateName } from "../../../../common/entity/compute_state_name"; import { computeStateName } from "../../../../common/entity/compute_state_name";
import { stateIcon } from "../../../../common/entity/state_icon";
import "../../../../components/ha-card"; import "../../../../components/ha-card";
import "../../../../components/ha-icon-button"; import "../../../../components/ha-icon-button";
import "../../../../components/ha-state-icon";
import { import {
DeviceConsumptionEnergyPreference, DeviceConsumptionEnergyPreference,
EnergyPreferences, EnergyPreferences,
@ -79,7 +79,7 @@ export class EnergyDeviceSettings extends LitElement {
const entityState = this.hass.states[device.stat_consumption]; const entityState = this.hass.states[device.stat_consumption];
return html` return html`
<div class="row"> <div class="row">
<ha-icon .icon=${stateIcon(entityState)}></ha-icon> <ha-state-icon .state=${entityState}></ha-state-icon>
<span class="content" <span class="content"
>${entityState >${entityState
? computeStateName(entityState) ? computeStateName(entityState)

View File

@ -137,11 +137,10 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
.value=${this._icon} .value=${this._icon}
@value-changed=${this._iconChanged} @value-changed=${this._iconChanged}
.label=${this.hass.localize("ui.dialogs.entity_registry.editor.icon")} .label=${this.hass.localize("ui.dialogs.entity_registry.editor.icon")}
.placeholder=${this.entry.original_icon || .placeholder=${this.entry.original_icon || stateObj?.attributes.icon}
domainIcon( .fallbackPath=${!this._icon && !stateObj?.attributes.icon && stateObj
computeDomain(this.entry.entity_id), ? domainIcon(computeDomain(stateObj.entity_id), stateObj)
this.hass.states[this.entry.entity_id] : undefined}
)}
.disabled=${this._submitting} .disabled=${this._submitting}
></ha-icon-picker> ></ha-icon-picker>
<paper-input <paper-input

View File

@ -1,17 +1,20 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
import { import {
mdiAlertCircle,
mdiCancel, mdiCancel,
mdiDelete, mdiDelete,
mdiFilterVariant, mdiFilterVariant,
mdiPencilOff,
mdiPlus, mdiPlus,
mdiRestoreAlert,
mdiUndo, mdiUndo,
} from "@mdi/js"; } from "@mdi/js";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-listbox/paper-listbox";
import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-tooltip/paper-tooltip";
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
@ -20,8 +23,6 @@ import memoize from "memoize-one";
import type { HASSDomEvent } from "../../../common/dom/fire_event"; import type { HASSDomEvent } from "../../../common/dom/fire_event";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { domainIcon } from "../../../common/entity/domain_icon";
import { stateIcon } from "../../../common/entity/state_icon";
import { navigate } from "../../../common/navigate"; import { navigate } from "../../../common/navigate";
import "../../../common/search/search-input"; import "../../../common/search/search-input";
import { LocalizeFunc } from "../../../common/translations/localize"; import { LocalizeFunc } from "../../../common/translations/localize";
@ -75,7 +76,7 @@ export interface StateEntity extends EntityRegistryEntry {
} }
export interface EntityRow extends StateEntity { export interface EntityRow extends StateEntity {
icon: string; entity: HassEntity;
unavailable: boolean; unavailable: boolean;
restored: boolean; restored: boolean;
status: string; status: string;
@ -168,8 +169,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
icon: { icon: {
title: "", title: "",
type: "icon", type: "icon",
template: (icon) => html` template: (_, entry: any) => html`
<ha-icon slot="item-icon" .icon=${icon}></ha-icon> <ha-state-icon
slot="item-icon"
.state=${entry.entity}
></ha-state-icon>
`, `,
}, },
name: { name: {
@ -249,18 +253,18 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
tabindex="0" tabindex="0"
style="display:inline-block; position: relative;" style="display:inline-block; position: relative;"
> >
<ha-icon <ha-svg-icon
style=${styleMap({ style=${styleMap({
color: entity.unavailable ? "var(--error-color)" : "", color: entity.unavailable ? "var(--error-color)" : "",
})} })}
.icon=${entity.restored .path=${entity.restored
? "hass:restore-alert" ? mdiRestoreAlert
: entity.unavailable : entity.unavailable
? "hass:alert-circle" ? mdiAlertCircle
: entity.disabled_by : entity.disabled_by
? "hass:cancel" ? mdiCancel
: "hass:pencil-off"} : mdiPencilOff}
></ha-icon> ></ha-svg-icon>
<paper-tooltip animation-delay="0" position="left"> <paper-tooltip animation-delay="0" position="left">
${entity.restored ${entity.restored
? this.hass.localize( ? this.hass.localize(
@ -371,9 +375,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
result.push({ result.push({
...entry, ...entry,
icon: entity entity,
? stateIcon(entity)
: domainIcon(computeDomain(entry.entity_id)),
name: name:
computeEntityRegistryName(this.hass!, entry) || computeEntityRegistryName(this.hass!, entry) ||
this.hass.localize("state.default.unavailable"), this.hass.localize("state.default.unavailable"),

View File

@ -121,10 +121,10 @@ export class DialogHelperDetail extends LitElement {
.platform=${platform} .platform=${platform}
dialogInitialFocus dialogInitialFocus
> >
<ha-icon <ha-svg-icon
slot="item-icon" slot="item-icon"
.icon=${domainIcon(platform)} .path=${domainIcon(platform)}
></ha-icon> ></ha-svg-icon>
<span class="item-text"> <span class="item-text">
${this.hass.localize( ${this.hass.localize(
`ui.panel.config.helpers.types.${platform}` `ui.panel.config.helpers.types.${platform}`

View File

@ -1,4 +1,4 @@
import { mdiPlus } from "@mdi/js"; import { mdiPencilOff, mdiPlus } from "@mdi/js";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-listbox/paper-listbox";
@ -42,9 +42,12 @@ export class HaConfigHelpers extends LitElement {
icon: { icon: {
title: "", title: "",
type: "icon", type: "icon",
template: (icon, helper: any) => html` template: (icon, helper: any) =>
<ha-icon .icon=${icon || domainIcon(helper.type)}></ha-icon> icon
`, ? html` <ha-icon .icon=${icon}></ha-icon> `
: html`<ha-svg-icon
.path=${domainIcon(helper.type)}
></ha-svg-icon>`,
}, },
name: { name: {
title: this.hass.localize( title: this.hass.localize(
@ -93,7 +96,7 @@ export class HaConfigHelpers extends LitElement {
tabindex="0" tabindex="0"
style="display:inline-block; position: relative;" style="display:inline-block; position: relative;"
> >
<ha-icon icon="hass:pencil-off"></ha-icon> <ha-svg-icon .path=${mdiPencilOff}></ha-svg-icon>
<paper-tooltip animation-delay="0" position="left"> <paper-tooltip animation-delay="0" position="left">
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.entities.picker.status.readonly" "ui.panel.config.entities.picker.status.readonly"

View File

@ -691,9 +691,6 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) {
margin-left: 4px; margin-left: 4px;
font-size: 14px; font-size: 14px;
} }
.active-filters ha-icon {
color: var(--primary-color);
}
.active-filters mwc-button { .active-filters mwc-button {
margin-left: 8px; margin-left: 8px;
} }

View File

@ -6,7 +6,6 @@ import { classMap } from "lit/directives/class-map";
import { navigate } from "../../../../../common/navigate"; import { navigate } from "../../../../../common/navigate";
import "../../../../../components/buttons/ha-call-service-button"; import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-icon-next";
import { import {
fetchOZWNetworkStatistics, fetchOZWNetworkStatistics,
fetchOZWNetworkStatus, fetchOZWNetworkStatus,

View File

@ -11,7 +11,6 @@ import {
RowClickedEvent, RowClickedEvent,
} from "../../../../../components/data-table/ha-data-table"; } from "../../../../../components/data-table/ha-data-table";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-icon-next";
import { fetchOZWNodes, OZWDevice } from "../../../../../data/ozw"; import { fetchOZWNodes, OZWDevice } from "../../../../../data/ozw";
import "../../../../../layouts/hass-tabs-subpage"; import "../../../../../layouts/hass-tabs-subpage";
import "../../../../../layouts/hass-tabs-subpage-data-table"; import "../../../../../layouts/hass-tabs-subpage-data-table";

View File

@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators";
import { navigate } from "../../../../../common/navigate"; import { navigate } from "../../../../../common/navigate";
import "../../../../../components/buttons/ha-call-service-button"; import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-icon-next";
import { import {
fetchOZWNodeConfig, fetchOZWNodeConfig,
fetchOZWNodeMetadata, fetchOZWNodeMetadata,

View File

@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators";
import { navigate } from "../../../../../common/navigate"; import { navigate } from "../../../../../common/navigate";
import "../../../../../components/buttons/ha-call-service-button"; import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-icon-next";
import { import {
fetchOZWNodeMetadata, fetchOZWNodeMetadata,
fetchOZWNodeStatus, fetchOZWNodeStatus,

View File

@ -10,7 +10,6 @@ import {
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import "../../../../../components/ha-circular-progress"; import "../../../../../components/ha-circular-progress";
import "../../../../../components/ha-icon-button";
import "../../../../../components/ha-service-description"; import "../../../../../components/ha-service-description";
import { import {
DEVICE_MESSAGE_TYPES, DEVICE_MESSAGE_TYPES,

View File

@ -1,4 +1,4 @@
import { mdiHelpCircle } from "@mdi/js"; import { mdiCheckboxMarkedCircle, mdiClose, mdiHelpCircle } from "@mdi/js";
import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
@ -6,7 +6,7 @@ import "../../../../../components/buttons/ha-call-api-button";
import "../../../../../components/buttons/ha-call-service-button"; import "../../../../../components/buttons/ha-call-service-button";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-circular-progress"; import "../../../../../components/ha-circular-progress";
import "../../../../../components/ha-icon"; import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-icon-button"; import "../../../../../components/ha-icon-button";
import "../../../../../components/ha-service-description"; import "../../../../../components/ha-service-description";
import { import {
@ -81,7 +81,7 @@ export class ZwaveNetwork extends LitElement {
<div class="details"> <div class="details">
${this._networkStatus.state === ZWAVE_NETWORK_STATE_STOPPED ${this._networkStatus.state === ZWAVE_NETWORK_STATE_STOPPED
? html` ? html`
<ha-icon icon="hass:close"></ha-icon> <ha-svg-icon .path=${mdiClose}></ha-svg-icon>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_stopped" "ui.panel.config.zwave.network_status.network_stopped"
)} )}
@ -100,7 +100,9 @@ export class ZwaveNetwork extends LitElement {
` `
: this._networkStatus.state === ZWAVE_NETWORK_STATE_AWAKED : this._networkStatus.state === ZWAVE_NETWORK_STATE_AWAKED
? html` ? html`
<ha-icon icon="hass:checkbox-marked-circle"> </ha-icon> <ha-svg-icon
.path=${mdiCheckboxMarkedCircle}
></ha-svg-icon>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.config.zwave.network_status.network_started" "ui.panel.config.zwave.network_status.network_started"
)}<br /> )}<br />
@ -252,7 +254,7 @@ export class ZwaveNetwork extends LitElement {
padding: 24px; padding: 24px;
} }
.network-status ha-icon { .network-status ha-svg-icon {
display: block; display: block;
margin: 0px auto 16px; margin: 0px auto 16px;
width: 48px; width: 48px;

View File

@ -1,4 +1,9 @@
import { mdiOpenInNew, mdiPlus } from "@mdi/js"; import {
mdiCheck,
mdiCheckCircleOutline,
mdiOpenInNew,
mdiPlus,
} from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-tooltip/paper-tooltip";
import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
@ -65,10 +70,10 @@ export class HaConfigLovelaceDashboards extends LitElement {
${title} ${title}
${dashboard.default ${dashboard.default
? html` ? html`
<ha-icon <ha-svg-icon
style="padding-left: 10px;" style="padding-left: 10px;"
icon="hass:check-circle-outline" .path=${mdiCheckCircleOutline}
></ha-icon> ></ha-svg-icon>
<paper-tooltip animation-delay="0"> <paper-tooltip animation-delay="0">
${this.hass.localize( ${this.hass.localize(
`ui.panel.config.lovelace.dashboards.default_dashboard` `ui.panel.config.lovelace.dashboards.default_dashboard`
@ -127,7 +132,7 @@ export class HaConfigLovelaceDashboards extends LitElement {
width: "100px", width: "100px",
template: (requireAdmin: boolean) => template: (requireAdmin: boolean) =>
requireAdmin requireAdmin
? html` <ha-icon icon="hass:check"></ha-icon> ` ? html` <ha-svg-icon .path=${mdiCheck}></ha-svg-icon> `
: html` - `, : html` - `,
}; };
columns.show_in_sidebar = { columns.show_in_sidebar = {
@ -137,7 +142,9 @@ export class HaConfigLovelaceDashboards extends LitElement {
type: "icon", type: "icon",
width: "121px", width: "121px",
template: (sidebar) => template: (sidebar) =>
sidebar ? html` <ha-icon icon="hass:check"></ha-icon> ` : html` - `, sidebar
? html` <ha-svg-icon .path=${mdiCheck}></ha-svg-icon> `
: html` - `,
}; };
} }

View File

@ -11,7 +11,6 @@ import {
RowClickedEvent, RowClickedEvent,
} from "../../../../components/data-table/ha-data-table"; } from "../../../../components/data-table/ha-data-table";
import "../../../../components/ha-fab"; import "../../../../components/ha-fab";
import "../../../../components/ha-icon";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import { import {
createResource, createResource,

View File

@ -13,12 +13,11 @@ import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table"; import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu"; import "../../../components/ha-button-related-filter-menu";
import "../../../components/ha-fab"; import "../../../components/ha-fab";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-state-icon";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import { forwardHaptic } from "../../../data/haptics"; import { forwardHaptic } from "../../../data/haptics";
import { activateScene, SceneEntity } from "../../../data/scene"; import { activateScene, SceneEntity } from "../../../data/scene";
@ -60,7 +59,6 @@ class HaSceneDashboard extends LitElement {
).map((scene) => ({ ).map((scene) => ({
...scene, ...scene,
name: computeStateName(scene), name: computeStateName(scene),
icon: stateIcon(scene),
})); }));
} }
); );
@ -85,7 +83,8 @@ class HaSceneDashboard extends LitElement {
icon: { icon: {
title: "", title: "",
type: "icon", type: "icon",
template: (icon) => html` <ha-icon .icon=${icon}></ha-icon> `, template: (_, scene) =>
html` <ha-state-icon .state=${scene}></ha-state-icon> `,
}, },
name: { name: {
title: this.hass.localize("ui.panel.config.scene.picker.headers.name"), title: this.hass.localize("ui.panel.config.scene.picker.headers.name"),

View File

@ -13,7 +13,6 @@ import memoizeOne from "memoize-one";
import { formatDateTime } from "../../../common/datetime/format_date_time"; import { formatDateTime } from "../../../common/datetime/format_date_time";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { computeRTL } from "../../../common/util/compute_rtl"; import { computeRTL } from "../../../common/util/compute_rtl";
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table"; import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
import "../../../components/ha-button-related-filter-menu"; import "../../../components/ha-button-related-filter-menu";
@ -61,7 +60,6 @@ class HaScriptPicker extends LitElement {
).map((script) => ({ ).map((script) => ({
...script, ...script,
name: computeStateName(script), name: computeStateName(script),
icon: stateIcon(script),
last_triggered: script.attributes.last_triggered || undefined, last_triggered: script.attributes.last_triggered || undefined,
})); }));
} }
@ -87,7 +85,8 @@ class HaScriptPicker extends LitElement {
icon: { icon: {
title: "", title: "",
type: "icon", type: "icon",
template: (icon) => html` <ha-icon .icon=${icon}></ha-icon> `, template: (_icon, script) =>
html` <ha-state-icon .state=${script}></ha-state-icon>`,
}, },
name: { name: {
title: this.hass.localize("ui.panel.config.script.picker.headers.name"), title: this.hass.localize("ui.panel.config.script.picker.headers.name"),

View File

@ -1,4 +1,4 @@
import { mdiPlus } from "@mdi/js"; import { mdiCheck, mdiPlus } from "@mdi/js";
import { html, LitElement, PropertyValues } from "lit"; import { html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
@ -89,7 +89,9 @@ export class HaConfigUsers extends LitElement {
filterable: true, filterable: true,
width: "80px", width: "80px",
template: (is_active) => template: (is_active) =>
is_active ? html`<ha-icon icon="hass:check"> </ha-icon>` : "", is_active
? html`<ha-svg-icon .path=${mdiCheck}> </ha-svg-icon>`
: "",
}, },
system_generated: { system_generated: {
title: this.hass.localize( title: this.hass.localize(
@ -100,7 +102,9 @@ export class HaConfigUsers extends LitElement {
filterable: true, filterable: true,
width: "160px", width: "160px",
template: (generated) => template: (generated) =>
generated ? html`<ha-icon icon="hass:check"> </ha-icon>` : "", generated
? html`<ha-svg-icon .path=${mdiCheck}> </ha-svg-icon>`
: "",
}, },
}; };

View File

@ -4,7 +4,6 @@ import "@polymer/paper-tabs/paper-tab";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { navigate } from "../../common/navigate"; import { navigate } from "../../common/navigate";
import "../../components/ha-icon-button";
import "../../components/ha-menu-button"; import "../../components/ha-menu-button";
import "../../components/ha-tabs"; import "../../components/ha-tabs";
import "../../layouts/ha-app-layout"; import "../../layouts/ha-app-layout";

View File

@ -122,9 +122,6 @@ class PanelEnergy extends LitElement {
return [ return [
haStyle, haStyle,
css` css`
ha-icon-button {
color: var(--text-primary-color);
}
app-toolbar { app-toolbar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@ -155,7 +155,7 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
.label=${this._stateIconLabel(stateObj.state)} .label=${this._stateIconLabel(stateObj.state)}
@click=${this._handleMoreInfo} @click=${this._handleMoreInfo}
> >
<ha-icon .icon=${alarmPanelIcon(stateObj.state)}></ha-icon> <ha-svg-icon .path=${alarmPanelIcon(stateObj.state)}></ha-svg-icon>
</ha-label-badge> </ha-label-badge>
<div id="armActions" class="actions"> <div id="armActions" class="actions">
${(stateObj.state === "disarmed" ${(stateObj.state === "disarmed"

View File

@ -26,7 +26,6 @@ import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { iconColorCSS } from "../../../common/style/icon_color_css"; import { iconColorCSS } from "../../../common/style/icon_color_css";
import "../../../components/ha-card"; import "../../../components/ha-card";
@ -167,7 +166,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
> >
${this._config.show_icon ${this._config.show_icon
? html` ? html`
<ha-icon <ha-state-icon
tabindex="-1" tabindex="-1"
data-domain=${ifDefined( data-domain=${ifDefined(
this._config.state_color && stateObj this._config.state_color && stateObj
@ -177,8 +176,8 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
data-state=${ifDefined( data-state=${ifDefined(
stateObj ? computeActiveState(stateObj) : undefined stateObj ? computeActiveState(stateObj) : undefined
)} )}
.icon=${this._config.icon || .icon=${this._config.icon}
(stateObj ? stateIcon(stateObj) : "")} .state=${stateObj}
style=${styleMap({ style=${styleMap({
filter: stateObj ? this._computeBrightness(stateObj) : "", filter: stateObj ? this._computeBrightness(stateObj) : "",
color: stateObj ? this._computeColor(stateObj) : "", color: stateObj ? this._computeColor(stateObj) : "",
@ -186,7 +185,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
? this._config.icon_height ? this._config.icon_height
: "", : "",
})} })}
></ha-icon> ></ha-state-icon>
` `
: ""} : ""}
${this._config.show_name ${this._config.show_name
@ -270,18 +269,18 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
outline: none; outline: none;
} }
ha-icon { ha-state-icon {
width: 40%; width: 40%;
height: auto; height: auto;
color: var(--paper-item-icon-color, #44739e); color: var(--paper-item-icon-color, #44739e);
--mdc-icon-size: 100%; --mdc-icon-size: 100%;
} }
ha-icon + span { ha-state-icon + span {
margin-top: 8px; margin-top: 8px;
} }
ha-icon, ha-state-icon,
span { span {
outline: none; outline: none;
} }

View File

@ -12,7 +12,6 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
import { HASSDomEvent } from "../../../common/dom/fire_event"; import { HASSDomEvent } from "../../../common/dom/fire_event";
import { debounce } from "../../../common/util/debounce"; import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon";
import { Calendar, fetchCalendarEvents } from "../../../data/calendar"; import { Calendar, fetchCalendarEvents } from "../../../data/calendar";
import type { import type {
CalendarEvent, CalendarEvent,

View File

@ -14,7 +14,6 @@ import { computeActiveState } from "../../../common/entity/compute_active_state"
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
import { iconColorCSS } from "../../../common/style/icon_color_css"; import { iconColorCSS } from "../../../common/style/icon_color_css";
@ -122,8 +121,9 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
<div class="header"> <div class="header">
<div class="name" .title=${name}>${name}</div> <div class="name" .title=${name}>${name}</div>
<div class="icon"> <div class="icon">
<ha-icon <ha-state-icon
.icon=${this._config.icon || stateIcon(stateObj)} .icon=${this._config.icon}
.state=${stateObj}
data-domain=${ifDefined( data-domain=${ifDefined(
this._config.state_color || this._config.state_color ||
(domain === "light" && this._config.state_color !== false) (domain === "light" && this._config.state_color !== false)
@ -131,7 +131,7 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
: undefined : undefined
)} )}
data-state=${stateObj ? computeActiveState(stateObj) : ""} data-state=${stateObj ? computeActiveState(stateObj) : ""}
></ha-icon> ></ha-state-icon>
</div> </div>
</div> </div>
<div class="info"> <div class="info">

View File

@ -15,10 +15,9 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-state-icon";
import { UNAVAILABLE, UNAVAILABLE_STATES } from "../../../data/entity"; import { UNAVAILABLE, UNAVAILABLE_STATES } from "../../../data/entity";
import { LightEntity, lightSupportsDimming } from "../../../data/light"; import { LightEntity, lightSupportsDimming } from "../../../data/light";
import { ActionHandlerEvent } from "../../../data/lovelace"; import { ActionHandlerEvent } from "../../../data/lovelace";
@ -145,9 +144,10 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
})} })}
tabindex="0" tabindex="0"
> >
<ha-icon <ha-state-icon
.icon=${this._config.icon || stateIcon(stateObj)} .icon=${this._config.icon}
></ha-icon> .state=${stateObj}
></ha-state-icon>
</ha-icon-button> </ha-icon-button>
</div> </div>
</div> </div>

View File

@ -15,12 +15,11 @@ import { styleMap } from "lit/directives/style-map";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { supportsFeature } from "../../../common/entity/supports-feature"; import { supportsFeature } from "../../../common/entity/supports-feature";
import { extractColors } from "../../../common/image/extract_color"; import { extractColors } from "../../../common/image/extract_color";
import { debounce } from "../../../common/util/debounce"; import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-state-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import { showMediaBrowserDialog } from "../../../components/media-player/show-media-browser-dialog"; import { showMediaBrowserDialog } from "../../../components/media-player/show-media-browser-dialog";
import { UNAVAILABLE_STATES } from "../../../data/entity"; import { UNAVAILABLE_STATES } from "../../../data/entity";
@ -227,7 +226,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
> >
<div class="top-info"> <div class="top-info">
<div class="icon-name"> <div class="icon-name">
<ha-icon class="icon" .icon=${stateIcon(stateObj)}></ha-icon> <ha-state-icon class="icon" .state=${stateObj}></ha-state-icon>
<div> <div>
${this._config!.name || ${this._config!.name ||
computeStateName(this.hass!.states[this._config!.entity])} computeStateName(this.hass!.states[this._config!.entity])}
@ -272,10 +271,10 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
.label=${this.hass.localize( .label=${this.hass.localize(
`ui.card.media_player.${control.action}` `ui.card.media_player.${control.action}`
)} )}
.path=${control.icon}
action=${control.action} action=${control.action}
@click=${this._handleClick} @click=${this._handleClick}
> >
<ha-icon .icon=${control.icon}></ha-icon>
</ha-icon-button> </ha-icon-button>
` `
)} )}
@ -706,7 +705,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
align-items: center; align-items: center;
} }
.icon-name ha-icon { .icon-name ha-state-icon {
padding-right: 8px; padding-right: 8px;
} }

View File

@ -14,10 +14,9 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-state-icon";
import { ActionHandlerEvent } from "../../../data/lovelace"; import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive"; import { actionHandler } from "../common/directives/action-handler-directive";
@ -253,14 +252,18 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
class=${classMap({ class=${classMap({
"state-on": !STATES_OFF.has(stateObj.state), "state-on": !STATES_OFF.has(stateObj.state),
})} })}
.label=${`${computeStateName(stateObj)} : ${computeStateDisplay( title=${`${computeStateName(stateObj)} : ${computeStateDisplay(
this.hass!.localize, this.hass!.localize,
stateObj, stateObj,
this.hass!.locale this.hass!.locale
)}`} )}`}
> >
<ha-icon .icon=${entityConf.icon || stateIcon(stateObj)}></ha-icon> <ha-state-icon
.icon=${entityConf.icon}
.state=${stateObj}
></ha-state-icon>
</ha-icon-button> </ha-icon-button>
${this._config!.show_state !== true && entityConf.show_state !== true ${this._config!.show_state !== true && entityConf.show_state !== true
? html`<div class="state"></div>` ? html`<div class="state"></div>`
: html` : html`

View File

@ -1,3 +1,9 @@
import {
mdiEmoticonPoop,
mdiThermometer,
mdiWater,
mdiWhiteBalanceSunny,
} from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { import {
css, css,
@ -10,9 +16,10 @@ import {
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { batteryIcon } from "../../../common/entity/battery_icon";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-svg-icon";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive"; import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entities"; import { findEntities } from "../common/find-entities";
@ -21,12 +28,12 @@ import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceCard, LovelaceCardEditor } from "../types"; import { LovelaceCard, LovelaceCardEditor } from "../types";
import { PlantAttributeTarget, PlantStatusCardConfig } from "./types"; import { PlantAttributeTarget, PlantStatusCardConfig } from "./types";
const SENSORS = { const SENSOR_ICONS = {
moisture: "hass:water", moisture: mdiWater,
temperature: "hass:thermometer", temperature: mdiThermometer,
brightness: "hass:white-balance-sunny", brightness: mdiWhiteBalanceSunny,
conductivity: "hass:emoticon-poop", conductivity: mdiEmoticonPoop,
battery: "hass:battery", battery: undefined,
}; };
@customElement("hui-plant-status-card") @customElement("hui-plant-status-card")
@ -132,9 +139,9 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
.value=${item} .value=${item}
> >
<div> <div>
<ha-icon <ha-svg-icon
icon=${this.computeIcon(item, stateObj.attributes.battery)} .path=${this.computeIcon(item, stateObj.attributes.battery)}
></ha-icon> ></ha-svg-icon>
</div> </div>
<div <div
class=${stateObj.attributes.problem.indexOf(item) === -1 class=${stateObj.attributes.problem.indexOf(item) === -1
@ -207,7 +214,7 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
padding-bottom: 16px; padding-bottom: 16px;
} }
ha-icon { ha-svg-icon {
color: var(--paper-item-icon-color); color: var(--paper-item-icon-color);
margin-bottom: 8px; margin-bottom: 8px;
} }
@ -238,20 +245,16 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
} }
private computeAttributes(stateObj: HassEntity): string[] { private computeAttributes(stateObj: HassEntity): string[] {
return Object.keys(SENSORS).filter((key) => key in stateObj.attributes); return Object.keys(SENSOR_ICONS).filter(
(key) => key in stateObj.attributes
);
} }
private computeIcon(attr: string, batLvl: number): string { private computeIcon(attr: string, batLvl: number): string {
const icon = SENSORS[attr];
if (attr === "battery") { if (attr === "battery") {
if (batLvl <= 5) { return batteryIcon(batLvl);
return `${icon}-alert`;
}
if (batLvl < 95) {
return `${icon}-${Math.round(batLvl / 10 - 0.01) * 10}`;
}
} }
return icon; return SENSOR_ICONS[attr];
} }
private _handleMoreInfo(ev: Event): void { private _handleMoreInfo(ev: Event): void {

View File

@ -15,7 +15,7 @@ import { guard } from "lit/directives/guard";
import { repeat } from "lit/directives/repeat"; import { repeat } from "lit/directives/repeat";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-checkbox"; import "../../../components/ha-checkbox";
import { import {
addItem, addItem,
@ -366,11 +366,6 @@ class HuiShoppingListCard
align-items: center; align-items: center;
} }
.addRow ha-icon {
color: var(--secondary-text-color);
--mdc-icon-size: 26px;
}
.addButton { .addButton {
padding-right: 16px; padding-right: 16px;
cursor: pointer; cursor: pointer;

View File

@ -1,4 +1,13 @@
import { mdiDotsVertical } from "@mdi/js"; import {
mdiAutorenew,
mdiCalendarSync,
mdiDotsVertical,
mdiFan,
mdiFire,
mdiPower,
mdiSnowflake,
mdiWaterPercent,
} from "@mdi/js";
import "@thomasloven/round-slider"; import "@thomasloven/round-slider";
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { import {
@ -19,7 +28,6 @@ import { computeStateName } from "../../../common/entity/compute_state_name";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
import "../../../components/ha-card"; import "../../../components/ha-card";
import type { HaCard } from "../../../components/ha-card"; import type { HaCard } from "../../../components/ha-card";
import "../../../components/ha-icon";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import { import {
ClimateEntity, ClimateEntity,
@ -36,13 +44,13 @@ import { LovelaceCard, LovelaceCardEditor } from "../types";
import { ThermostatCardConfig } from "./types"; import { ThermostatCardConfig } from "./types";
const modeIcons: { [mode in HvacMode]: string } = { const modeIcons: { [mode in HvacMode]: string } = {
auto: "hass:calendar-sync", auto: mdiCalendarSync,
heat_cool: "hass:autorenew", heat_cool: mdiAutorenew,
heat: "hass:fire", heat: mdiFire,
cool: "hass:snowflake", cool: mdiSnowflake,
off: "hass:power", off: mdiPower,
fan_only: "hass:fan", fan_only: mdiFan,
dry: "hass:water-percent", dry: mdiWaterPercent,
}; };
@customElement("hui-thermostat-card") @customElement("hui-thermostat-card")
@ -418,8 +426,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
.mode=${mode} .mode=${mode}
@click=${this._handleAction} @click=${this._handleAction}
tabindex="0" tabindex="0"
.path=${modeIcons[mode]}
> >
<ha-icon .icon=${modeIcons[mode]}></ha-icon>
</ha-icon-button> </ha-icon-button>
`; `;
} }

View File

@ -12,12 +12,11 @@ import { formatTime } from "../../../common/datetime/format_time";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
import { debounce } from "../../../common/util/debounce"; import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-svg-icon";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import { ActionHandlerEvent } from "../../../data/lovelace"; import { ActionHandlerEvent } from "../../../data/lovelace";
import { import {
@ -207,10 +206,10 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
<div class="icon-image"> <div class="icon-image">
${weatherStateIcon || ${weatherStateIcon ||
html` html`
<ha-icon <ha-state-icon
class="weather-icon" class="weather-icon"
.icon=${stateIcon(stateObj)} .state=${stateObj}
></ha-icon> ></ha-state-icon>
`} `}
</div> </div>
<div class="info"> <div class="info">

View File

@ -15,7 +15,6 @@ import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { computeRTL } from "../../../common/util/compute_rtl"; import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-icon";
import "../../../components/ha-relative-time"; import "../../../components/ha-relative-time";
import { ActionHandlerEvent } from "../../../data/lovelace"; import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";

View File

@ -1,3 +1,4 @@
import { mdiClose } from "@mdi/js";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu"; import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import "@polymer/paper-item/paper-item"; import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox"; import "@polymer/paper-listbox/paper-listbox";
@ -6,7 +7,7 @@ import { customElement, property, state } from "lit/decorators";
import { array, assert, assign, object, optional, string } from "superstruct"; import { array, assert, assign, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-icon"; import "../../../../components/ha-svg-icon";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { AlarmPanelCardConfig } from "../../cards/types"; import { AlarmPanelCardConfig } from "../../cards/types";
import "../../components/hui-theme-select-editor"; import "../../components/hui-theme-select-editor";
@ -73,12 +74,11 @@ export class HuiAlarmPanelCardEditor
return html` return html`
<div class="card-config"> <div class="card-config">
<ha-entity-picker <ha-entity-picker
.label=${this.hass.localize( .label=${`${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.entity" "ui.panel.lovelace.editor.card.generic.entity"
)} )} (${this.hass.localize(
(${this.hass.localize(
"ui.panel.lovelace.editor.card.config.required" "ui.panel.lovelace.editor.card.config.required"
)}) )})`}
.hass=${this.hass} .hass=${this.hass}
.value=${this._entity} .value=${this._entity}
.configValue=${"entity"} .configValue=${"entity"}
@ -87,12 +87,11 @@ export class HuiAlarmPanelCardEditor
allow-custom-entity allow-custom-entity
></ha-entity-picker> ></ha-entity-picker>
<paper-input <paper-input
.label=${this.hass.localize( .label=${`${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.name" "ui.panel.lovelace.editor.card.generic.name"
)} )} (${this.hass.localize(
(${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional" "ui.panel.lovelace.editor.card.config.optional"
)}) )})`}
.value=${this._name} .value=${this._name}
.configValue=${"name"} .configValue=${"name"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@ -101,12 +100,12 @@ export class HuiAlarmPanelCardEditor
(entityState, index) => html` (entityState, index) => html`
<div class="states"> <div class="states">
<paper-item>${entityState}</paper-item> <paper-item>${entityState}</paper-item>
<ha-icon <ha-svg-icon
class="deleteState" class="deleteState"
.value=${index} .value=${index}
icon="hass:close" .path=${mdiClose}
@click=${this._stateRemoved} @click=${this._stateRemoved}
></ha-icon> ></ha-svg-icon>
</div> </div>
` `
)} )}
@ -146,7 +145,7 @@ export class HuiAlarmPanelCardEditor
.states:hover > .deleteState { .states:hover > .deleteState {
visibility: visible; visibility: visible;
} }
ha-icon { ha-svg-icon {
padding-top: 12px; padding-top: 12px;
} }
`, `,

View File

@ -3,7 +3,6 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { assert, boolean, object, optional, string, assign } from "superstruct"; import { assert, boolean, object, optional, string, assign } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stateIcon } from "../../../../common/entity/state_icon";
import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import { computeRTLDirection } from "../../../../common/util/compute_rtl";
import "../../../../components/ha-formfield"; import "../../../../components/ha-formfield";
import "../../../../components/ha-icon-picker"; import "../../../../components/ha-icon-picker";
@ -19,6 +18,8 @@ import { actionConfigStruct } from "../structs/action-struct";
import { EditorTarget } from "../types"; import { EditorTarget } from "../types";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -107,6 +108,7 @@ export class HuiButtonCardEditor
} }
const dir = computeRTLDirection(this.hass!); const dir = computeRTLDirection(this.hass!);
const entityState = this.hass.states[this._entity];
return html` return html`
<div class="card-config"> <div class="card-config">
@ -140,8 +142,12 @@ export class HuiButtonCardEditor
"ui.panel.lovelace.editor.card.config.optional" "ui.panel.lovelace.editor.card.config.optional"
)})" )})"
.value=${this._icon} .value=${this._icon}
.placeholder=${this._icon || .placeholder=${this._icon || entityState?.attributes.icon}
stateIcon(this.hass.states[this._entity])} .fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-icon-picker> ></ha-icon-picker>

View File

@ -3,7 +3,8 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { assert, assign, boolean, object, optional, string } from "superstruct"; import { assert, assign, boolean, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stateIcon } from "../../../../common/entity/state_icon"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon";
import "../../../../components/entity/ha-entity-attribute-picker"; import "../../../../components/entity/ha-entity-attribute-picker";
import "../../../../components/ha-icon-picker"; import "../../../../components/ha-icon-picker";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
@ -77,6 +78,7 @@ export class HuiEntityCardEditor
if (!this.hass || !this._config) { if (!this.hass || !this._config) {
return html``; return html``;
} }
const entityState = this.hass.states[this._entity];
return html` return html`
<div class="card-config"> <div class="card-config">
@ -110,8 +112,12 @@ export class HuiEntityCardEditor
"ui.panel.lovelace.editor.card.config.optional" "ui.panel.lovelace.editor.card.config.optional"
)})" )})"
.value=${this._icon} .value=${this._icon}
.placeholder=${this._icon || .placeholder=${this._icon || entityState?.attributes.icon}
stateIcon(this.hass.states[this._entity])} .fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-icon-picker> ></ha-icon-picker>

View File

@ -4,7 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import { assert } from "superstruct"; import { assert } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { stateIcon } from "../../../../common/entity/state_icon"; import { domainIcon } from "../../../../common/entity/domain_icon";
import "../../../../components/ha-formfield"; import "../../../../components/ha-formfield";
import "../../../../components/ha-icon-picker"; import "../../../../components/ha-icon-picker";
import "../../../../components/ha-switch"; import "../../../../components/ha-switch";
@ -64,6 +64,7 @@ export class HuiGenericEntityRowEditor
} }
const domain = computeDomain(this._entity); const domain = computeDomain(this._entity);
const entityState = this.hass.states[this._entity];
return html` return html`
<div class="card-config"> <div class="card-config">
@ -88,8 +89,13 @@ export class HuiGenericEntityRowEditor
"ui.panel.lovelace.editor.card.generic.icon" "ui.panel.lovelace.editor.card.generic.icon"
)} )}
.value=${this._config.icon} .value=${this._config.icon}
.placeholder=${stateIcon(this.hass!.states[this._config.entity])}
.configValue=${"icon"} .configValue=${"icon"}
.placeholder=${entityState?.attributes.icon}
.fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-icon-picker> ></ha-icon-picker>
</div> </div>

View File

@ -3,7 +3,6 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { assert, object, optional, string, assign } from "superstruct"; import { assert, object, optional, string, assign } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stateIcon } from "../../../../common/entity/state_icon";
import "../../../../components/ha-icon-picker"; import "../../../../components/ha-icon-picker";
import { ActionConfig } from "../../../../data/lovelace"; import { ActionConfig } from "../../../../data/lovelace";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
@ -16,6 +15,8 @@ import { actionConfigStruct } from "../structs/action-struct";
import { EditorTarget } from "../types"; import { EditorTarget } from "../types";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { domainIcon } from "../../../../common/entity/domain_icon";
import { computeDomain } from "../../../../common/entity/compute_domain";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -83,6 +84,8 @@ export class HuiLightCardEditor
"none", "none",
]; ];
const entityState = this.hass.states[this._entity];
return html` return html`
<div class="card-config"> <div class="card-config">
<ha-entity-picker <ha-entity-picker
@ -116,8 +119,12 @@ export class HuiLightCardEditor
"ui.panel.lovelace.editor.card.config.optional" "ui.panel.lovelace.editor.card.config.optional"
)})" )})"
.value=${this._icon} .value=${this._icon}
.placeholder=${this._icon || .placeholder=${this._icon || entityState?.attributes.icon}
stateIcon(this.hass.states[this._entity])} .fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-icon-picker> ></ha-icon-picker>

View File

@ -4,7 +4,6 @@ import { customElement, property, state } from "lit/decorators";
import { assert, assign, object, optional, string } from "superstruct"; import { assert, assign, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-icon";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { PlantStatusCardConfig } from "../../cards/types"; import { PlantStatusCardConfig } from "../../cards/types";
import "../../components/hui-theme-select-editor"; import "../../components/hui-theme-select-editor";

View File

@ -6,7 +6,8 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { assert, assign, number, object, optional, string } from "superstruct"; import { assert, assign, number, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stateIcon } from "../../../../common/entity/state_icon"; import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-formfield"; import "../../../../components/ha-formfield";
import "../../../../components/ha-icon-picker"; import "../../../../components/ha-icon-picker";
@ -88,6 +89,8 @@ export class HuiSensorCardEditor
const graphs = ["line", "none"]; const graphs = ["line", "none"];
const entityState = this.hass.states[this._entity];
return html` return html`
<div class="card-config"> <div class="card-config">
<ha-entity-picker <ha-entity-picker
@ -121,8 +124,12 @@ export class HuiSensorCardEditor
"ui.panel.lovelace.editor.card.config.optional" "ui.panel.lovelace.editor.card.config.optional"
)})" )})"
.value=${this._icon} .value=${this._icon}
.placeholder=${this._icon || .placeholder=${this._icon || entityState?.attributes.icon}
stateIcon(this.hass.states[this._entity])} .fallbackPath=${!this._icon &&
!entityState?.attributes.icon &&
entityState
? domainIcon(computeDomain(entityState.entity_id), entityState)
: undefined}
.configValue=${"icon"} .configValue=${"icon"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
></ha-icon-picker> ></ha-icon-picker>

View File

@ -8,7 +8,6 @@ import { navigate } from "../../../../common/navigate";
import "../../../../components/ha-circular-progress"; import "../../../../components/ha-circular-progress";
import "../../../../components/ha-dialog"; import "../../../../components/ha-dialog";
import "../../../../components/ha-alert"; import "../../../../components/ha-alert";
import "../../../../components/ha-icon-button";
import type { import type {
LovelaceBadgeConfig, LovelaceBadgeConfig,
LovelaceCardConfig, LovelaceCardConfig,

View File

@ -13,7 +13,6 @@ import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import { UNAVAILABLE_STATES } from "../../../data/entity"; import { UNAVAILABLE_STATES } from "../../../data/entity";
@ -89,7 +88,10 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
> >
${weatherStateIcon || ${weatherStateIcon ||
html` html`
<ha-icon class="weather-icon" .icon=${stateIcon(stateObj)}></ha-icon> <ha-state-icon
class="weather-icon"
.state=${stateObj}
></ha-state-icon>
`} `}
</div> </div>
<div <div

View File

@ -20,7 +20,6 @@ import { deepEqual } from "../../common/util/deep-equal";
import "../../components/ha-circular-progress"; import "../../components/ha-circular-progress";
import "../../components/ha-code-editor"; import "../../components/ha-code-editor";
import type { HaCodeEditor } from "../../components/ha-code-editor"; import type { HaCodeEditor } from "../../components/ha-code-editor";
import "../../components/ha-icon";
import "../../components/ha-icon-button"; import "../../components/ha-icon-button";
import type { LovelaceConfig } from "../../data/lovelace"; import type { LovelaceConfig } from "../../data/lovelace";
import { import {

View File

@ -4,14 +4,13 @@ import { customElement, state } from "lit/decorators";
import { DOMAINS_TOGGLE } from "../../../common/const"; import { DOMAINS_TOGGLE } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import "../../../components/ha-icon";
import { ActionHandlerEvent } from "../../../data/lovelace"; import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive"; import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action"; import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action"; import { hasAction } from "../common/has-action";
import { ButtonRowConfig, LovelaceRow } from "../entity-rows/types"; import { ButtonRowConfig, LovelaceRow } from "../entity-rows/types";
import "../../../components/ha-state-icon";
@customElement("hui-button-row") @customElement("hui-button-row")
export class HuiButtonRow extends LitElement implements LovelaceRow { export class HuiButtonRow extends LitElement implements LovelaceRow {
@ -54,11 +53,8 @@ export class HuiButtonRow extends LitElement implements LovelaceRow {
this._config.name ?? (stateObj ? computeStateName(stateObj) : ""); this._config.name ?? (stateObj ? computeStateName(stateObj) : "");
return html` return html`
<ha-icon <ha-state-icon .icon=${this._config.icon} .state=${stateObj}>
.icon=${this._config.icon || </ha-state-icon>
(stateObj ? stateIcon(stateObj) : "hass:remote")}
>
</ha-icon>
<div class="flex"> <div class="flex">
<div .title=${name}>${name}</div> <div .title=${name}>${name}</div>
<mwc-button <mwc-button
@ -81,7 +77,7 @@ export class HuiButtonRow extends LitElement implements LovelaceRow {
display: flex; display: flex;
align-items: center; align-items: center;
} }
ha-icon { ha-state-icon {
padding: 8px; padding: 8px;
color: var(--paper-item-icon-color); color: var(--paper-item-icon-color);
} }

View File

@ -1,6 +1,5 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators"; import { customElement, state } from "lit/decorators";
import "../../../components/ha-icon";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceRow, SectionConfig } from "../entity-rows/types"; import { LovelaceRow, SectionConfig } from "../entity-rows/types";