mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Introduce tile card (#14085)
This commit is contained in:
parent
a475b06d49
commit
dec8883f2a
44
src/common/color/compute-color.ts
Normal file
44
src/common/color/compute-color.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { hex2rgb } from "./convert-color";
|
||||||
|
|
||||||
|
export const THEME_COLORS = new Set(["primary", "accent", "disabled"]);
|
||||||
|
|
||||||
|
export const COLORS = new Map([
|
||||||
|
["red", "#f44336"],
|
||||||
|
["pink", "#e91e63"],
|
||||||
|
["purple", "#9b27b0"],
|
||||||
|
["deep-purple", "#683ab7"],
|
||||||
|
["indigo", "#3f51b5"],
|
||||||
|
["blue", "#2194f3"],
|
||||||
|
["light-blue", "#2196f3"],
|
||||||
|
["cyan", "#03a8f4"],
|
||||||
|
["teal", "#009688"],
|
||||||
|
["green", "#4caf50"],
|
||||||
|
["light-green", "#8bc34a"],
|
||||||
|
["lime", "#ccdc39"],
|
||||||
|
["yellow", "#ffeb3b"],
|
||||||
|
["amber", "#ffc107"],
|
||||||
|
["orange", "#ff9800"],
|
||||||
|
["deep-orange", "#ff5722"],
|
||||||
|
["brown", "#795548"],
|
||||||
|
["grey", "#9e9e9e"],
|
||||||
|
["blue-grey", "#607d8b"],
|
||||||
|
["black", "#000000"],
|
||||||
|
["white", "ffffff"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function computeRgbColor(color: string): string {
|
||||||
|
if (THEME_COLORS.has(color)) {
|
||||||
|
return `var(--rgb-${color}-color)`;
|
||||||
|
}
|
||||||
|
if (COLORS.has(color)) {
|
||||||
|
return hex2rgb(COLORS.get(color)!).join(", ");
|
||||||
|
}
|
||||||
|
if (color.startsWith("#")) {
|
||||||
|
try {
|
||||||
|
return hex2rgb(color).join(", ");
|
||||||
|
} catch (err) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
54
src/components/tile/ha-tile-icon.ts
Normal file
54
src/components/tile/ha-tile-icon.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { CSSResultGroup, html, css, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import "../ha-icon";
|
||||||
|
import "../ha-svg-icon";
|
||||||
|
|
||||||
|
@customElement("ha-tile-icon")
|
||||||
|
export class HaTileIcon extends LitElement {
|
||||||
|
@property() public iconPath?: string;
|
||||||
|
|
||||||
|
@property() public icon?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="shape">
|
||||||
|
${this.icon
|
||||||
|
? html`<ha-icon .icon=${this.icon}></ha-icon>`
|
||||||
|
: html`<ha-svg-icon .path=${this.iconPath}></ha-svg-icon>`}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
--icon-color: rgb(var(--color));
|
||||||
|
--shape-color: rgba(var(--color), 0.2);
|
||||||
|
--mdc-icon-size: 24px;
|
||||||
|
}
|
||||||
|
.shape {
|
||||||
|
position: relative;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: var(--shape-color);
|
||||||
|
transition: background-color 180ms ease-in-out, color 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
.shape ha-icon,
|
||||||
|
.shape ha-svg-icon {
|
||||||
|
display: flex;
|
||||||
|
color: var(--icon-color);
|
||||||
|
transition: color 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-tile-icon": HaTileIcon;
|
||||||
|
}
|
||||||
|
}
|
59
src/components/tile/ha-tile-info.ts
Normal file
59
src/components/tile/ha-tile-info.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { CSSResultGroup, html, css, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import "../ha-icon";
|
||||||
|
import "../ha-svg-icon";
|
||||||
|
|
||||||
|
@customElement("ha-tile-info")
|
||||||
|
export class HaTileInfo extends LitElement {
|
||||||
|
@property() public primary?: string;
|
||||||
|
|
||||||
|
@property() public secondary?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<div class="info">
|
||||||
|
<span class="primary">${this.primary}</span>
|
||||||
|
${this.secondary
|
||||||
|
? html`<span class="secondary">${this.secondary}</span>`
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
.info {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.primary {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
.secondary {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-tile-info": HaTileInfo;
|
||||||
|
}
|
||||||
|
}
|
210
src/panels/lovelace/cards/hui-tile-card.ts
Normal file
210
src/panels/lovelace/cards/hui-tile-card.ts
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
import { mdiHelp } from "@mdi/js";
|
||||||
|
import { css, CSSResultGroup, html, LitElement } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { styleMap } from "lit/directives/style-map";
|
||||||
|
import { computeRgbColor } from "../../../common/color/compute-color";
|
||||||
|
import { DOMAINS_TOGGLE, STATES_OFF } from "../../../common/const";
|
||||||
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||||
|
import { stateIconPath } from "../../../common/entity/state_icon_path";
|
||||||
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/tile/ha-tile-icon";
|
||||||
|
import "../../../components/tile/ha-tile-info";
|
||||||
|
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||||
|
import { findEntities } from "../common/find-entities";
|
||||||
|
import { handleAction } from "../common/handle-action";
|
||||||
|
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||||
|
import { ThermostatCardConfig, TileCardConfig } from "./types";
|
||||||
|
|
||||||
|
@customElement("hui-tile-card")
|
||||||
|
export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||||
|
public static async getConfigElement(): Promise<LovelaceCardEditor> {
|
||||||
|
await import("../editor/config-elements/hui-tile-card-editor");
|
||||||
|
return document.createElement("hui-tile-card-editor");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getStubConfig(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entities: string[],
|
||||||
|
entitiesFallback: string[]
|
||||||
|
): TileCardConfig {
|
||||||
|
const includeDomains = ["sensor", "light", "switch"];
|
||||||
|
const maxEntities = 1;
|
||||||
|
const foundEntities = findEntities(
|
||||||
|
hass,
|
||||||
|
maxEntities,
|
||||||
|
entities,
|
||||||
|
entitiesFallback,
|
||||||
|
includeDomains
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "tile",
|
||||||
|
entity: foundEntities[0] || "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _config?: TileCardConfig;
|
||||||
|
|
||||||
|
public setConfig(config: ThermostatCardConfig): void {
|
||||||
|
if (!config.entity) {
|
||||||
|
throw new Error("Specify an entity");
|
||||||
|
}
|
||||||
|
|
||||||
|
const supportToggle =
|
||||||
|
config.entity && DOMAINS_TOGGLE.has(computeDomain(config.entity));
|
||||||
|
|
||||||
|
this._config = {
|
||||||
|
tap_action: {
|
||||||
|
action: "more-info",
|
||||||
|
},
|
||||||
|
icon_tap_action: {
|
||||||
|
action: supportToggle ? "toggle" : "more-info",
|
||||||
|
},
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCardSize(): number {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleAction(ev: ActionHandlerEvent) {
|
||||||
|
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleIconAction() {
|
||||||
|
const config = {
|
||||||
|
entity: this._config!.entity,
|
||||||
|
tap_action: this._config!.icon_tap_action,
|
||||||
|
};
|
||||||
|
handleAction(this, this.hass!, config, "tap");
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (!this._config || !this.hass) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
const entityId = this._config.entity;
|
||||||
|
const entity = entityId ? this.hass.states[entityId] : undefined;
|
||||||
|
|
||||||
|
if (!entity) {
|
||||||
|
return html`
|
||||||
|
<ha-card class="disabled">
|
||||||
|
<div class="tile">
|
||||||
|
<ha-tile-icon .iconPath=${mdiHelp}></ha-tile-icon>
|
||||||
|
<ha-tile-info
|
||||||
|
.primary=${entityId}
|
||||||
|
secondary=${this.hass.localize("ui.card.tile.not_found")}
|
||||||
|
></ha-tile-info>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = this._config.icon || entity.attributes.icon;
|
||||||
|
const iconPath = stateIconPath(entity);
|
||||||
|
|
||||||
|
const name = this._config.name || entity.attributes.friendly_name;
|
||||||
|
const stateDisplay = computeStateDisplay(
|
||||||
|
this.hass.localize,
|
||||||
|
entity,
|
||||||
|
this.hass.locale
|
||||||
|
);
|
||||||
|
|
||||||
|
const iconStyle = {};
|
||||||
|
if (this._config.color && !STATES_OFF.includes(entity.state)) {
|
||||||
|
iconStyle["--main-color"] = computeRgbColor(this._config.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-card style=${styleMap(iconStyle)}>
|
||||||
|
<div class="tile">
|
||||||
|
<ha-tile-icon
|
||||||
|
.icon=${icon}
|
||||||
|
.iconPath=${iconPath}
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
@action=${this._handleIconAction}
|
||||||
|
.actionHandler=${actionHandler()}
|
||||||
|
></ha-tile-icon>
|
||||||
|
<ha-tile-info
|
||||||
|
.primary=${name}
|
||||||
|
.secondary=${stateDisplay}
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
@action=${this._handleAction}
|
||||||
|
.actionHandler=${actionHandler()}
|
||||||
|
></ha-tile-info>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
--main-color: var(--rgb-disabled-color);
|
||||||
|
--tap-padding: 6px;
|
||||||
|
}
|
||||||
|
ha-card {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
ha-card.disabled {
|
||||||
|
background: rgba(var(--rgb-disabled-color), 0.1);
|
||||||
|
}
|
||||||
|
.tile {
|
||||||
|
padding: calc(12px - var(--tap-padding));
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
ha-tile-icon {
|
||||||
|
padding: var(--tap-padding);
|
||||||
|
flex: none;
|
||||||
|
margin-right: calc(12px - 2 * var(--tap-padding));
|
||||||
|
margin-inline-end: calc(12px - 2 * var(--tap-padding));
|
||||||
|
margin-inline-start: initial;
|
||||||
|
direction: var(--direction);
|
||||||
|
--color: var(--main-color);
|
||||||
|
transition: transform 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
[role="button"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
ha-tile-icon[role="button"]:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
ha-tile-icon[role="button"]:focus-visible {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
ha-tile-icon[role="button"]:active {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
ha-tile-info {
|
||||||
|
padding: var(--tap-padding);
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 40px;
|
||||||
|
border-radius: calc(var(--ha-card-border-radius, 12px) - 2px);
|
||||||
|
transition: background-color 180ms ease-in-out;
|
||||||
|
}
|
||||||
|
ha-tile-info:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
ha-tile-info:focus-visible {
|
||||||
|
background-color: rgba(var(--main-color), 0.1);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-tile-card": HuiTileCard;
|
||||||
|
}
|
||||||
|
}
|
@ -472,3 +472,12 @@ export interface EnergyFlowCardConfig extends LovelaceCardConfig {
|
|||||||
hold_action?: ActionConfig;
|
hold_action?: ActionConfig;
|
||||||
double_tap_action?: ActionConfig;
|
double_tap_action?: ActionConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TileCardConfig extends LovelaceCardConfig {
|
||||||
|
entity: string;
|
||||||
|
name?: string;
|
||||||
|
icon?: string;
|
||||||
|
color?: string;
|
||||||
|
tap_action?: ActionConfig;
|
||||||
|
icon_tap_action?: ActionConfig;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import "../cards/hui-light-card";
|
|||||||
import "../cards/hui-sensor-card";
|
import "../cards/hui-sensor-card";
|
||||||
import "../cards/hui-thermostat-card";
|
import "../cards/hui-thermostat-card";
|
||||||
import "../cards/hui-weather-forecast-card";
|
import "../cards/hui-weather-forecast-card";
|
||||||
|
import "../cards/hui-tile-card";
|
||||||
import {
|
import {
|
||||||
createLovelaceElement,
|
createLovelaceElement,
|
||||||
getLovelaceElementClass,
|
getLovelaceElementClass,
|
||||||
@ -27,6 +28,7 @@ const ALWAYS_LOADED_TYPES = new Set([
|
|||||||
"sensor",
|
"sensor",
|
||||||
"thermostat",
|
"thermostat",
|
||||||
"weather-forecast",
|
"weather-forecast",
|
||||||
|
"tile",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const LAZY_LOAD_TYPES = {
|
const LAZY_LOAD_TYPES = {
|
||||||
|
@ -0,0 +1,153 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
import { assert, assign, object, optional, string } from "superstruct";
|
||||||
|
import { COLORS, THEME_COLORS } from "../../../../common/color/compute-color";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { computeDomain } from "../../../../common/entity/compute_domain";
|
||||||
|
import { domainIcon } from "../../../../common/entity/domain_icon";
|
||||||
|
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
|
||||||
|
import "../../../../components/ha-form/ha-form";
|
||||||
|
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||||
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
import type { TileCardConfig } from "../../cards/types";
|
||||||
|
import type { LovelaceCardEditor } from "../../types";
|
||||||
|
import { actionConfigStruct } from "../structs/action-struct";
|
||||||
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
|
|
||||||
|
const cardConfigStruct = assign(
|
||||||
|
baseLovelaceCardConfig,
|
||||||
|
object({
|
||||||
|
entity: optional(string()),
|
||||||
|
name: optional(string()),
|
||||||
|
icon: optional(string()),
|
||||||
|
color: optional(string()),
|
||||||
|
tap_action: optional(actionConfigStruct),
|
||||||
|
icon_tap_action: optional(actionConfigStruct),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
@customElement("hui-tile-card-editor")
|
||||||
|
export class HuiTileCardEditor
|
||||||
|
extends LitElement
|
||||||
|
implements LovelaceCardEditor
|
||||||
|
{
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _config?: TileCardConfig;
|
||||||
|
|
||||||
|
public setConfig(config: TileCardConfig): void {
|
||||||
|
assert(config, cardConfigStruct);
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _schema = memoizeOne(
|
||||||
|
(entity: string, icon?: string, entityState?: HassEntity) =>
|
||||||
|
[
|
||||||
|
{ name: "entity", selector: { entity: {} } },
|
||||||
|
{ name: "name", selector: { text: {} } },
|
||||||
|
{
|
||||||
|
name: "icon",
|
||||||
|
selector: {
|
||||||
|
icon: {
|
||||||
|
placeholder: icon || entityState?.attributes.icon,
|
||||||
|
fallbackPath:
|
||||||
|
!icon && !entityState?.attributes.icon && entityState
|
||||||
|
? domainIcon(computeDomain(entity), entityState)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "color",
|
||||||
|
selector: {
|
||||||
|
select: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "Default",
|
||||||
|
value: "default",
|
||||||
|
},
|
||||||
|
...[
|
||||||
|
...Array.from(THEME_COLORS),
|
||||||
|
...Array.from(COLORS.keys()),
|
||||||
|
].map((color) => ({
|
||||||
|
label: capitalizeFirstLetter(color),
|
||||||
|
value: color,
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tap_action",
|
||||||
|
selector: {
|
||||||
|
"ui-action": {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "icon_tap_action",
|
||||||
|
selector: {
|
||||||
|
"ui-action": {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
);
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.hass || !this._config) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entity = this.hass.states[this._config.entity ?? ""];
|
||||||
|
|
||||||
|
const schema = this._schema(this._config.entity, this._config.icon, entity);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
color: "default",
|
||||||
|
...this._config,
|
||||||
|
};
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-form
|
||||||
|
.hass=${this.hass}
|
||||||
|
.data=${data}
|
||||||
|
.schema=${schema}
|
||||||
|
.computeLabel=${this._computeLabelCallback}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-form>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
|
const config = {
|
||||||
|
...ev.detail.value,
|
||||||
|
};
|
||||||
|
if (ev.detail.value.color === "default") {
|
||||||
|
config.color = undefined;
|
||||||
|
}
|
||||||
|
fireEvent(this, "config-changed", { config });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeLabelCallback = (
|
||||||
|
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||||
|
) => {
|
||||||
|
switch (schema.name) {
|
||||||
|
case "color":
|
||||||
|
case "icon_tap_action":
|
||||||
|
return this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.tile.${schema.name}`
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return this.hass!.localize(
|
||||||
|
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-tile-card-editor": HuiTileCardEditor;
|
||||||
|
}
|
||||||
|
}
|
@ -93,6 +93,10 @@ export const coreCards: Card[] = [
|
|||||||
type: "area",
|
type: "area",
|
||||||
showElement: true,
|
showElement: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "tile",
|
||||||
|
showElement: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "conditional",
|
type: "conditional",
|
||||||
},
|
},
|
||||||
|
@ -111,6 +111,7 @@ documentContainer.innerHTML = `<custom-style>
|
|||||||
--rgb-secondary-text-color: 114, 114, 114;
|
--rgb-secondary-text-color: 114, 114, 114;
|
||||||
--rgb-text-primary-color: 255, 255, 255;
|
--rgb-text-primary-color: 255, 255, 255;
|
||||||
--rgb-card-background-color: 255, 255, 255;
|
--rgb-card-background-color: 255, 255, 255;
|
||||||
|
--rgb-disabled-color: 189, 189, 189;
|
||||||
|
|
||||||
/* input components */
|
/* input components */
|
||||||
--input-idle-line-color: rgba(0, 0, 0, 0.42);
|
--input-idle-line-color: rgba(0, 0, 0, 0.42);
|
||||||
|
@ -48,6 +48,7 @@ export const darkStyles = {
|
|||||||
"energy-grid-return-color": "#a280db",
|
"energy-grid-return-color": "#a280db",
|
||||||
"map-filter":
|
"map-filter":
|
||||||
"invert(.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) saturate(.3)",
|
"invert(.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) saturate(.3)",
|
||||||
|
"rgb-disabled-color": "111, 111, 111",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const derivedStyles = {
|
export const derivedStyles = {
|
||||||
|
@ -243,6 +243,9 @@
|
|||||||
"finish": "finish"
|
"finish": "finish"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tile": {
|
||||||
|
"not_found": "Entity not found"
|
||||||
|
},
|
||||||
"vacuum": {
|
"vacuum": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"resume_cleaning": "Resume cleaning",
|
"resume_cleaning": "Resume cleaning",
|
||||||
@ -4120,6 +4123,12 @@
|
|||||||
"name": "Thermostat",
|
"name": "Thermostat",
|
||||||
"description": "The Thermostat card gives control of your climate entity. Allowing you to change the temperature and mode of the entity."
|
"description": "The Thermostat card gives control of your climate entity. Allowing you to change the temperature and mode of the entity."
|
||||||
},
|
},
|
||||||
|
"tile": {
|
||||||
|
"name": "Tile",
|
||||||
|
"description": "The tile card gives you a quick overview of your entity. The card allow you to toggle the entity, show the more info dialog or custom actions.",
|
||||||
|
"color": "Color",
|
||||||
|
"icon_tap_action": "Icon tap action"
|
||||||
|
},
|
||||||
"vertical-stack": {
|
"vertical-stack": {
|
||||||
"name": "Vertical Stack",
|
"name": "Vertical Stack",
|
||||||
"description": "The Vertical Stack card allows you to group multiple cards so they always sit in the same column."
|
"description": "The Vertical Stack card allows you to group multiple cards so they always sit in the same column."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user