From 2e7d97359794a12a0f291d5ed627a92d1fb003bc Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 13 Apr 2023 21:15:01 +0200 Subject: [PATCH] Use body scroll with ha-drawer (#16137) --- src/components/ha-drawer.ts | 10 +- src/components/ha-top-app-bar-fixed.ts | 28 +----- src/layouts/home-assistant-main.ts | 1 + .../ha-panel-developer-tools.ts | 24 +++-- src/panels/lovelace/hui-root.ts | 91 +++++++++---------- src/panels/lovelace/views/hui-masonry-view.ts | 3 +- src/panels/lovelace/views/hui-panel-view.ts | 3 +- src/panels/lovelace/views/hui-sidebar-view.ts | 3 +- 8 files changed, 75 insertions(+), 88 deletions(-) diff --git a/src/components/ha-drawer.ts b/src/components/ha-drawer.ts index 62930305d3..c55b56c118 100644 --- a/src/components/ha-drawer.ts +++ b/src/components/ha-drawer.ts @@ -63,13 +63,21 @@ export class HaDrawer extends DrawerBase { styles, css` .mdc-drawer { + position: fixed; top: 0; } .mdc-drawer.mdc-drawer--modal.mdc-drawer--open { z-index: 200; } .mdc-drawer-app-content { - transform: translateZ(0); + overflow: unset; + flex: none; + padding-left: var(--mdc-drawer-width); + padding-inline-start: var(--mdc-drawer-width); + padding-inline-end: initial; + direction: var(--direction); + width: 100%; + box-sizing: border-box; } `, ]; diff --git a/src/components/ha-top-app-bar-fixed.ts b/src/components/ha-top-app-bar-fixed.ts index d75c74f651..49501ac01b 100644 --- a/src/components/ha-top-app-bar-fixed.ts +++ b/src/components/ha-top-app-bar-fixed.ts @@ -1,43 +1,19 @@ import { TopAppBarFixedBase } from "@material/mwc-top-app-bar-fixed/mwc-top-app-bar-fixed-base"; import { styles } from "@material/mwc-top-app-bar/mwc-top-app-bar.css"; import { css } from "lit"; -import { customElement, property } from "lit/decorators"; - -let drawerContent: HTMLElement | undefined; +import { customElement } from "lit/decorators"; @customElement("ha-top-app-bar-fixed") export class HaTopAppBarFixed extends TopAppBarFixedBase { - private get _drawerContent() { - if (!drawerContent) { - drawerContent = document - .querySelector("home-assistant")! - .renderRoot.querySelector("home-assistant-main")! - .renderRoot.querySelector("ha-drawer")! - .renderRoot.querySelector(".mdc-drawer-app-content") as HTMLElement; - } - return drawerContent; - } - - @property({ type: Object }) - get scrollTarget() { - return this._scrollTarget || this._drawerContent || window; - } - - protected updateRootPosition() {} - static override styles = [ styles, css` - .mdc-top-app-bar { - position: sticky; - top: 0; - } .mdc-top-app-bar__row { height: var(--header-height); border-bottom: var(--app-header-border-bottom); } .mdc-top-app-bar--fixed-adjust { - padding-top: 0; + padding-top: var(--header-height); } .mdc-top-app-bar { --mdc-typography-headline6-font-weight: 400; diff --git a/src/layouts/home-assistant-main.ts b/src/layouts/home-assistant-main.ts index afd153947b..dcaa2b460f 100644 --- a/src/layouts/home-assistant-main.ts +++ b/src/layouts/home-assistant-main.ts @@ -176,6 +176,7 @@ export class HomeAssistantMain extends LitElement { /* remove the grey tap highlights in iOS on the fullscreen touch targets */ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); --mdc-drawer-width: 56px; + --mdc-top-app-bar-width: calc(100% - var(--mdc-drawer-width)); } :host([expanded]) { --mdc-drawer-width: calc(256px + env(safe-area-inset-left)); diff --git a/src/panels/developer-tools/ha-panel-developer-tools.ts b/src/panels/developer-tools/ha-panel-developer-tools.ts index 2dac2c0389..54c5666e9f 100644 --- a/src/panels/developer-tools/ha-panel-developer-tools.ts +++ b/src/panels/developer-tools/ha-panel-developer-tools.ts @@ -39,7 +39,7 @@ class PanelDeveloperTools extends LitElement { scrollable attr-for-selected="page-name" .selected=${page} - @iron-activate=${this.handlePageSelected} + @selected-changed=${this.handlePageSelected} > ${this.hass.localize("ui.panel.developer-tools.tabs.yaml.title")} @@ -76,11 +76,11 @@ class PanelDeveloperTools extends LitElement { } private handlePageSelected(ev) { - const newPage = ev.detail.item.getAttribute("page-name"); + const newPage = ev.detail.value; if (newPage !== this._page) { navigate(`/developer-tools/${newPage}`); } else { - scrollTo(0, 0); + scrollTo({ behavior: "smooth", top: 0 }); } } @@ -93,13 +93,18 @@ class PanelDeveloperTools extends LitElement { haStyle, css` :host { - display: block; - height: 100%; color: var(--primary-text-color); --paper-card-header-color: var(--primary-text-color); + display: flex; + min-height: 100vh; } .header { + position: fixed; + top: 0; + z-index: 4; background-color: var(--app-header-background-color); + width: var(--mdc-top-app-bar-width, 100%); + padding-top: env(safe-area-inset-top); color: var(--app-header-text-color, white); border-bottom: var(--app-header-border-bottom, none); } @@ -124,9 +129,12 @@ class PanelDeveloperTools extends LitElement { } developer-tools-router { display: block; - height: calc(100% - var(--header-height) - 48px); - overflow: auto; - overscroll-behavior: contain; + padding-top: calc( + var(--header-height) + 48px + env(safe-area-inset-top) + ); + padding-bottom: calc(env(safe-area-inset-bottom)); + flex: 1 1 100%; + max-width: 100%; } paper-tabs { margin-left: max(env(safe-area-inset-left), 24px); diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index a5fb2ded57..58825d76ab 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -26,13 +26,7 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { - customElement, - eventOptions, - property, - query, - state, -} from "lit/decorators"; +import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { ifDefined } from "lit/directives/if-defined"; import memoizeOne from "memoize-one"; @@ -93,8 +87,6 @@ class HUIRoot extends LitElement { @state() private _curView?: number | "hass-unused-entities"; - @query("#view", true) _view!: HTMLDivElement; - private _viewCache?: { [viewId: string]: HUIView }; private _debouncedConfigChanged: () => void; @@ -550,19 +542,14 @@ class HUIRoot extends LitElement { ` : ""} -
+
`; } - @eventOptions({ passive: true }) - private _viewScrolled(ev) { - this.toggleAttribute("scrolled", ev.currentTarget.scrollTop !== 0); - } + private _handleWindowScroll = () => { + this.toggleAttribute("scrolled", window.scrollY !== 0); + }; private _isVisible = (view: LovelaceViewConfig) => Boolean( @@ -573,7 +560,8 @@ class HUIRoot extends LitElement { view.visible.some((show) => show.user === this.hass!.user?.id)) ); - protected firstUpdated() { + protected firstUpdated(changedProps: PropertyValues) { + super.firstUpdated(changedProps); // Check for requested edit mode const searchParams = extractSearchParamsObject(); if (searchParams.edit === "1") { @@ -586,6 +574,14 @@ class HUIRoot extends LitElement { constructUrlCurrentPath(removeSearchParam("conversation")) ); } + window.addEventListener("scroll", this._handleWindowScroll, { + passive: true, + }); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + window.removeEventListener("scroll", this._handleWindowScroll); } protected updated(changedProperties: PropertyValues): void { @@ -628,6 +624,9 @@ class HUIRoot extends LitElement { } newSelectView = index; } + + // Will allow to override history scroll restoration when using back button + setTimeout(() => scrollTo({ behavior: "auto", top: 0 }), 1); } if (changedProperties.has("lovelace")) { @@ -817,13 +816,14 @@ class HUIRoot extends LitElement { } private _navigateToView(path: string | number, replace?: boolean) { - if (!this.lovelace!.editMode) { - navigate(`${this.route!.prefix}/${path}${location.search}`, { replace }); - return; + const url = this.lovelace!.editMode + ? `${this.route!.prefix}/${path}?${addSearchParam({ edit: "1" })}` + : `${this.route!.prefix}/${path}${location.search}`; + + const currentUrl = `${location.pathname}${location.search}`; + if (currentUrl !== url) { + navigate(url, { replace }); } - navigate(`${this.route!.prefix}/${path}?${addSearchParam({ edit: "1" })}`, { - replace, - }); } private _editView() { @@ -870,12 +870,12 @@ class HUIRoot extends LitElement { private _handleViewSelected(ev) { ev.preventDefault(); const viewIndex = ev.detail.selected as number; - if (viewIndex !== this._curView) { const path = this.config.views[viewIndex].path || viewIndex; this._navigateToView(path); + } else if (!this._editMode) { + scrollTo({ behavior: "smooth", top: 0 }); } - this._view.scrollTo(0, 0); } private _selectView(viewIndex: HUIRoot["_curView"], force: boolean): void { @@ -1048,34 +1048,31 @@ class HUIRoot extends LitElement { color: var(--error-color); } #view { - margin-top: calc(var(--header-height) + env(safe-area-inset-top)); - height: calc(100vh - var(--header-height) - env(safe-area-inset-top)); + position: relative; + display: flex; + background: var( + --lovelace-background, + var(--primary-background-color) + ); + padding-top: calc(var(--header-height) + env(safe-area-inset-top)); + min-height: 100vh; + box-sizing: border-box; + padding-left: env(safe-area-inset-left); + padding-right: env(safe-area-inset-right); + padding-bottom: env(safe-area-inset-bottom); + } + hui-view { + flex: 1 1 100%; + max-width: 100%; } /** * In edit mode we have the tab bar on a new line * */ .edit-mode #view { - height: calc( - 100vh - var(--header-height) - 48px - env(safe-area-inset-top) - ); - margin-top: calc( + padding-top: calc( var(--header-height) + 48px + env(safe-area-inset-top) ); } - hui-view { - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); - background: var( - --lovelace-background, - var(--primary-background-color) - ); - overflow: auto; - overscroll-behavior: contain; - width: 100%; - height: 100%; - transform: translateZ(0); - display: block; - } .hide-tab { display: none; } diff --git a/src/panels/lovelace/views/hui-masonry-view.ts b/src/panels/lovelace/views/hui-masonry-view.ts index 0ee9db908c..937f924b24 100644 --- a/src/panels/lovelace/views/hui-masonry-view.ts +++ b/src/panels/lovelace/views/hui-masonry-view.ts @@ -298,7 +298,6 @@ export class MasonryView extends LitElement implements LovelaceViewElement { :host { display: block; padding-top: 4px; - padding-bottom: env(safe-area-inset-bottom); } .badges { @@ -327,7 +326,7 @@ export class MasonryView extends LitElement implements LovelaceViewElement { } ha-fab { - position: absolute; + position: fixed; right: calc(16px + env(safe-area-inset-right)); bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 1; diff --git a/src/panels/lovelace/views/hui-panel-view.ts b/src/panels/lovelace/views/hui-panel-view.ts index 7b21e2a533..33ae765228 100644 --- a/src/panels/lovelace/views/hui-panel-view.ts +++ b/src/panels/lovelace/views/hui-panel-view.ts @@ -134,8 +134,7 @@ export class PanelView extends LitElement implements LovelaceViewElement { } ha-fab { - position: sticky; - float: right; + position: fixed; right: calc(16px + env(safe-area-inset-right)); bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 1; diff --git a/src/panels/lovelace/views/hui-sidebar-view.ts b/src/panels/lovelace/views/hui-sidebar-view.ts index 1233c00c94..6ed7cce4b4 100644 --- a/src/panels/lovelace/views/hui-sidebar-view.ts +++ b/src/panels/lovelace/views/hui-sidebar-view.ts @@ -196,7 +196,6 @@ export class SideBarView extends LitElement implements LovelaceViewElement { :host { display: block; padding-top: 4px; - padding-bottom: env(safe-area-inset-bottom); } .container { @@ -235,7 +234,7 @@ export class SideBarView extends LitElement implements LovelaceViewElement { } ha-fab { - position: absolute; + position: fixed; right: calc(16px + env(safe-area-inset-right)); bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 1;