diff --git a/src/data/lovelace/config/section.ts b/src/data/lovelace/config/section.ts index ad2c66e2aa..8708d4a013 100644 --- a/src/data/lovelace/config/section.ts +++ b/src/data/lovelace/config/section.ts @@ -17,6 +17,10 @@ export interface LovelaceSectionConfig extends LovelaceBaseSectionConfig { cards?: LovelaceCardConfig[]; } +export interface LovelaceGridSectionConfig extends LovelaceSectionConfig { + grid_base?: number; +} + export interface LovelaceStrategySectionConfig extends LovelaceBaseSectionConfig { strategy: LovelaceStrategyConfig; diff --git a/src/panels/lovelace/editor/card-editor/hui-card-element-editor.ts b/src/panels/lovelace/editor/card-editor/hui-card-element-editor.ts index 51804864af..a9818b1ad7 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-element-editor.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-element-editor.ts @@ -3,12 +3,15 @@ import "@material/mwc-tab/mwc-tab"; import { CSSResultGroup, TemplateResult, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; +import { + LovelaceGridSectionConfig, + LovelaceSectionConfig, +} from "../../../../data/lovelace/config/section"; import { getCardElementClass } from "../../create-element/create-card-element"; import type { LovelaceCardEditor, LovelaceConfigForm } from "../../types"; import { HuiTypedElementEditor } from "../hui-typed-element-editor"; import "./hui-card-layout-editor"; import "./hui-card-visibility-editor"; -import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section"; const tabs = ["config", "visibility", "layout"] as const; @@ -59,7 +62,7 @@ export class HuiCardElementEditor extends HuiTypedElementEditor `; diff --git a/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts b/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts index 6ee81aba24..188356b9fa 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-layout-editor.ts @@ -19,7 +19,10 @@ import "../../../../components/ha-switch"; import "../../../../components/ha-yaml-editor"; import type { HaYamlEditor } from "../../../../components/ha-yaml-editor"; import { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; -import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section"; +import { + LovelaceGridSectionConfig, + LovelaceSectionConfig, +} from "../../../../data/lovelace/config/section"; import { haStyle } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; import { HuiCard } from "../../cards/hui-card"; @@ -27,6 +30,7 @@ import { CardGridSize, computeCardGridSize, } from "../../common/compute-card-grid-size"; +import { DEFAULT_GRID_BASE } from "../../sections/hui-grid-section"; import { LovelaceLayoutOptions } from "../../types"; @customElement("hui-card-layout-editor") @@ -72,7 +76,10 @@ export class HuiCardLayoutEditor extends LitElement { const value = this._computeCardGridSize(options); - const totalColumns = (this.sectionConfig.column_span ?? 1) * 4; + const totalColumns = + (this.sectionConfig.column_span ?? 1) * + ((this.sectionConfig as LovelaceGridSectionConfig).grid_base || + DEFAULT_GRID_BASE); return html`
diff --git a/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts b/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts index dcc922c3e8..42d0b56fcd 100644 --- a/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts +++ b/src/panels/lovelace/editor/section-editor/hui-section-settings-editor.ts @@ -1,4 +1,4 @@ -import { LitElement, html } from "lit"; +import { html, LitElement } from "lit"; import { customElement, property } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; @@ -6,12 +6,21 @@ import { HaFormSchema, SchemaUnion, } from "../../../../components/ha-form/types"; -import { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section"; +import { + isStrategySection, + LovelaceGridSectionConfig, + LovelaceSectionRawConfig, +} from "../../../../data/lovelace/config/section"; import { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import { HomeAssistant } from "../../../../types"; +import { LocalizeFunc } from "../../../../common/translations/localize"; +import { DEFAULT_GRID_BASE } from "../../sections/hui-grid-section"; + +type GridDensity = "default" | "dense" | "custom"; type SettingsData = { column_span?: number; + grid_density?: GridDensity; }; @customElement("hui-section-settings-editor") @@ -23,27 +32,89 @@ export class HuiDialogEditSection extends LitElement { @property({ attribute: false }) public viewConfig!: LovelaceViewConfig; private _schema = memoizeOne( - (maxColumns: number) => + ( + maxColumns: number, + localize: LocalizeFunc, + type?: string | undefined, + columnDensity?: GridDensity, + columnBase?: number + ) => [ { - name: "column_span", - selector: { - number: { - min: 1, - max: maxColumns, - slider_ticks: true, - }, - }, + name: "title", + selector: { text: {} }, }, + ...(type === "grid" + ? ([ + { + name: "grid_density", + default: "default", + selector: { + select: { + mode: "list", + options: [ + { + label: localize( + `ui.panel.lovelace.editor.edit_section.settings.grid_density_options.default`, + { count: 4 } + ), + value: "default", + }, + { + label: localize( + `ui.panel.lovelace.editor.edit_section.settings.grid_density_options.dense`, + { count: 6 } + ), + value: "dense", + }, + ...(columnDensity === "custom" && columnBase + ? [ + { + label: localize( + `ui.panel.lovelace.editor.edit_section.settings.grid_density_options.custom`, + { count: columnBase } + ), + value: "custom", + }, + ] + : []), + ], + }, + }, + }, + ] as const satisfies readonly HaFormSchema[]) + : []), ] as const satisfies HaFormSchema[] ); + private _isGridSectionConfig( + config: LovelaceSectionRawConfig + ): config is LovelaceGridSectionConfig { + return !isStrategySection(config) && config.type === "grid"; + } + render() { + const gridBase = this._isGridSectionConfig(this.config) + ? this.config.grid_base || DEFAULT_GRID_BASE + : undefined; + + const columnDensity = + gridBase === 6 ? "dense" : gridBase === 4 ? "default" : "custom"; + const data: SettingsData = { column_span: this.config.column_span || 1, + grid_density: columnDensity, }; - const schema = this._schema(this.viewConfig.max_columns || 4); + const type = "type" in this.config ? this.config.type : undefined; + + const schema = this._schema( + this.viewConfig.max_columns || 4, + this.hass.localize, + type, + columnDensity, + gridBase + ); return html` -
+
${repeat( cardsConfig, (cardConfig) => this._getKey(cardConfig), @@ -165,7 +172,6 @@ export class GridSection extends LitElement implements LovelaceSectionElement { haStyle, css` :host { - --base-column-count: 4; --row-gap: var(--ha-section-grid-row-gap, 8px); --column-gap: var(--ha-section-grid-column-gap, 8px); --row-height: var(--ha-section-grid-row-height, 56px); @@ -175,7 +181,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement { } .container { --grid-column-count: calc( - var(--base-column-count) * var(--column-span, 1) + var(--column-count, 4) * var(--column-span, 1) ); display: grid; grid-template-columns: repeat( diff --git a/src/translations/en.json b/src/translations/en.json index cc08d701a6..4f1f057c18 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5714,7 +5714,13 @@ "title": "Title", "title_helper": "The title will appear at the top of section. Leave empty to hide the title.", "column_span": "Width", - "column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)" + "column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)", + "grid_density": "Grid density", + "grid_density_options": { + "default": "Default ({count} columns)", + "dense": "Dense ({count} columns)", + "custom": "Custom ({count} {count, plural,\n one {column}\n other {columns}\n})" + } }, "visibility": { "explanation": "The section will be shown when ALL conditions below are fulfilled. If no conditions are set, the section will always be shown."