mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add layout options to cards and improve grid and sections defaults (#20001)
* Add grid options to cards * Fix the height of the card it's rows option is provided * Add variable * Adjust grid margin * Use layout options * Fix max width when only one column * Update card API
This commit is contained in:
parent
33a4258c06
commit
effefdbff1
@ -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;
|
||||
}
|
||||
|
@ -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) =>
|
||||
@ -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 {
|
||||
|
@ -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";
|
||||
|
||||
@ -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 {
|
||||
|
@ -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";
|
||||
|
||||
@ -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) {
|
||||
|
@ -3,4 +3,5 @@ import { object, string, any } from "superstruct";
|
||||
export const baseLovelaceCardConfig = object({
|
||||
type: string(),
|
||||
view_layout: any(),
|
||||
layout_options: any(),
|
||||
});
|
||||
|
@ -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,
|
||||
@ -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`
|
||||
@ -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;
|
||||
}
|
||||
@ -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 {
|
||||
@ -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;
|
||||
}
|
||||
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -234,11 +234,15 @@ 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;
|
||||
}
|
||||
@ -246,18 +250,13 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
.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
|
||||
@ -267,8 +266,9 @@ 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)
|
||||
@ -276,7 +276,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user