diff --git a/src/components/ha-menu-button.ts b/src/components/ha-menu-button.ts index 6c2b148c4b..baac1dc297 100644 --- a/src/components/ha-menu-button.ts +++ b/src/components/ha-menu-button.ts @@ -98,8 +98,8 @@ class HaMenuButton extends LitElement { return; } - this.style.visibility = - newNarrow || this._alwaysVisible ? "initial" : "hidden"; + this.style.display = + newNarrow || this._alwaysVisible ? "initial" : "none"; if (!newNarrow) { this._hasNotifications = false; diff --git a/src/components/ha-tabs.ts b/src/components/ha-tabs.ts new file mode 100644 index 0000000000..33338c4a93 --- /dev/null +++ b/src/components/ha-tabs.ts @@ -0,0 +1,97 @@ +import "@polymer/paper-tabs/paper-tabs"; +import type { PaperIconButtonElement } from "@polymer/paper-icon-button/paper-icon-button"; +import type { PaperTabElement } from "@polymer/paper-tabs/paper-tab"; +import type { PaperTabsElement } from "@polymer/paper-tabs/paper-tabs"; +import { customElement } from "lit-element"; +import { Constructor } from "../types"; + +const PaperTabs = customElements.get("paper-tabs") as Constructor< + PaperTabsElement +>; + +let subTemplate: HTMLTemplateElement; + +@customElement("ha-tabs") +export class HaTabs extends PaperTabs { + private _firstTabWidth = 0; + + private _lastTabWidth = 0; + + private _lastLeftHiddenState = false; + + static get template(): HTMLTemplateElement { + if (!subTemplate) { + subTemplate = (PaperTabs as any).template.cloneNode(true); + + const superStyle = subTemplate.content.querySelector("style"); + + // Add "noink" attribute for scroll buttons to disable animation. + subTemplate.content + .querySelectorAll("paper-icon-button") + .forEach((arrow: PaperIconButtonElement) => { + arrow.setAttribute("noink", ""); + }); + + superStyle!.appendChild( + document.createTextNode(` + .not-visible { + display: none; + } + :host > paper-icon-button:first-of-type { + padding-left: 0; + } + paper-icon-button { + margin: 0 -8px 0 0; + } + `) + ); + } + return subTemplate; + } + + // Get first and last tab's width for _affectScroll + public _tabChanged(tab: PaperTabElement, old: PaperTabElement): void { + super._tabChanged(tab, old); + const tabs = this.querySelectorAll("paper-tab:not(.hide-tab)"); + if (tabs.length > 0) { + this._firstTabWidth = tabs[0].clientWidth; + this._lastTabWidth = tabs[tabs.length - 1].clientWidth; + } + + // Scroll active tab into view if needed. + const selected = this.querySelector(".iron-selected"); + if (selected) { + selected.scrollIntoView(); + } + } + + /** + * Modify _affectScroll so that when the scroll arrows appear + * while scrolling and the tab container shrinks we can counteract + * the jump in tab position so that the scroll still appears smooth. + */ + public _affectScroll(dx: number): void { + if (this._firstTabWidth === 0 || this._lastTabWidth === 0) { + return; + } + + this.$.tabsContainer.scrollLeft += dx; + + const scrollLeft = this.$.tabsContainer.scrollLeft; + + this._leftHidden = scrollLeft - this._firstTabWidth < 0; + this._rightHidden = + scrollLeft + this._lastTabWidth > this._tabContainerScrollSize; + + if (this._lastLeftHiddenState !== this._leftHidden) { + this._lastLeftHiddenState = this._leftHidden; + this.$.tabsContainer.scrollLeft += this._leftHidden ? -46 : 46; + } + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-tabs": HaTabs; + } +} diff --git a/src/panels/developer-tools/ha-panel-developer-tools.ts b/src/panels/developer-tools/ha-panel-developer-tools.ts index 1a71602c8b..e8c8317e17 100644 --- a/src/panels/developer-tools/ha-panel-developer-tools.ts +++ b/src/panels/developer-tools/ha-panel-developer-tools.ts @@ -3,7 +3,7 @@ import "@polymer/app-layout/app-toolbar/app-toolbar"; import "../../layouts/ha-app-layout"; import "../../components/ha-icon-button"; import "@polymer/paper-tabs/paper-tab"; -import "@polymer/paper-tabs/paper-tabs"; +import "../../components/ha-tabs"; import { css, CSSResultArray, @@ -44,7 +44,7 @@ class PanelDeveloperTools extends LitElement { >