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, 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() {
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;
}

View File

@ -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`
<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 {
color: var(--primary-text-color);
border-bottom: 1px solid var(--divider-color);
background-color: var(--primary-background-color);
min-height: 64px;
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 {
@ -119,11 +45,10 @@ export class HuiNotificationDrawer extends EventsMixin(
text-align: center;
}
</style>
<div class="overlay" on-click="_closeDrawer"></div>
<div class="container">
<app-drawer id='drawer' opened="{{open}}">
<app-toolbar>
<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>
<div class="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>
</template>
</div>
</div>
</app-drawer>
`;
}
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,35 +106,19 @@ 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) {
} else if (this._unsubNotifications) {
this._unsubNotifications();
this._unsubNotifications = undefined;
}
}
}
_computeRTL(hass) {
return computeRTL(hass);
}
_computeNotifications(open, hass, notificationsBackend) {
if (!open) {
@ -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);