Add view top margin option for section view (#24386)

This commit is contained in:
Paul Bottein 2025-02-25 15:06:13 +01:00 committed by GitHub
parent 50ac60b35e
commit 8f06e70a11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 116 additions and 92 deletions

View File

@ -45,6 +45,7 @@ export interface LovelaceBaseViewConfig {
// Only used for section view, it should move to a section view config type when the views will have dedicated editor. // Only used for section view, it should move to a section view config type when the views will have dedicated editor.
max_columns?: number; max_columns?: number;
dense_section_placement?: boolean; dense_section_placement?: boolean;
top_margin?: boolean;
} }
export interface LovelaceViewConfig extends LovelaceBaseViewConfig { export interface LovelaceViewConfig extends LovelaceBaseViewConfig {

View File

@ -100,6 +100,12 @@ export class HuiViewEditor extends LitElement {
boolean: {}, boolean: {},
}, },
}, },
{
name: "top_margin",
selector: {
boolean: {},
},
},
], ],
}, },
] as const satisfies HaFormSchema[]) ] as const satisfies HaFormSchema[])
@ -149,6 +155,7 @@ export class HuiViewEditor extends LitElement {
if (config.type !== SECTIONS_VIEW_LAYOUT) { if (config.type !== SECTIONS_VIEW_LAYOUT) {
delete config.max_columns; delete config.max_columns;
delete config.dense_section_placement; delete config.dense_section_placement;
delete config.top_margin;
} }
if ( if (
@ -174,6 +181,7 @@ export class HuiViewEditor extends LitElement {
case "subview": case "subview":
case "max_columns": case "max_columns":
case "dense_section_placement": case "dense_section_placement":
case "top_margin":
case "section_specifics": case "section_specifics":
return this.hass.localize( return this.hass.localize(
`ui.panel.lovelace.editor.edit_view.${schema.name}` `ui.panel.lovelace.editor.edit_view.${schema.name}`
@ -191,6 +199,7 @@ export class HuiViewEditor extends LitElement {
switch (schema.name) { switch (schema.name) {
case "subview": case "subview":
case "dense_section_placement": case "dense_section_placement":
case "top_margin":
return this.hass.localize( return this.hass.localize(
`ui.panel.lovelace.editor.edit_view.${schema.name}_helper` `ui.panel.lovelace.editor.edit_view.${schema.name}_helper`
); );

View File

@ -154,44 +154,49 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
const maxColumnCount = this._columnsController.value ?? 1; const maxColumnCount = this._columnsController.value ?? 1;
return html` return html`
<hui-view-header <div
.hass=${this.hass} class="wrapper ${classMap({
.badges=${this.badges} "top-margin": Boolean(this._config?.top_margin),
.lovelace=${this.lovelace} })}"
.viewIndex=${this.index}
.config=${this._config?.header}
style=${styleMap({
"--max-column-count": maxColumnCount,
})}
></hui-view-header>
<ha-sortable
.disabled=${!editMode}
@item-moved=${this._sectionMoved}
group="section"
handle-selector=".handle"
draggable-selector=".section"
.rollback=${false}
> >
<div <hui-view-header
class="container ${classMap({ .hass=${this.hass}
dense: Boolean(this._config?.dense_section_placement), .badges=${this.badges}
})}" .lovelace=${this.lovelace}
.viewIndex=${this.index}
.config=${this._config?.header}
style=${styleMap({ style=${styleMap({
"--total-section-count": totalSectionCount,
"--max-column-count": maxColumnCount, "--max-column-count": maxColumnCount,
})} })}
></hui-view-header>
<ha-sortable
.disabled=${!editMode}
@item-moved=${this._sectionMoved}
group="section"
handle-selector=".handle"
draggable-selector=".section"
.rollback=${false}
> >
${repeat( <div
sections, class="container ${classMap({
(section) => this._getSectionKey(section), dense: Boolean(this._config?.dense_section_placement),
(section, idx) => { })}"
const columnSpan = Math.min( style=${styleMap({
section.config.column_span || 1, "--total-section-count": totalSectionCount,
maxColumnCount "--max-column-count": maxColumnCount,
); })}
const rowSpan = section.config.row_span || 1; >
${repeat(
sections,
(section) => this._getSectionKey(section),
(section, idx) => {
const columnSpan = Math.min(
section.config.column_span || 1,
maxColumnCount
);
const rowSpan = section.config.row_span || 1;
return html` return html`
<div <div
class="section" class="section"
style=${styleMap({ style=${styleMap({
@ -238,72 +243,73 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
</div> </div>
</div> </div>
`; `;
} }
)} )}
${editMode ${editMode
? html` ? html`
<ha-sortable <ha-sortable
group="card" group="card"
@item-added=${this._handleCardAdded} @item-added=${this._handleCardAdded}
draggable-selector=".card" draggable-selector=".card"
.rollback=${false} .rollback=${false}
> >
<div class="create-section-container"> <div class="create-section-container">
<div class="drop-helper" aria-hidden="true"> <div class="drop-helper" aria-hidden="true">
<p> <p>
${this.hass.localize(
"ui.panel.lovelace.editor.section.drop_card_create_section"
)}
</p>
</div>
<button
class="create-section"
@click=${this._createSection}
aria-label=${this.hass.localize(
"ui.panel.lovelace.editor.section.create_section"
)}
.title=${this.hass.localize(
"ui.panel.lovelace.editor.section.create_section"
)}
>
<ha-ripple></ha-ripple>
<ha-svg-icon .path=${mdiViewGridPlus}></ha-svg-icon>
</button>
</div>
</ha-sortable>
`
: nothing}
${editMode && this._config?.cards?.length
? html`
<div class="section imported-cards">
<div class="imported-card-header">
<p class="title">
<ha-svg-icon .path=${mdiEyeOff}></ha-svg-icon>
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.editor.section.drop_card_create_section" "ui.panel.lovelace.editor.section.imported_cards_title"
)}
</p>
<p class="subtitle">
${this.hass.localize(
"ui.panel.lovelace.editor.section.imported_cards_description"
)} )}
</p> </p>
</div> </div>
<button <hui-section
class="create-section" .lovelace=${this.lovelace}
@click=${this._createSection} .hass=${this.hass}
aria-label=${this.hass.localize( .config=${this._importedCardSectionConfig(
"ui.panel.lovelace.editor.section.create_section" this._config.cards
)} )}
.title=${this.hass.localize( .viewIndex=${this.index}
"ui.panel.lovelace.editor.section.create_section" preview
)} import-only
> ></hui-section>
<ha-ripple></ha-ripple>
<ha-svg-icon .path=${mdiViewGridPlus}></ha-svg-icon>
</button>
</div> </div>
</ha-sortable> `
` : nothing}
: nothing} </div>
${editMode && this._config?.cards?.length </ha-sortable>
? html` </div>
<div class="section imported-cards">
<div class="imported-card-header">
<p class="title">
<ha-svg-icon .path=${mdiEyeOff}></ha-svg-icon>
${this.hass.localize(
"ui.panel.lovelace.editor.section.imported_cards_title"
)}
</p>
<p class="subtitle">
${this.hass.localize(
"ui.panel.lovelace.editor.section.imported_cards_description"
)}
</p>
</div>
<hui-section
.lovelace=${this.lovelace}
.hass=${this.hass}
.config=${this._importedCardSectionConfig(
this._config.cards
)}
.viewIndex=${this.index}
preview
import-only
></hui-section>
</div>
`
: nothing}
</div>
</ha-sortable>
`; `;
} }
@ -429,6 +435,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
--column-gap: var(--ha-view-sections-column-gap, 32px); --column-gap: var(--ha-view-sections-column-gap, 32px);
--column-max-width: var(--ha-view-sections-column-max-width, 500px); --column-max-width: var(--ha-view-sections-column-max-width, 500px);
--column-min-width: var(--ha-view-sections-column-min-width, 320px); --column-min-width: var(--ha-view-sections-column-min-width, 320px);
--top-margin: var(--ha-view-sections-extra-top-margin, 80px);
display: block; display: block;
} }
@ -438,6 +445,11 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
} }
} }
.wrapper.top-margin {
display: block;
margin-top: var(--top-margin);
}
.container > * { .container > * {
position: relative; position: relative;
width: 100%; width: 100%;

View File

@ -6569,6 +6569,8 @@
"section_specifics": "Sections view specific settings", "section_specifics": "Sections view specific settings",
"dense_section_placement": "Dense section placement", "dense_section_placement": "Dense section placement",
"dense_section_placement_helper": "Will try to fill gaps with sections that fit the gap. This may make section placement less predictable.", "dense_section_placement_helper": "Will try to fill gaps with sections that fit the gap. This may make section placement less predictable.",
"top_margin": "Add additional space above",
"top_margin_helper": "Helps reveal more of the background",
"subview_helper": "Subviews don't appear in tabs and have a back button.", "subview_helper": "Subviews don't appear in tabs and have a back button.",
"edit_ui": "Edit in visual editor", "edit_ui": "Edit in visual editor",
"edit_yaml": "Edit in YAML", "edit_yaml": "Edit in YAML",