Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add layout options to cards and improve grid and sections defaults #20001

Merged
merged 7 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/data/lovelace/config/card.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { LovelaceLayoutOptions } from "../../../panels/lovelace/types";

export interface LovelaceCardConfig {
index?: number;
view_index?: number;
view_layout?: any;
layout_options?: LovelaceLayoutOptions;
type: string;
[key: string]: any;
}
12 changes: 8 additions & 4 deletions src/panels/lovelace/cards/hui-button-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entities";
import { hasAction } from "../common/has-action";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import {
LovelaceCard,
LovelaceCardEditor,
LovelaceLayoutOptions,
} from "../types";
import { ButtonCardConfig } from "./types";

export const getEntityDefaultButtonAction = (entityId?: string) =>
Expand Down Expand Up @@ -143,14 +147,14 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
);
}

public getGridSize(): [number, number] {
public getLayoutOptions(): LovelaceLayoutOptions {
if (
this._config?.show_icon &&
(this._config?.show_name || this._config?.show_state)
) {
return [2, 2];
return { grid_rows: 2, grid_columns: 2 };
}
return [1, 1];
return { grid_rows: 1, grid_columns: 1 };
}

public setConfig(config: ButtonCardConfig): void {
Expand Down
11 changes: 7 additions & 4 deletions src/panels/lovelace/cards/hui-sensor-card.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { css, CSSResultGroup } from "lit";
import { HassEntity } from "home-assistant-js-websocket/dist/types";
import { css, CSSResultGroup } from "lit";
import { customElement } from "lit/decorators";
import { computeDomain } from "../../../common/entity/compute_domain";
import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities";
import { GraphHeaderFooterConfig } from "../header-footer/types";
import { LovelaceCardEditor } from "../types";
import { LovelaceCardEditor, LovelaceLayoutOptions } from "../types";
import { HuiEntityCard } from "./hui-entity-card";
import { EntityCardConfig, SensorCardConfig } from "./types";

Expand Down Expand Up @@ -72,8 +72,11 @@ class HuiSensorCard extends HuiEntityCard {
super.setConfig(entityCardConfig);
}

public getGridSize(): [number, number] {
return [2, 2];
public getLayoutOptions(): LovelaceLayoutOptions {
return {
grid_columns: 2,
grid_rows: 2,
};
}

static get styles(): CSSResultGroup {
Expand Down
20 changes: 13 additions & 7 deletions src/panels/lovelace/cards/hui-tile-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ import { findEntities } from "../common/find-entities";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import "../components/hui-timestamp-display";
import type { LovelaceCard, LovelaceCardEditor } from "../types";
import type {
LovelaceCard,
LovelaceCardEditor,
LovelaceLayoutOptions,
} from "../types";
import { renderTileBadge } from "./tile/badges/tile-badge";
import type { ThermostatCardConfig, TileCardConfig } from "./types";

Expand Down Expand Up @@ -124,16 +128,18 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
);
}

public getGridSize(): [number, number] {
const width = 2;
let height = 1;
public getLayoutOptions(): LovelaceLayoutOptions {
const options = {
grid_columns: 2,
grid_rows: 1,
};
if (this._config?.features?.length) {
height += Math.ceil((this._config.features.length * 2) / 3);
options.grid_rows += Math.ceil((this._config.features.length * 2) / 3);
}
if (this._config?.vertical) {
height++;
options.grid_rows++;
}
return [width, height];
return options;
}

private _handleAction(ev: ActionHandlerEvent) {
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/editor/structs/base-card-struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { object, string, any } from "superstruct";
export const baseLovelaceCardConfig = object({
type: string(),
view_layout: any(),
layout_options: any(),
});
42 changes: 32 additions & 10 deletions src/panels/lovelace/sections/hui-grid-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type { HomeAssistant } from "../../../types";
import { HuiErrorCard } from "../cards/hui-error-card";
import "../components/hui-card-edit-mode";
import { moveCard } from "../editor/config-util";
import type { Lovelace, LovelaceCard } from "../types";
import type { Lovelace, LovelaceCard, LovelaceLayoutOptions } from "../types";

const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
delay: 100,
Expand Down Expand Up @@ -97,14 +97,26 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
const card = this.cards![idx];
(card as any).editMode = editMode;
(card as any).lovelace = this.lovelace;
const size = card && (card as any).getGridSize?.();

const configOptions = _cardConfig.layout_options;
const cardOptions = (card as any)?.getLayoutOptions?.() as
| LovelaceLayoutOptions
| undefined;

const options = {
...cardOptions,
...configOptions,
} as LovelaceLayoutOptions;

return html`
<div
class="card"
style=${styleMap({
"--column-size": size?.[0],
"--row-size": size?.[1],
"--column-size": options.grid_columns,
"--row-size": options.grid_rows,
})}
class="card ${classMap({
"fit-rows": typeof options?.grid_rows === "number",
})}"
>
${editMode
? html`
Expand Down Expand Up @@ -171,16 +183,18 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
haStyle,
css`
:host {
--grid-gap: 8px;
--grid-row-height: 66px;
display: flex;
flex-direction: column;
gap: 8px;
gap: var(--grid-gap);
}
.container {
--column-count: 4;
display: grid;
grid-template-columns: repeat(var(--column-count), minmax(0, 1fr));
grid-auto-rows: minmax(66px, auto);
gap: 8px;
grid-auto-rows: minmax(var(--grid-row-height), auto);
gap: var(--grid-gap);
padding: 0;
margin: 0 auto;
}
Expand All @@ -189,7 +203,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
padding: 8px;
border-radius: var(--ha-card-border-radius, 12px);
border: 2px dashed var(--divider-color);
min-height: 66px;
min-height: var(var(--grid-row-height));
}

.title {
Expand All @@ -216,6 +230,14 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
grid-column: span var(--column-size, 4);
}

.card.fit-rows {
height: calc(
(var(--row-size, 1) * (var(--grid-row-height) + var(--grid-gap))) - var(
--grid-gap
)
);
}

.card:has(> *) {
display: block;
}
Expand All @@ -232,7 +254,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
cursor: pointer;
border-radius: var(--ha-card-border-radius, 12px);
border: 2px dashed var(--primary-color);
height: 66px;
height: var(--grid-row-height);
order: 1;
}
.add:focus {
Expand Down
7 changes: 6 additions & 1 deletion src/panels/lovelace/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ export interface LovelaceBadge extends HTMLElement {
setConfig(config: LovelaceBadgeConfig): void;
}

export type LovelaceLayoutOptions = {
grid_columns?: number;
grid_rows?: number;
};

export interface LovelaceCard extends HTMLElement {
hass?: HomeAssistant;
isPanel?: boolean;
editMode?: boolean;
getCardSize(): number | Promise<number>;
getGridSize?(): [number, number];
getLayoutOptions?(): LovelaceLayoutOptions;
setConfig(config: LovelaceCardConfig): void;
}

Expand Down
22 changes: 11 additions & 11 deletions src/panels/lovelace/views/hui-sections-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,30 +234,29 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
static get styles(): CSSResultGroup {
return css`
:host {
--grid-gap: 32px;
--grid-max-section-count: 4;
--grid-section-min-width: 320px;
--grid-section-max-width: 500px;
display: block;
}

.badges {
margin: 12px 8px 16px 8px;
margin: 12px 8px 4px 8px;
font-size: 85%;
text-align: center;
}

.section {
position: relative;
border-radius: var(--ha-card-border-radius, 12px);
max-width: var(--grid-section-max-width);
width: 100%;
}

.container {
/* Inputs */
--grid-gap: 32px;
--grid-max-section-count: 4;
--grid-section-min-width: 320px;
--grid-section-max-width: 500px;

/* Calculated */
--max-count: min(var(--section-count), var(--grid-max-section-count));
--grid-max-width: min(
--max-width: min(
calc(
(var(--max-count) + 1) * var(--grid-section-min-width) +
(var(--max-count) + 2) * var(--grid-gap) - 1px
Expand All @@ -267,16 +266,17 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
(var(--max-count) + 1) * var(--grid-gap)
)
);

display: grid;
align-items: start;
justify-items: center;
grid-template-columns: repeat(
auto-fit,
minmax(min(var(--grid-section-min-width), 100%), 1fr)
);
grid-gap: 8px var(--grid-gap);
padding: 8px var(--grid-gap);
box-sizing: border-box;
max-width: var(--grid-max-width);
max-width: var(--max-width);
margin: 0 auto;
}

Expand Down