- ${this._config.features
+ ${features.length > 0
? html`
`
: nothing}
@@ -372,6 +405,10 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
flex-direction: column;
flex: 1;
}
+ .container.horizontal {
+ flex-direction: row;
+ }
+
.content {
position: relative;
display: flex;
@@ -383,6 +420,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
pointer-events: none;
gap: 10px;
}
+
+ .container.horizontal .content {
+ width: 50%;
+ }
+
.vertical {
flex-direction: column;
text-align: center;
@@ -413,6 +455,13 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
}
hui-card-features {
--feature-color: var(--tile-color);
+ padding: 0 12px 12px 12px;
+ }
+ .container.horizontal hui-card-features {
+ width: 50%;
+ --feature-height: 36px;
+ padding: 10px;
+ padding-inline-start: 0;
}
ha-tile-icon[data-domain="alarm_control_panel"][data-state="pending"],
diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts
index 01ddaf2f53..c1c3f856f1 100644
--- a/src/panels/lovelace/cards/types.ts
+++ b/src/panels/lovelace/cards/types.ts
@@ -533,6 +533,7 @@ export interface TileCardConfig extends LovelaceCardConfig {
icon_hold_action?: ActionConfig;
icon_double_tap_action?: ActionConfig;
features?: LovelaceCardFeatureConfig[];
+ features_position?: "bottom" | "inline";
}
export interface HeadingCardConfig extends LovelaceCardConfig {
diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
index f599b1ee1e..e2507047fc 100644
--- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
@@ -8,6 +8,7 @@ import {
assert,
assign,
boolean,
+ enums,
object,
optional,
string,
@@ -15,6 +16,7 @@ import {
} from "superstruct";
import type { HASSDomEvent } from "../../../../common/dom/fire_event";
import { fireEvent } from "../../../../common/dom/fire_event";
+import type { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-expansion-panel";
import "../../../../components/ha-form/ha-form";
import type {
@@ -54,6 +56,7 @@ const cardConfigStruct = assign(
icon_hold_action: optional(actionConfigStruct),
icon_double_tap_action: optional(actionConfigStruct),
features: optional(array(any())),
+ features_position: optional(enums(["bottom", "inline"])),
})
);
@@ -109,8 +112,10 @@ export class HuiTileCardEditor
private _schema = memoizeOne(
(
+ localize: LocalizeFunc,
entityId: string | undefined,
hideState: boolean,
+ vertical: boolean,
displayActions: AdvancedActions[] = []
) =>
[
@@ -148,12 +153,6 @@ export class HuiTileCardEditor
boolean: {},
},
},
- {
- name: "vertical",
- selector: {
- boolean: {},
- },
- },
{
name: "hide_state",
selector: {
@@ -175,6 +174,43 @@ export class HuiTileCardEditor
},
] as const satisfies readonly HaFormSchema[])
: []),
+ {
+ name: "",
+ type: "grid",
+ schema: [
+ {
+ name: "content_layout",
+ required: true,
+ selector: {
+ select: {
+ mode: "dropdown",
+ options: ["horizontal", "vertical"].map((value) => ({
+ label: localize(
+ `ui.panel.lovelace.editor.card.tile.content_layout_options.${value}`
+ ),
+ value,
+ })),
+ },
+ },
+ },
+ {
+ name: "features_position",
+ required: true,
+ selector: {
+ select: {
+ mode: "dropdown",
+ options: ["bottom", "inline"].map((value) => ({
+ label: localize(
+ `ui.panel.lovelace.editor.card.tile.features_position_options.${value}`
+ ),
+ value,
+ disabled: vertical && value === "inline",
+ })),
+ },
+ },
+ },
+ ],
+ },
],
},
{
@@ -223,12 +259,22 @@ export class HuiTileCardEditor
const stateObj = entityId ? this.hass!.states[entityId] : undefined;
const schema = this._schema(
+ this.hass.localize,
entityId,
- this._config!.hide_state ?? false,
+ this._config.hide_state ?? false,
+ this._config.vertical ?? false,
this._displayActions
);
- const data = this._config;
+ const data = {
+ ...this._config,
+ content_layout: this._config.vertical ? "vertical" : "horizontal",
+ };
+
+ // Default features position to bottom and force it to bottom in vertical mode
+ if (!data.features_position || data.vertical) {
+ data.features_position = "bottom";
+ }
return html`