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
This commit is contained in:
Paulus Schoutsen 2019-07-01 10:35:10 -07:00 committed by GitHub
parent 8c1aff7505
commit d7371ace6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 122 deletions

View File

@ -116,10 +116,13 @@ class HaSidebar extends LitElement {
@property({ type: Boolean }) public alwaysExpand = false; @property({ type: Boolean }) public alwaysExpand = false;
@property({ type: Boolean, reflect: true }) public expanded = false; @property({ type: Boolean, reflect: true }) public expanded = false;
@property({ type: Boolean, reflect: true }) public expandedWidth = false;
@property() public _defaultPage?: string = @property() public _defaultPage?: string =
localStorage.defaultPage || DEFAULT_PANEL; localStorage.defaultPage || DEFAULT_PANEL;
@property() private _externalConfig?: ExternalConfig; @property() private _externalConfig?: ExternalConfig;
@property() private _notifications?: PersistentNotification[]; @property() private _notifications?: PersistentNotification[];
private _expandTimeout?: number;
private _contractTimeout?: number;
protected render() { protected render() {
const hass = this.hass; const hass = this.hass;
@ -239,6 +242,7 @@ class HaSidebar extends LitElement {
protected shouldUpdate(changedProps: PropertyValues): boolean { protected shouldUpdate(changedProps: PropertyValues): boolean {
if ( if (
changedProps.has("expanded") || changedProps.has("expanded") ||
changedProps.has("expandedWidth") ||
changedProps.has("narrow") || changedProps.has("narrow") ||
changedProps.has("alwaysExpand") || changedProps.has("alwaysExpand") ||
changedProps.has("_externalConfig") || changedProps.has("_externalConfig") ||
@ -271,8 +275,17 @@ class HaSidebar extends LitElement {
this._externalConfig = conf; 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.addEventListener("mouseenter", () => {
this.expanded = true; this._expand();
}); });
this.addEventListener("mouseleave", () => { this.addEventListener("mouseleave", () => {
this._contract(); this._contract();
@ -284,10 +297,11 @@ class HaSidebar extends LitElement {
protected updated(changedProps) { protected updated(changedProps) {
super.updated(changedProps); super.updated(changedProps);
if (changedProps.has("alwaysExpand")) { if (changedProps.has("alwaysExpand") && this.alwaysExpand) {
this.expanded = 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; return;
} }
const oldHass = changedProps.get("hass") as HomeAssistant | undefined; 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() { 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() { private _handleShowNotificationDrawer() {
@ -338,7 +375,7 @@ class HaSidebar extends LitElement {
contain: strict; contain: strict;
transition-delay: 0.2s; transition-delay: 0.2s;
} }
:host([expanded]) { :host([expandedwidth]) {
width: 256px; width: 256px;
} }

View File

@ -1,3 +1,4 @@
import "@polymer/app-layout/app-drawer/app-drawer";
import "@material/mwc-button"; import "@material/mwc-button";
import "@polymer/paper-icon-button/paper-icon-button"; import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/app-layout/app-toolbar/app-toolbar"; 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 { PolymerElement } from "@polymer/polymer/polymer-element";
import "./notification-item"; import "./notification-item";
import "../../components/ha-paper-icon-button-next"; import "../../components/ha-paper-icon-button-prev";
import { EventsMixin } from "../../mixins/events-mixin"; import { EventsMixin } from "../../mixins/events-mixin";
import LocalizeMixin from "../../mixins/localize-mixin"; import LocalizeMixin from "../../mixins/localize-mixin";
import { computeRTL } from "../../common/util/compute_rtl";
import { subscribeNotifications } from "../../data/persistent_notification"; import { subscribeNotifications } from "../../data/persistent_notification";
import computeDomain from "../../common/entity/compute_domain"; import computeDomain from "../../common/entity/compute_domain";
/* /*
@ -23,86 +23,12 @@ export class HuiNotificationDrawer extends EventsMixin(
static get template() { static get template() {
return html` return html`
<style include="paper-material-styles"> <style include="paper-material-styles">
:host {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
:host([hidden]) {
display: none;
}
.container {
align-items: stretch;
background: var(--sidebar-background-color, var(--primary-background-color));
bottom: 0;
box-shadow: var(--paper-material-elevation-1_-_box-shadow);
display: flex;
flex-direction: column;
overflow-y: hidden;
position: fixed;
top: 0;
transition: right .2s ease-in;
width: 500px;
z-index: 10;
}
:host([rtl]) .container {
transition: left .2s ease-in !important;
}
:host(:not(narrow)) .container {
right: -500px;
}
:host([rtl]:not(narrow)) .container {
left: -500px;
}
:host([narrow]) .container {
right: -100%;
width: 100%;
}
:host([rtl][narrow]) .container {
left: -100%;
width: 100%;
}
:host(.open) .container,
:host(.open[narrow]) .container {
right: 0;
}
:host([rtl].open) .container,
:host([rtl].open[narrow]) .container {
left: 0;
}
app-toolbar { app-toolbar {
color: var(--primary-text-color); color: var(--primary-text-color);
border-bottom: 1px solid var(--divider-color); border-bottom: 1px solid var(--divider-color);
background-color: var(--primary-background-color); background-color: var(--primary-background-color);
min-height: 64px; min-height: 64px;
width: calc(100% - 32px); width: calc(100% - 32px);
z-index: 11;
}
.overlay {
display: none;
}
:host(.open) .overlay {
bottom: 0;
display: block;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 5;
} }
.notifications { .notifications {
@ -119,11 +45,10 @@ export class HuiNotificationDrawer extends EventsMixin(
text-align: center; text-align: center;
} }
</style> </style>
<div class="overlay" on-click="_closeDrawer"></div> <app-drawer id='drawer' opened="{{open}}">
<div class="container">
<app-toolbar> <app-toolbar>
<div main-title>[[localize('ui.notification_drawer.title')]]</div> <div main-title>[[localize('ui.notification_drawer.title')]]</div>
<ha-paper-icon-button-next on-click="_closeDrawer"></paper-icon-button> <ha-paper-icon-button-prev on-click="_closeDrawer"></paper-icon-button>
</app-toolbar> </app-toolbar>
<div class="notifications"> <div class="notifications">
<template is="dom-if" if="[[!_empty(notifications)]]"> <template is="dom-if" if="[[!_empty(notifications)]]">
@ -139,27 +64,17 @@ export class HuiNotificationDrawer extends EventsMixin(
<div class="empty">[[localize('ui.notification_drawer.empty')]]<div> <div class="empty">[[localize('ui.notification_drawer.empty')]]<div>
</template> </template>
</div> </div>
</div> </app-drawer>
`; `;
} }
static get properties() { static get properties() {
return { return {
hass: Object, hass: Object,
narrow: {
type: Boolean,
reflectToAttribute: true,
},
open: { open: {
type: Boolean, type: Boolean,
notify: true,
observer: "_openChanged", observer: "_openChanged",
}, },
hidden: {
type: Boolean,
value: true,
reflectToAttribute: true,
},
notifications: { notifications: {
type: Array, type: Array,
computed: "_computeNotifications(open, hass, _notificationsBackend)", computed: "_computeNotifications(open, hass, _notificationsBackend)",
@ -168,11 +83,6 @@ export class HuiNotificationDrawer extends EventsMixin(
type: Array, type: Array,
value: [], value: [],
}, },
rtl: {
type: Boolean,
reflectToAttribute: true,
computed: "_computeRTL(hass)",
},
}; };
} }
@ -196,36 +106,20 @@ export class HuiNotificationDrawer extends EventsMixin(
} }
_openChanged(open) { _openChanged(open) {
clearTimeout(this._openTimer);
if (open) { if (open) {
// Render closed then animate open // Render closed then animate open
this.hidden = false;
this._openTimer = setTimeout(() => {
this.classList.add("open");
}, 50);
this._unsubNotifications = subscribeNotifications( this._unsubNotifications = subscribeNotifications(
this.hass.connection, this.hass.connection,
(notifications) => { (notifications) => {
this._notificationsBackend = notifications; this._notificationsBackend = notifications;
} }
); );
} else { } else if (this._unsubNotifications) {
// Animate closed then hide this._unsubNotifications();
this.classList.remove("open"); this._unsubNotifications = undefined;
this._openTimer = setTimeout(() => {
this.hidden = true;
}, 250);
if (this._unsubNotifications) {
this._unsubNotifications();
this._unsubNotifications = undefined;
}
} }
} }
_computeRTL(hass) {
return computeRTL(hass);
}
_computeNotifications(open, hass, notificationsBackend) { _computeNotifications(open, hass, notificationsBackend) {
if (!open) { if (!open) {
return []; return [];
@ -239,8 +133,11 @@ export class HuiNotificationDrawer extends EventsMixin(
} }
showDialog({ narrow }) { showDialog({ narrow }) {
this.open = true; this.style.setProperty(
this.narrow = narrow; "--app-drawer-width",
narrow ? window.innerWidth + "px" : "500px"
);
this.$.drawer.open();
} }
} }
customElements.define("notification-drawer", HuiNotificationDrawer); customElements.define("notification-drawer", HuiNotificationDrawer);