From d7371ace6a7d9c511a8b4bf80f69c461f8b250c1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 1 Jul 2019 10:35:10 -0700 Subject: [PATCH] Sidebar improvements (#3325) * Do not contract sidebar when undocking sidebar * Do not hide text until fully contracted * Cancel hover expanding on tablets * Open notifications on the left * Set property before opening * Fix check for support scroll if needed --- src/components/ha-sidebar.ts | 49 ++++++- .../notifications/notification-drawer.js | 129 ++---------------- 2 files changed, 56 insertions(+), 122 deletions(-) diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 3a9a1ed348..06f51a8235 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -116,10 +116,13 @@ class HaSidebar extends LitElement { @property({ type: Boolean }) public alwaysExpand = false; @property({ type: Boolean, reflect: true }) public expanded = false; + @property({ type: Boolean, reflect: true }) public expandedWidth = false; @property() public _defaultPage?: string = localStorage.defaultPage || DEFAULT_PANEL; @property() private _externalConfig?: ExternalConfig; @property() private _notifications?: PersistentNotification[]; + private _expandTimeout?: number; + private _contractTimeout?: number; protected render() { const hass = this.hass; @@ -239,6 +242,7 @@ class HaSidebar extends LitElement { protected shouldUpdate(changedProps: PropertyValues): boolean { if ( changedProps.has("expanded") || + changedProps.has("expandedWidth") || changedProps.has("narrow") || changedProps.has("alwaysExpand") || changedProps.has("_externalConfig") || @@ -271,8 +275,17 @@ class HaSidebar extends LitElement { this._externalConfig = conf; }); } + // On tablets, there is no hover. So we receive click and mouseenter at the + // same time. In that case, we're going to cancel expanding, because it is + // going to require another tap outside the sidebar to trigger mouseleave + this.addEventListener("click", () => { + if (this._expandTimeout) { + clearTimeout(this._expandTimeout); + this._expandTimeout = undefined; + } + }); this.addEventListener("mouseenter", () => { - this.expanded = true; + this._expand(); }); this.addEventListener("mouseleave", () => { this._contract(); @@ -284,10 +297,11 @@ class HaSidebar extends LitElement { protected updated(changedProps) { super.updated(changedProps); - if (changedProps.has("alwaysExpand")) { - this.expanded = this.alwaysExpand; + if (changedProps.has("alwaysExpand") && this.alwaysExpand) { + this.expanded = true; + this.expandedWidth = true; } - if (SUPPORT_SCROLL_IF_NEEDED || !changedProps.has("hass")) { + if (!SUPPORT_SCROLL_IF_NEEDED || !changedProps.has("hass")) { return; } const oldHass = changedProps.get("hass") as HomeAssistant | undefined; @@ -299,8 +313,31 @@ class HaSidebar extends LitElement { } } + private _expand() { + // We debounce it one frame, because on tablets, the mouse-enter and + // click event fire at the same time. + this._expandTimeout = window.setTimeout(() => { + this.expanded = true; + this.expandedWidth = true; + }, 0); + if (this._contractTimeout) { + clearTimeout(this._contractTimeout); + this._contractTimeout = undefined; + } + } + private _contract() { - this.expanded = this.alwaysExpand || false; + if (this._expandTimeout) { + clearTimeout(this._expandTimeout); + this._expandTimeout = undefined; + } + if (this.alwaysExpand) { + return; + } + this.expandedWidth = false; + this._contractTimeout = window.setTimeout(() => { + this.expanded = this.alwaysExpand || false; + }, 400); } private _handleShowNotificationDrawer() { @@ -338,7 +375,7 @@ class HaSidebar extends LitElement { contain: strict; transition-delay: 0.2s; } - :host([expanded]) { + :host([expandedwidth]) { width: 256px; } diff --git a/src/dialogs/notifications/notification-drawer.js b/src/dialogs/notifications/notification-drawer.js index f86ce08a4e..b70ec0c496 100644 --- a/src/dialogs/notifications/notification-drawer.js +++ b/src/dialogs/notifications/notification-drawer.js @@ -1,3 +1,4 @@ +import "@polymer/app-layout/app-drawer/app-drawer"; import "@material/mwc-button"; import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/app-layout/app-toolbar/app-toolbar"; @@ -6,11 +7,10 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import "./notification-item"; -import "../../components/ha-paper-icon-button-next"; +import "../../components/ha-paper-icon-button-prev"; import { EventsMixin } from "../../mixins/events-mixin"; import LocalizeMixin from "../../mixins/localize-mixin"; -import { computeRTL } from "../../common/util/compute_rtl"; import { subscribeNotifications } from "../../data/persistent_notification"; import computeDomain from "../../common/entity/compute_domain"; /* @@ -23,86 +23,12 @@ export class HuiNotificationDrawer extends EventsMixin( static get template() { return html` -
-
+
[[localize('ui.notification_drawer.title')]]
- +
-
+ `; } static get properties() { return { hass: Object, - narrow: { - type: Boolean, - reflectToAttribute: true, - }, open: { type: Boolean, - notify: true, observer: "_openChanged", }, - hidden: { - type: Boolean, - value: true, - reflectToAttribute: true, - }, notifications: { type: Array, computed: "_computeNotifications(open, hass, _notificationsBackend)", @@ -168,11 +83,6 @@ export class HuiNotificationDrawer extends EventsMixin( type: Array, value: [], }, - rtl: { - type: Boolean, - reflectToAttribute: true, - computed: "_computeRTL(hass)", - }, }; } @@ -196,36 +106,20 @@ export class HuiNotificationDrawer extends EventsMixin( } _openChanged(open) { - clearTimeout(this._openTimer); if (open) { // Render closed then animate open - this.hidden = false; - this._openTimer = setTimeout(() => { - this.classList.add("open"); - }, 50); this._unsubNotifications = subscribeNotifications( this.hass.connection, (notifications) => { this._notificationsBackend = notifications; } ); - } else { - // Animate closed then hide - this.classList.remove("open"); - this._openTimer = setTimeout(() => { - this.hidden = true; - }, 250); - if (this._unsubNotifications) { - this._unsubNotifications(); - this._unsubNotifications = undefined; - } + } else if (this._unsubNotifications) { + this._unsubNotifications(); + this._unsubNotifications = undefined; } } - _computeRTL(hass) { - return computeRTL(hass); - } - _computeNotifications(open, hass, notificationsBackend) { if (!open) { return []; @@ -239,8 +133,11 @@ export class HuiNotificationDrawer extends EventsMixin( } showDialog({ narrow }) { - this.open = true; - this.narrow = narrow; + this.style.setProperty( + "--app-drawer-width", + narrow ? window.innerWidth + "px" : "500px" + ); + this.$.drawer.open(); } } customElements.define("notification-drawer", HuiNotificationDrawer);