${repeat(
cardsConfig,
(cardConfig) => this._getKey(cardConfig),
diff --git a/src/panels/lovelace/sections/hui-section.ts b/src/panels/lovelace/sections/hui-section.ts
index 07dc7a78f8..c6cc4a4638 100644
--- a/src/panels/lovelace/sections/hui-section.ts
+++ b/src/panels/lovelace/sections/hui-section.ts
@@ -47,6 +47,8 @@ export class HuiSection extends ReactiveElement {
@property({ type: Number }) public viewIndex!: number;
+ @property({ type: Number }) public columnSpan!: number;
+
@state() private _cards: HuiCard[] = [];
private _layoutElementType?: string;
@@ -131,6 +133,9 @@ export class HuiSection extends ReactiveElement {
if (changedProperties.has("_cards")) {
this._layoutElement.cards = this._cards;
}
+ if (changedProperties.has("columnSpan")) {
+ this._layoutElement.columnSpan = this.columnSpan;
+ }
if (changedProperties.has("hass") || changedProperties.has("preview")) {
this._updateElement();
}
@@ -195,6 +200,7 @@ export class HuiSection extends ReactiveElement {
this._layoutElement!.lovelace = this.lovelace;
this._layoutElement!.index = this.index;
this._layoutElement!.viewIndex = this.viewIndex;
+ this._layoutElement!.columnSpan = this.columnSpan;
this._layoutElement!.cards = this._cards;
if (addLayoutElement) {
diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts
index 6fd5920428..243f99a25d 100644
--- a/src/panels/lovelace/views/hui-sections-view.ts
+++ b/src/panels/lovelace/views/hui-sections-view.ts
@@ -27,12 +27,15 @@ import { findLovelaceContainer } from "../editor/lovelace-path";
import { showEditSectionDialog } from "../editor/section-editor/show-edit-section-dialog";
import { HuiSection } from "../sections/hui-section";
import type { Lovelace } from "../types";
+import { listenMediaQuery } from "../../../common/dom/media_query";
export const DEFAULT_MAX_COLUMNS = 4;
const parsePx = (value: string) => parseInt(value.replace("px", ""));
-export const BREAKPOINTS: Record
= {
+type Breakpoints = Record;
+
+export const DEFAULT_BREAKPOINTS: Breakpoints = {
"0": 1,
"768": 2,
"1280": 3,
@@ -41,6 +44,16 @@ export const BREAKPOINTS: Record = {
"2560": 6,
};
+const buildMediaQueries = (breakpoints: Breakpoints) =>
+ Object.keys(breakpoints).map((breakpoint, index, array) => {
+ const nextBreakpoint = array[index + 1] as string | undefined;
+ let mediaQuery = `(min-width: ${breakpoint}px)`;
+ if (nextBreakpoint) {
+ mediaQuery += ` and (max-width: ${parseInt(nextBreakpoint) - 1}px)`;
+ }
+ return mediaQuery;
+ });
+
@customElement("hui-sections-view")
export class SectionsView extends LitElement implements LovelaceViewElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -85,8 +98,13 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
},
});
+ private _listeners: Array<() => void> = [];
+
+ @state() private _columns: number = 1;
+
public setConfig(config: LovelaceViewConfig): void {
this._config = config;
+ this._attachMediaQueriesListeners();
}
private _sectionConfigKeys = new WeakMap();
@@ -109,12 +127,32 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
this._computeSectionsCount();
};
+ private _attachMediaQueriesListeners() {
+ this._detachMediaQueriesListeners();
+ const breakpoints = this._config?.column_breakpoints || DEFAULT_BREAKPOINTS;
+ const mediaQueries = buildMediaQueries(breakpoints);
+ this._listeners = mediaQueries.map((mediaQuery, index) =>
+ listenMediaQuery(mediaQuery, (matches) => {
+ if (matches) {
+ this._columns = Object.values(breakpoints)[index];
+ }
+ })
+ );
+ }
+
+ private _detachMediaQueriesListeners() {
+ while (this._listeners.length) {
+ this._listeners.pop()!();
+ }
+ }
+
connectedCallback(): void {
super.connectedCallback();
this.addEventListener(
"section-visibility-changed",
this._sectionVisibilityChanged
);
+ this._attachMediaQueriesListeners();
}
disconnectedCallback(): void {
@@ -123,6 +161,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
"section-visibility-changed",
this._sectionVisibilityChanged
);
+ this._detachMediaQueriesListeners();
}
willUpdate(changedProperties: PropertyValues): void {
@@ -170,14 +209,12 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
(section) => this._getSectionKey(section),
(section, idx) => {
const sectionConfig = this._config?.sections?.[idx];
- const columnSpan = Math.min(
- sectionConfig?.column_span || 1,
- maxColumnCount
- );
+ const columnSpan = Math.min(sectionConfig?.column_span || 1);
const rowSpan = sectionConfig?.row_span || 1;
(section as any).itemPath = [idx];
+ (section as any).columnSpan = columnSpan;
return html`
* {
position: relative;
width: 100%;
}
.section {
- --section-column-span: min(var(--column-span, 1), var(--column-count));
border-radius: var(--ha-card-border-radius, 12px);
- grid-column: span var(--section-column-span);
+ grid-column: span var(--column-span);
grid-row: span var(--row-span);
}