diff --git a/src/components/tile/ha-tile-container.ts b/src/components/tile/ha-tile-container.ts
new file mode 100644
index 0000000000..327fac2eb3
--- /dev/null
+++ b/src/components/tile/ha-tile-container.ts
@@ -0,0 +1,155 @@
+import { css, html, LitElement } from "lit";
+import { customElement, property } from "lit/decorators";
+import { classMap } from "lit/directives/class-map";
+import { ifDefined } from "lit/directives/if-defined";
+import type { ActionHandlerOptions } from "../../data/lovelace/action_handler";
+import { actionHandler } from "../../panels/lovelace/common/directives/action-handler-directive";
+import "../ha-ripple";
+
+@customElement("ha-tile-container")
+export class HaTileContainer extends LitElement {
+ @property({ attribute: false })
+ public featurePosition: "bottom" | "inline" = "bottom";
+
+ @property({ type: Boolean })
+ public vertical = false;
+
+ @property({ type: Boolean, attribute: false })
+ public interactive = false;
+
+ @property({ attribute: false })
+ public actionHandlerOptions?: ActionHandlerOptions;
+
+ private _handleFocus(ev: FocusEvent) {
+ if ((ev.target as HTMLElement).matches(":focus-visible")) {
+ this.setAttribute("focused", "");
+ }
+ }
+
+ private _handleBlur() {
+ this.removeAttribute("focused");
+ }
+
+ protected render() {
+ const containerOrientationClass =
+ this.featurePosition === "inline" ? "horizontal" : "";
+ const contentClasses = { vertical: this.vertical };
+
+ return html`
+
-
+
+ ${this._renderIcon()}
`;
@@ -60,6 +82,11 @@ export class HaTileIcon extends LitElement {
position: relative;
user-select: none;
transition: transform 180ms ease-in-out;
+ pointer-events: none;
+ }
+ :host([interactive]) {
+ -webkit-tap-highlight-color: transparent;
+ pointer-events: auto;
}
:host([interactive]:active) {
transform: scale(1.2);
@@ -78,9 +105,16 @@ export class HaTileIcon extends LitElement {
overflow: hidden;
transition: box-shadow 180ms ease-in-out;
}
- :host([interactive]:focus-visible) .container {
+ .container:focus-visible {
box-shadow: 0 0 0 2px var(--tile-icon-color);
}
+ .container:focus {
+ outline: none;
+ }
+ [role="button"] {
+ cursor: pointer;
+ pointer-events: auto;
+ }
.container.background::before {
content: "";
position: absolute;
@@ -94,7 +128,9 @@ export class HaTileIcon extends LitElement {
opacity 180ms ease-in-out;
opacity: var(--tile-icon-opacity);
}
- .container ::slotted([slot="icon"]) {
+ .container ::slotted([slot="icon"]),
+ .container ha-icon,
+ .container ha-svg-icon {
display: flex;
color: var(--tile-icon-color);
transition: color 180ms ease-in-out;
diff --git a/src/panels/lovelace/cards/hui-area-card.ts b/src/panels/lovelace/cards/hui-area-card.ts
index 60bd6cf40d..50fbbd270c 100644
--- a/src/panels/lovelace/cards/hui-area-card.ts
+++ b/src/panels/lovelace/cards/hui-area-card.ts
@@ -9,8 +9,6 @@ import {
type TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
-import { classMap } from "lit/directives/class-map";
-import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { computeCssColor } from "../../../common/color/compute-color";
@@ -30,21 +28,20 @@ import "../../../components/ha-control-button";
import "../../../components/ha-control-button-group";
import "../../../components/ha-domain-icon";
import "../../../components/ha-icon";
-import "../../../components/ha-ripple";
-import "../../../components/ha-svg-icon";
import "../../../components/tile/ha-tile-badge";
+import "../../../components/tile/ha-tile-container";
import "../../../components/tile/ha-tile-icon";
import "../../../components/tile/ha-tile-info";
import { isUnavailableState } from "../../../data/entity/entity";
import type { HomeAssistant } from "../../../types";
import "../card-features/hui-card-features";
import type { LovelaceCardFeatureContext } from "../card-features/types";
-import { actionHandler } from "../common/directives/action-handler-directive";
import type {
LovelaceCard,
LovelaceCardEditor,
LovelaceGridOptions,
} from "../types";
+import { tileCardStyle } from "./tile/tile-card-style";
import type { AreaCardConfig } from "./types";
export const DEFAULT_ASPECT_RATIO = "16:9";
@@ -548,9 +545,7 @@ export class HuiAreaCard extends LitElement implements LovelaceCard {
`;
}
- const contentClasses = { vertical: Boolean(this._config.vertical) };
-
- const icon = area.icon;
+ const icon = area.icon || undefined;
const name = this._config.name || computeAreaName(area);
@@ -560,9 +555,6 @@ export class HuiAreaCard extends LitElement implements LovelaceCard {
const featurePosition = this._featurePosition(this._config);
const features = this._displayedFeatures(this._config);
- const containerOrientationClass =
- featurePosition === "inline" ? "horizontal" : "";
-
const displayType = this._config.display_type || "picture";
const cameraEntityId =
@@ -582,16 +574,6 @@ export class HuiAreaCard extends LitElement implements LovelaceCard {
return html`
-
-
-
${displayType === "compact"
? nothing
: html`
@@ -628,30 +610,30 @@ export class HuiAreaCard extends LitElement implements LovelaceCard {
${this._renderAlertSensors()}
`}
-