mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-12 20:40:29 +00:00
Compare commits
16 Commits
copilot/fi
...
sidebar-mw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f138ec8ce0 | ||
|
|
b6cf935953 | ||
|
|
dca9bec03c | ||
|
|
aa6915cb90 | ||
|
|
28405f6ddf | ||
|
|
366bea4344 | ||
|
|
173c6bc4c3 | ||
|
|
91e00815df | ||
|
|
29d9219481 | ||
|
|
1369d0f36d | ||
|
|
4a38f7a9e0 | ||
|
|
12aab855d7 | ||
|
|
f24b1ea844 | ||
|
|
3345b52da4 | ||
|
|
6ec35380ac | ||
|
|
24f334bfe2 |
61
src/components/ha-clickable-list-item.ts
Normal file
61
src/components/ha-clickable-list-item.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { style } from "@material/mwc-list/mwc-list-item-css";
|
||||||
|
import { ListItemBase } from "@material/mwc-list/mwc-list-item-base";
|
||||||
|
import { css, CSSResult, customElement, property } from "lit-element";
|
||||||
|
import { html } from "lit-html";
|
||||||
|
|
||||||
|
@customElement("ha-clickable-list-item")
|
||||||
|
export class HaClickableListItem extends ListItemBase {
|
||||||
|
public href?: string;
|
||||||
|
|
||||||
|
public disableHref = false;
|
||||||
|
|
||||||
|
// property used only in css
|
||||||
|
@property({ type: Boolean, reflect: true }) public rtl = false;
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const r = super.render();
|
||||||
|
const href = this.href ? `/${this.href}` : "";
|
||||||
|
|
||||||
|
return html` ${this.renderRipple()}
|
||||||
|
${this.disableHref
|
||||||
|
? html`<a aria-role="option">${r}</a>`
|
||||||
|
: html`<a aria-role="option" href=${href}>${r}</a>`}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult[] {
|
||||||
|
return [
|
||||||
|
style,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([rtl]) span {
|
||||||
|
margin-left: var(--mdc-list-item-graphic-margin, 20px) !important;
|
||||||
|
margin-right: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([graphic="avatar"]:not([twoLine])),
|
||||||
|
:host([graphic="icon"]:not([twoLine])) {
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: var(--mdc-list-side-padding, 20px);
|
||||||
|
padding-right: var(--mdc-list-side-padding, 20px);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-clickable-list-item": HaClickableListItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
import "./ha-clickable-list-item";
|
||||||
|
import "./ha-icon";
|
||||||
|
import "./ha-menu-button";
|
||||||
|
import "./ha-svg-icon";
|
||||||
|
import "./user/ha-user-badge";
|
||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import "@material/mwc-icon-button";
|
import "@material/mwc-icon-button";
|
||||||
|
import { List } from "@material/mwc-list";
|
||||||
import {
|
import {
|
||||||
mdiBell,
|
mdiBell,
|
||||||
mdiCellphoneCog,
|
mdiCellphoneCog,
|
||||||
@@ -9,10 +15,6 @@ import {
|
|||||||
mdiPlus,
|
mdiPlus,
|
||||||
mdiViewDashboard,
|
mdiViewDashboard,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
|
||||||
import type { PaperIconItemElement } from "@polymer/paper-item/paper-icon-item";
|
|
||||||
import "@polymer/paper-item/paper-item";
|
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
@@ -23,8 +25,8 @@ import {
|
|||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
|
query,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
|
||||||
import { guard } from "lit-html/directives/guard";
|
import { guard } from "lit-html/directives/guard";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { LocalStorage } from "../common/decorators/local-storage";
|
import { LocalStorage } from "../common/decorators/local-storage";
|
||||||
@@ -44,10 +46,8 @@ import {
|
|||||||
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant, PanelInfo } from "../types";
|
import type { HomeAssistant, PanelInfo } from "../types";
|
||||||
import "./ha-icon";
|
import { ListItem } from "@material/mwc-list/mwc-list-item";
|
||||||
import "./ha-menu-button";
|
import { navigate } from "../common/navigate";
|
||||||
import "./ha-svg-icon";
|
|
||||||
import "./user/ha-user-badge";
|
|
||||||
|
|
||||||
const SHOW_AFTER_SPACER = ["config", "developer-tools", "hassio"];
|
const SHOW_AFTER_SPACER = ["config", "developer-tools", "hassio"];
|
||||||
|
|
||||||
@@ -157,6 +157,12 @@ const computePanels = memoizeOne(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isListItem = (element: Element): element is ListItem =>
|
||||||
|
element.hasAttribute("mwc-list-item");
|
||||||
|
|
||||||
|
const isNodeElement = (node: Node): node is Element =>
|
||||||
|
node.nodeType === Node.ELEMENT_NODE;
|
||||||
|
|
||||||
let Sortable;
|
let Sortable;
|
||||||
|
|
||||||
@customElement("ha-sidebar")
|
@customElement("ha-sidebar")
|
||||||
@@ -181,6 +187,12 @@ class HaSidebar extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _renderEmptySortable = false;
|
@internalProperty() private _renderEmptySortable = false;
|
||||||
|
|
||||||
|
@query("div.ha-scrollbar mwc-list.main-panels", false)
|
||||||
|
private _standardPanelList!: List;
|
||||||
|
|
||||||
|
@query("div.ha-scrollbar mwc-list.utility-panels", false)
|
||||||
|
private _utilityPanelList!: List;
|
||||||
|
|
||||||
private _mouseLeaveTimeout?: number;
|
private _mouseLeaveTimeout?: number;
|
||||||
|
|
||||||
private _tooltipHideTimeout?: number;
|
private _tooltipHideTimeout?: number;
|
||||||
@@ -209,11 +221,21 @@ class HaSidebar extends LitElement {
|
|||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return html`
|
return html`
|
||||||
${this._renderHeader()}
|
${this._renderHeader()}
|
||||||
|
<div class="ha-scrollbar">
|
||||||
${this._renderAllPanels()}
|
${this._renderAllPanels()}
|
||||||
${this._renderDivider()}
|
</div>
|
||||||
|
<mwc-list
|
||||||
|
attr-for-selected="data-panel"
|
||||||
|
@focusin=${this._listboxFocusIn}
|
||||||
|
@focusout=${this._listboxFocusOut}
|
||||||
|
@scroll=${this._listboxScroll}
|
||||||
|
@keydown=${this._listboxKeydown}
|
||||||
|
>
|
||||||
|
<li divider role="separator"></li>
|
||||||
${this._renderNotifications()}
|
${this._renderNotifications()}
|
||||||
${this._renderUserItem()}
|
${this._renderUserItem()}
|
||||||
<div disabled class="bottom-spacer"></div>
|
${this._renderSpacer()}
|
||||||
|
</mwc-list>
|
||||||
<div class="tooltip"></div>
|
<div class="tooltip"></div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -289,7 +311,9 @@ class HaSidebar extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!oldHass || oldHass.panelUrl !== this.hass.panelUrl) {
|
if (!oldHass || oldHass.panelUrl !== this.hass.panelUrl) {
|
||||||
const selectedEl = this.shadowRoot!.querySelector(".iron-selected");
|
const selectedEl = this.shadowRoot!.querySelector(
|
||||||
|
"ha-clickable-list-item[activated]"
|
||||||
|
);
|
||||||
if (selectedEl) {
|
if (selectedEl) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
selectedEl.scrollIntoViewIfNeeded();
|
selectedEl.scrollIntoViewIfNeeded();
|
||||||
@@ -329,7 +353,15 @@ class HaSidebar extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderAllPanels() {
|
private _renderAllPanels() {
|
||||||
const [beforeSpacer, afterSpacer] = computePanels(
|
// prettier-ignore
|
||||||
|
return html`
|
||||||
|
${this._renderNormalPanels()}
|
||||||
|
${this._renderUtilityPanels()}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderNormalPanels() {
|
||||||
|
const [beforeSpacer] = computePanels(
|
||||||
this.hass.panels,
|
this.hass.panels,
|
||||||
this.hass.defaultPanel,
|
this.hass.defaultPanel,
|
||||||
this._panelOrder,
|
this._panelOrder,
|
||||||
@@ -338,10 +370,9 @@ class HaSidebar extends LitElement {
|
|||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return html`
|
return html`
|
||||||
<paper-listbox
|
<mwc-list
|
||||||
|
class="main-panels"
|
||||||
attr-for-selected="data-panel"
|
attr-for-selected="data-panel"
|
||||||
class="ha-scrollbar"
|
|
||||||
.selected=${this.hass.panelUrl}
|
|
||||||
@focusin=${this._listboxFocusIn}
|
@focusin=${this._listboxFocusIn}
|
||||||
@focusout=${this._listboxFocusOut}
|
@focusout=${this._listboxFocusOut}
|
||||||
@scroll=${this._listboxScroll}
|
@scroll=${this._listboxScroll}
|
||||||
@@ -350,10 +381,7 @@ class HaSidebar extends LitElement {
|
|||||||
${this.editMode
|
${this.editMode
|
||||||
? this._renderPanelsEdit(beforeSpacer)
|
? this._renderPanelsEdit(beforeSpacer)
|
||||||
: this._renderPanels(beforeSpacer)}
|
: this._renderPanels(beforeSpacer)}
|
||||||
${this._renderSpacer()}
|
</mwc-list>
|
||||||
${this._renderPanels(afterSpacer)}
|
|
||||||
${this._renderExternalConfiguration()}
|
|
||||||
</paper-listbox>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +392,7 @@ class HaSidebar extends LitElement {
|
|||||||
this._renderEmptySortable ? "" : this._renderPanels(beforeSpacer)
|
this._renderEmptySortable ? "" : this._renderPanels(beforeSpacer)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
${this._renderSpacer()}
|
${this._renderHiddenItemSpacer()}
|
||||||
${this._renderHiddenPanels()} `;
|
${this._renderHiddenPanels()} `;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,13 +403,15 @@ class HaSidebar extends LitElement {
|
|||||||
if (!panel) {
|
if (!panel) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return html`<paper-icon-item
|
return html`<ha-clickable-list-item
|
||||||
@click=${this._unhidePanel}
|
@click=${this._unhidePanel}
|
||||||
class="hidden-panel"
|
class="hidden-panel"
|
||||||
.panel=${url}
|
.panel=${url}
|
||||||
|
graphic="icon"
|
||||||
|
.rtl=${this.rtl}
|
||||||
>
|
>
|
||||||
<ha-icon
|
<ha-icon
|
||||||
slot="item-icon"
|
slot="graphic"
|
||||||
.icon=${panel.url_path === this.hass.defaultPanel
|
.icon=${panel.url_path === this.hass.defaultPanel
|
||||||
? "mdi:view-dashboard"
|
? "mdi:view-dashboard"
|
||||||
: panel.icon}
|
: panel.icon}
|
||||||
@@ -395,18 +425,52 @@ class HaSidebar extends LitElement {
|
|||||||
<mwc-icon-button class="show-panel">
|
<mwc-icon-button class="show-panel">
|
||||||
<ha-svg-icon .path=${mdiPlus}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiPlus}></ha-svg-icon>
|
||||||
</mwc-icon-button>
|
</mwc-icon-button>
|
||||||
</paper-icon-item>`;
|
</ha-clickable-list-item>`;
|
||||||
})}
|
})}
|
||||||
${this._renderSpacer()}`
|
${this._renderSpacer()}`
|
||||||
: ""}`;
|
: ""}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderDivider() {
|
private _renderUtilityPanels() {
|
||||||
return html`<div class="divider"></div>`;
|
const [, afterSpacer] = computePanels(
|
||||||
|
this.hass.panels,
|
||||||
|
this.hass.defaultPanel,
|
||||||
|
this._panelOrder,
|
||||||
|
this._hiddenPanels
|
||||||
|
);
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
return html`
|
||||||
|
<mwc-list
|
||||||
|
@focusin=${this._listboxFocusIn}
|
||||||
|
@focusout=${this._listboxFocusOut}
|
||||||
|
@scroll=${this._listboxScroll}
|
||||||
|
@keydown=${this._listboxKeydown}
|
||||||
|
class="utility-panels"
|
||||||
|
>
|
||||||
|
${afterSpacer.map((panel) =>
|
||||||
|
this._renderPanel(
|
||||||
|
panel.url_path,
|
||||||
|
panel.url_path === this.hass.defaultPanel
|
||||||
|
? panel.title || this.hass.localize("panel.states")
|
||||||
|
: this.hass.localize(`panel.${panel.title}`) || panel.title,
|
||||||
|
panel.icon,
|
||||||
|
panel.url_path === this.hass.defaultPanel && !panel.icon
|
||||||
|
? mdiViewDashboard
|
||||||
|
: undefined
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
${this._renderExternalConfiguration()}
|
||||||
|
</mwc-list>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderSpacer() {
|
private _renderSpacer() {
|
||||||
return html`<div class="spacer" disabled></div>`;
|
return html`<li divider role="separator" class="spacer"></li>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderHiddenItemSpacer() {
|
||||||
|
return html`<li divider role="separator" class="spacer-hidden"></li>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderNotifications() {
|
private _renderNotifications() {
|
||||||
@@ -419,20 +483,20 @@ class HaSidebar extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return html` <div
|
return html`
|
||||||
class="notifications-container"
|
<ha-clickable-list-item
|
||||||
@mouseenter=${this._itemMouseEnter}
|
|
||||||
@mouseleave=${this._itemMouseLeave}
|
|
||||||
>
|
|
||||||
<paper-icon-item
|
|
||||||
class="notifications"
|
|
||||||
aria-role="option"
|
aria-role="option"
|
||||||
@click=${this._handleShowNotificationDrawer}
|
@click=${this._handleShowNotificationDrawer}
|
||||||
|
graphic="icon"
|
||||||
|
hasMeta
|
||||||
|
@mouseenter=${this._itemMouseEnter}
|
||||||
|
@mouseleave=${this._itemMouseLeave}
|
||||||
|
.rtl=${this.rtl}
|
||||||
>
|
>
|
||||||
<ha-svg-icon slot="item-icon" .path=${mdiBell}></ha-svg-icon>
|
<ha-svg-icon slot="graphic" .path=${mdiBell}></ha-svg-icon>
|
||||||
${!this.expanded && notificationCount > 0
|
${!this.expanded && notificationCount > 0
|
||||||
? html`
|
? html`
|
||||||
<span class="notification-badge" slot="item-icon">
|
<span class="notification-badge">
|
||||||
${notificationCount}
|
${notificationCount}
|
||||||
</span>
|
</span>
|
||||||
`
|
`
|
||||||
@@ -441,45 +505,45 @@ class HaSidebar extends LitElement {
|
|||||||
${this.hass.localize("ui.notification_drawer.title")}
|
${this.hass.localize("ui.notification_drawer.title")}
|
||||||
</span>
|
</span>
|
||||||
${this.expanded && notificationCount > 0
|
${this.expanded && notificationCount > 0
|
||||||
? html` <span class="notification-badge">${notificationCount}</span> `
|
? html`
|
||||||
|
<span class="notification-badge" slot="meta"
|
||||||
|
>${notificationCount}</span
|
||||||
|
>
|
||||||
|
`
|
||||||
: ""}
|
: ""}
|
||||||
</paper-icon-item>
|
</ha-clickable-list-item>
|
||||||
</div>`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderUserItem() {
|
private _renderUserItem() {
|
||||||
return html`<a
|
return html`<ha-clickable-list-item
|
||||||
class=${classMap({
|
class="profile"
|
||||||
profile: true,
|
.href=${"profile"}
|
||||||
// Mimick behavior that paper-listbox provides
|
|
||||||
"iron-selected": this.hass.panelUrl === "profile",
|
|
||||||
})}
|
|
||||||
href="/profile"
|
|
||||||
data-panel="panel"
|
data-panel="panel"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
aria-role="option"
|
|
||||||
aria-label=${this.hass.localize("panel.profile")}
|
aria-label=${this.hass.localize("panel.profile")}
|
||||||
@mouseenter=${this._itemMouseEnter}
|
@mouseenter=${this._itemMouseEnter}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
@mouseleave=${this._itemMouseLeave}
|
||||||
|
graphic="icon"
|
||||||
|
.activated=${this.hass.panelUrl === "profile"}
|
||||||
|
.rtl=${this.rtl}
|
||||||
>
|
>
|
||||||
<paper-icon-item>
|
|
||||||
<ha-user-badge
|
<ha-user-badge
|
||||||
slot="item-icon"
|
slot="graphic"
|
||||||
.user=${this.hass.user}
|
.user=${this.hass.user}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
></ha-user-badge>
|
></ha-user-badge>
|
||||||
|
|
||||||
<span class="item-text">
|
<span class="item-text">
|
||||||
${this.hass.user ? this.hass.user.name : ""}
|
${this.hass.user?.name}
|
||||||
</span>
|
</span>
|
||||||
</paper-icon-item>
|
</ha-clickable-list-item> `;
|
||||||
</a>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderExternalConfiguration() {
|
private _renderExternalConfiguration() {
|
||||||
return html`${this._externalConfig && this._externalConfig.hasSettingsScreen
|
return html`${this._externalConfig && this._externalConfig.hasSettingsScreen
|
||||||
? html`
|
? html`
|
||||||
<a
|
<ha-clickable-list-item
|
||||||
aria-role="option"
|
aria-role="option"
|
||||||
aria-label=${this.hass.localize(
|
aria-label=${this.hass.localize(
|
||||||
"ui.sidebar.external_app_configuration"
|
"ui.sidebar.external_app_configuration"
|
||||||
@@ -489,19 +553,17 @@ class HaSidebar extends LitElement {
|
|||||||
@click=${this._handleExternalAppConfiguration}
|
@click=${this._handleExternalAppConfiguration}
|
||||||
@mouseenter=${this._itemMouseEnter}
|
@mouseenter=${this._itemMouseEnter}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
@mouseleave=${this._itemMouseLeave}
|
||||||
|
graphic="icon"
|
||||||
|
.rtl=${this.rtl}
|
||||||
>
|
>
|
||||||
<paper-icon-item>
|
<ha-svg-icon slot="graphic" .path=${mdiCellphoneCog}></ha-svg-icon>
|
||||||
<ha-svg-icon
|
|
||||||
slot="item-icon"
|
|
||||||
.path=${mdiCellphoneCog}
|
|
||||||
></ha-svg-icon>
|
|
||||||
<span class="item-text">
|
<span class="item-text">
|
||||||
${this.hass.localize("ui.sidebar.external_app_configuration")}
|
${this.hass.localize("ui.sidebar.external_app_configuration")}
|
||||||
</span>
|
</span>
|
||||||
</paper-icon-item>
|
</ha-clickable-list-item>
|
||||||
</a>
|
|
||||||
`
|
`
|
||||||
: ""}`;
|
: ""}
|
||||||
|
${this._renderSpacer()} `;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _tooltip() {
|
private get _tooltip() {
|
||||||
@@ -520,7 +582,7 @@ class HaSidebar extends LitElement {
|
|||||||
if (!Sortable) {
|
if (!Sortable) {
|
||||||
const [sortableImport, sortStylesImport] = await Promise.all([
|
const [sortableImport, sortStylesImport] = await Promise.all([
|
||||||
import("sortablejs/modular/sortable.core.esm"),
|
import("sortablejs/modular/sortable.core.esm"),
|
||||||
import("../resources/ha-sortable-style"),
|
import("../resources/ha-sortable-style-ha-clickable"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const style = document.createElement("style");
|
const style = document.createElement("style");
|
||||||
@@ -542,7 +604,6 @@ class HaSidebar extends LitElement {
|
|||||||
animation: 150,
|
animation: 150,
|
||||||
fallbackClass: "sortable-fallback",
|
fallbackClass: "sortable-fallback",
|
||||||
dataIdAttr: "data-panel",
|
dataIdAttr: "data-panel",
|
||||||
handle: "paper-icon-item",
|
|
||||||
onSort: async () => {
|
onSort: async () => {
|
||||||
this._panelOrder = this._sortable.toArray();
|
this._panelOrder = this._sortable.toArray();
|
||||||
},
|
},
|
||||||
@@ -604,7 +665,7 @@ class HaSidebar extends LitElement {
|
|||||||
clearTimeout(this._mouseLeaveTimeout);
|
clearTimeout(this._mouseLeaveTimeout);
|
||||||
this._mouseLeaveTimeout = undefined;
|
this._mouseLeaveTimeout = undefined;
|
||||||
}
|
}
|
||||||
this._showTooltip(ev.currentTarget as PaperIconItemElement);
|
this._showTooltip(ev.currentTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _itemMouseLeave() {
|
private _itemMouseLeave() {
|
||||||
@@ -620,7 +681,7 @@ class HaSidebar extends LitElement {
|
|||||||
if (this.expanded || ev.target.nodeName !== "A") {
|
if (this.expanded || ev.target.nodeName !== "A") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._showTooltip(ev.target.querySelector("paper-icon-item"));
|
this._showTooltip(ev.target.querySelector("ha-clickable-list-item"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _listboxFocusOut() {
|
private _listboxFocusOut() {
|
||||||
@@ -640,17 +701,91 @@ class HaSidebar extends LitElement {
|
|||||||
this._hideTooltip();
|
this._hideTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _listboxKeydown() {
|
private _getIndexOfTarget(evt: Event): number {
|
||||||
|
const listbox = evt.currentTarget as List;
|
||||||
|
const elements = listbox.items;
|
||||||
|
const path = evt.composedPath();
|
||||||
|
|
||||||
|
for (const pathItem of path as Node[]) {
|
||||||
|
let index = -1;
|
||||||
|
if (isNodeElement(pathItem) && isListItem(pathItem)) {
|
||||||
|
index = elements.indexOf(pathItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getCurrentListPosition(ev: KeyboardEvent) {
|
||||||
|
return {
|
||||||
|
index: this._getIndexOfTarget(ev),
|
||||||
|
list: ev.currentTarget as List,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectNextItem(ev: KeyboardEvent) {
|
||||||
|
const [beforeSpacer, afterSpacer] = computePanels(
|
||||||
|
this.hass.panels,
|
||||||
|
this.hass.defaultPanel,
|
||||||
|
this._panelOrder,
|
||||||
|
this._hiddenPanels
|
||||||
|
);
|
||||||
|
|
||||||
|
const { index, list } = this._getCurrentListPosition(ev);
|
||||||
|
|
||||||
|
if (list === this._standardPanelList && index === beforeSpacer.length - 1) {
|
||||||
|
this._setFocusPanelList(this._utilityPanelList, "top");
|
||||||
|
} else if (
|
||||||
|
list === this._utilityPanelList &&
|
||||||
|
index === afterSpacer.length - 1
|
||||||
|
) {
|
||||||
|
this._setFocusPanelList(this._standardPanelList, "top");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _selectPreviousItem(ev: KeyboardEvent) {
|
||||||
|
const { index, list } = this._getCurrentListPosition(ev);
|
||||||
|
|
||||||
|
if (list === this._standardPanelList && index === 0) {
|
||||||
|
this._setFocusPanelList(this._utilityPanelList, "bottom");
|
||||||
|
} else if (list === this._utilityPanelList && index === 0) {
|
||||||
|
this._setFocusPanelList(this._standardPanelList, "bottom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _listboxKeydown(ev: KeyboardEvent) {
|
||||||
|
if (ev.code === "ArrowDown") {
|
||||||
|
this._selectNextItem(ev);
|
||||||
|
} else if (ev.code === "ArrowUp") {
|
||||||
|
this._selectPreviousItem(ev);
|
||||||
|
} else if (ev.code === "Enter") {
|
||||||
|
(ev.target as ListItem)?.shadowRoot?.querySelector("a")?.click();
|
||||||
|
}
|
||||||
|
|
||||||
this._recentKeydownActiveUntil = new Date().getTime() + 100;
|
this._recentKeydownActiveUntil = new Date().getTime() + 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _showTooltip(item: PaperIconItemElement) {
|
private _setFocusPanelList(list: List, position: "top" | "bottom") {
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
if (position === "bottom") {
|
||||||
|
index = list.querySelectorAll("ha-clickable-list-item").length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
list.focusItemAtIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showTooltip(item) {
|
||||||
if (this._tooltipHideTimeout) {
|
if (this._tooltipHideTimeout) {
|
||||||
clearTimeout(this._tooltipHideTimeout);
|
clearTimeout(this._tooltipHideTimeout);
|
||||||
this._tooltipHideTimeout = undefined;
|
this._tooltipHideTimeout = undefined;
|
||||||
}
|
}
|
||||||
const tooltip = this._tooltip;
|
const tooltip = this._tooltip;
|
||||||
const listbox = this.shadowRoot!.querySelector("paper-listbox")!;
|
const listbox = this.shadowRoot!.querySelector("mwc-list")!;
|
||||||
let top = item.offsetTop + 11;
|
let top = item.offsetTop + 11;
|
||||||
if (listbox.contains(item)) {
|
if (listbox.contains(item)) {
|
||||||
top -= listbox.scrollTop;
|
top -= listbox.scrollTop;
|
||||||
@@ -711,23 +846,22 @@ class HaSidebar extends LitElement {
|
|||||||
iconPath?: string | null
|
iconPath?: string | null
|
||||||
) {
|
) {
|
||||||
return html`
|
return html`
|
||||||
<a
|
<ha-clickable-list-item
|
||||||
aria-role="option"
|
.activated=${urlPath === this.hass.panelUrl}
|
||||||
href=${`/${urlPath}`}
|
.href=${urlPath}
|
||||||
|
.disableHref=${this.editMode}
|
||||||
data-panel=${urlPath}
|
data-panel=${urlPath}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
@mouseenter=${this._itemMouseEnter}
|
@mouseenter=${this._itemMouseEnter}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
@mouseleave=${this._itemMouseLeave}
|
||||||
|
@click=${() => navigate(this, `/${urlPath}`)}
|
||||||
|
graphic="icon"
|
||||||
|
.rtl=${this.rtl}
|
||||||
>
|
>
|
||||||
<paper-icon-item>
|
|
||||||
${iconPath
|
${iconPath
|
||||||
? html`<ha-svg-icon
|
? html`<ha-svg-icon slot="graphic" .path=${iconPath}></ha-svg-icon>`
|
||||||
slot="item-icon"
|
: html`<ha-icon slot="graphic" .icon=${icon}></ha-icon>`}
|
||||||
.path=${iconPath}
|
${title}
|
||||||
></ha-svg-icon>`
|
|
||||||
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
|
||||||
<span class="item-text">${title}</span>
|
|
||||||
</paper-icon-item>
|
|
||||||
${this.editMode
|
${this.editMode
|
||||||
? html`<mwc-icon-button
|
? html`<mwc-icon-button
|
||||||
class="hide-panel"
|
class="hide-panel"
|
||||||
@@ -737,7 +871,7 @@ class HaSidebar extends LitElement {
|
|||||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||||
</mwc-icon-button>`
|
</mwc-icon-button>`
|
||||||
: ""}
|
: ""}
|
||||||
</a>
|
</ha-clickable-list-item>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,6 +929,21 @@ class HaSidebar extends LitElement {
|
|||||||
.menu mwc-icon-button {
|
.menu mwc-icon-button {
|
||||||
color: var(--sidebar-icon-color);
|
color: var(--sidebar-icon-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-clickable-list-item {
|
||||||
|
margin: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 40px;
|
||||||
|
--mdc-list-side-padding: 12px;
|
||||||
|
--mdc-theme-text-icon-on-background: var(--sidebar-icon-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-clickable-list-item[activated] {
|
||||||
|
--mdc-theme-text-icon-on-background: var(
|
||||||
|
--sidebar-selected-icon-color
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin-left: 19px;
|
margin-left: 19px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -806,7 +955,6 @@ class HaSidebar extends LitElement {
|
|||||||
}
|
}
|
||||||
:host([narrow]) .title {
|
:host([narrow]) .title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 16px;
|
|
||||||
}
|
}
|
||||||
:host([expanded]) .title {
|
:host([expanded]) .title {
|
||||||
display: initial;
|
display: initial;
|
||||||
@@ -822,120 +970,46 @@ class HaSidebar extends LitElement {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
paper-listbox {
|
.ha-scrollbar {
|
||||||
padding: 4px 0;
|
height: calc(100% - var(--header-height) - 105px);
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: calc(100% - var(--header-height) - 132px);
|
|
||||||
height: calc(
|
height: calc(
|
||||||
100% - var(--header-height) - 132px - env(safe-area-inset-bottom)
|
100% - var(--header-height) - 105px - env(safe-area-inset-bottom)
|
||||||
);
|
);
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
background: none;
|
display: flex;
|
||||||
margin-left: env(safe-area-inset-left);
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([rtl]) paper-listbox {
|
mwc-list {
|
||||||
|
width: var(--app-drawer-width);
|
||||||
|
--mdc-list-vertical-padding: 4px 0;
|
||||||
|
margin-left: env(safe-area-inset-left);
|
||||||
|
-ms-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
background-color: var(--sidebar-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([rtl]) mwc-list {
|
||||||
|
border-right: 0;
|
||||||
|
/* border-left: 1px solid var(--divider-color); */
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([expanded]) mwc-list {
|
||||||
|
width: 256px;
|
||||||
|
width: calc(256px + env(safe-area-inset-left));
|
||||||
|
}
|
||||||
|
|
||||||
|
[slot="graphic"] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([rtl]) mwc-list {
|
||||||
margin-left: initial;
|
margin-left: initial;
|
||||||
margin-right: env(safe-area-inset-right);
|
margin-right: env(safe-area-inset-right);
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--sidebar-text-color);
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-icon-item {
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 4px;
|
|
||||||
padding-left: 12px;
|
|
||||||
border-radius: 4px;
|
|
||||||
--paper-item-min-height: 40px;
|
|
||||||
width: 48px;
|
|
||||||
}
|
|
||||||
:host([expanded]) paper-icon-item {
|
|
||||||
width: 248px;
|
|
||||||
}
|
|
||||||
:host([rtl]) paper-icon-item {
|
|
||||||
padding-left: auto;
|
|
||||||
padding-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-icon[slot="item-icon"],
|
|
||||||
ha-svg-icon[slot="item-icon"] {
|
|
||||||
color: var(--sidebar-icon-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.iron-selected paper-icon-item::before,
|
|
||||||
a:not(.iron-selected):focus::before {
|
|
||||||
border-radius: 4px;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 2px;
|
|
||||||
bottom: 0;
|
|
||||||
left: 2px;
|
|
||||||
pointer-events: none;
|
|
||||||
content: "";
|
|
||||||
transition: opacity 15ms linear;
|
|
||||||
will-change: opacity;
|
|
||||||
}
|
|
||||||
.iron-selected paper-icon-item::before {
|
|
||||||
background-color: var(--sidebar-selected-icon-color);
|
|
||||||
opacity: 0.12;
|
|
||||||
}
|
|
||||||
a:not(.iron-selected):focus::before {
|
|
||||||
background-color: currentColor;
|
|
||||||
opacity: var(--dark-divider-opacity);
|
|
||||||
margin: 4px 8px;
|
|
||||||
}
|
|
||||||
.iron-selected paper-icon-item:focus::before,
|
|
||||||
.iron-selected:focus paper-icon-item::before {
|
|
||||||
opacity: 0.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iron-selected paper-icon-item[pressed]:before {
|
|
||||||
opacity: 0.37;
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-icon-item span {
|
|
||||||
color: var(--sidebar-text-color);
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.iron-selected paper-icon-item ha-icon,
|
|
||||||
a.iron-selected paper-icon-item ha-svg-icon {
|
|
||||||
color: var(--sidebar-selected-icon-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
a.iron-selected .item-text {
|
|
||||||
color: var(--sidebar-selected-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-icon-item .item-text {
|
|
||||||
display: none;
|
|
||||||
max-width: calc(100% - 56px);
|
|
||||||
}
|
|
||||||
:host([expanded]) paper-icon-item .item-text {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
bottom: 112px;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
.divider::before {
|
|
||||||
content: " ";
|
|
||||||
display: block;
|
|
||||||
height: 1px;
|
|
||||||
background-color: var(--divider-color);
|
|
||||||
}
|
|
||||||
.notifications-container {
|
.notifications-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: env(safe-area-inset-left);
|
margin-left: env(safe-area-inset-left);
|
||||||
@@ -951,22 +1025,19 @@ class HaSidebar extends LitElement {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
.profile {
|
.profile {
|
||||||
margin-left: env(safe-area-inset-left);
|
--mdc-list-item-graphic-margin: 16px;
|
||||||
|
--mdc-list-item-graphic-size: 40px;
|
||||||
|
--mdc-list-side-padding: 4px;
|
||||||
}
|
}
|
||||||
:host([rtl]) .profile {
|
:host([rtl]) .profile {
|
||||||
margin-left: initial;
|
--mdc-list-item-graphic-size: 40px;
|
||||||
margin-right: env(safe-area-inset-right);
|
--mdc-list-side-padding: 4px;
|
||||||
}
|
|
||||||
.profile paper-icon-item {
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
:host([rtl]) .profile paper-icon-item {
|
|
||||||
padding-left: auto;
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile .item-text {
|
.profile .item-text {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([rtl]) .profile .item-text {
|
:host([rtl]) .profile .item-text {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
@@ -977,21 +1048,31 @@ class HaSidebar extends LitElement {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
line-height: 20px;
|
line-height: 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0px 6px;
|
padding: 2px 6px;
|
||||||
color: var(--text-accent-color, var(--text-primary-color));
|
color: var(--text-accent-color, var(--text-primary-color));
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-svg-icon + .notification-badge {
|
ha-svg-icon + .notification-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 14px;
|
bottom: 18px;
|
||||||
left: 26px;
|
left: 25px;
|
||||||
font-size: 0.65em;
|
padding: 0px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spacer {
|
.spacer {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer-hidden {
|
||||||
|
flex: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
height: 77px;
|
||||||
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subheader {
|
.subheader {
|
||||||
@@ -1002,19 +1083,6 @@ class HaSidebar extends LitElement {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dev-tools {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 8px;
|
|
||||||
width: 256px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dev-tools a {
|
|
||||||
color: var(--sidebar-icon-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
95
src/resources/ha-sortable-style-ha-clickable.ts
Normal file
95
src/resources/ha-sortable-style-ha-clickable.ts
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import { css } from "lit-element";
|
||||||
|
|
||||||
|
export const sortableStyles = css`
|
||||||
|
#sortable ha-clickable-list-item:nth-of-type(2n) {
|
||||||
|
animation-name: keyframes1;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
transform-origin: 50% 10%;
|
||||||
|
animation-delay: -0.75s;
|
||||||
|
animation-duration: 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sortable ha-clickable-list-item:nth-of-type(2n-1) {
|
||||||
|
animation-name: keyframes2;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-direction: alternate;
|
||||||
|
transform-origin: 30% 5%;
|
||||||
|
animation-delay: -0.5s;
|
||||||
|
animation-duration: 0.33s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sortable a {
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sortable {
|
||||||
|
outline: none;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-panel {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-fallback {
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-ghost {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes keyframes1 {
|
||||||
|
0% {
|
||||||
|
transform: rotate(-1deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: rotate(1.5deg);
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes keyframes2 {
|
||||||
|
0% {
|
||||||
|
transform: rotate(1deg);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: rotate(-1.5deg);
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-panel,
|
||||||
|
.hide-panel {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
--mdc-icon-button-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-panel {
|
||||||
|
top: 4px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([expanded]) .hide-panel {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([expanded]) .show-panel {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-clickable-list-item.hidden-panel,
|
||||||
|
ha-clickable-list-item.hidden-panel span {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { css } from "lit-element";
|
import { css } from "lit-element";
|
||||||
|
|
||||||
export const sortableStyles = css`
|
export const sortableStyles = css`
|
||||||
|
#sortable ha-clickable-list-item:nth-of-type(2n),
|
||||||
#sortable a:nth-of-type(2n) paper-icon-item {
|
#sortable a:nth-of-type(2n) paper-icon-item {
|
||||||
animation-name: keyframes1;
|
animation-name: keyframes1;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
@@ -9,6 +10,7 @@ export const sortableStyles = css`
|
|||||||
animation-duration: 0.25s;
|
animation-duration: 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sortable ha-clickable-list-item:nth-of-type(2n-1),
|
||||||
#sortable a:nth-of-type(2n-1) paper-icon-item {
|
#sortable a:nth-of-type(2n-1) paper-icon-item {
|
||||||
animation-name: keyframes2;
|
animation-name: keyframes2;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
@@ -34,16 +36,13 @@ export const sortableStyles = css`
|
|||||||
|
|
||||||
.sortable-fallback {
|
.sortable-fallback {
|
||||||
display: none;
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sortable-ghost {
|
.sortable-ghost {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sortable-fallback {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes keyframes1 {
|
@keyframes keyframes1 {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(-1deg);
|
transform: rotate(-1deg);
|
||||||
@@ -73,15 +72,10 @@ export const sortableStyles = css`
|
|||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 4px;
|
right: 0;
|
||||||
--mdc-icon-button-size: 40px;
|
--mdc-icon-button-size: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([rtl]) .show-panel {
|
|
||||||
right: initial;
|
|
||||||
left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-panel {
|
.hide-panel {
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
@@ -100,6 +94,8 @@ export const sortableStyles = css`
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-clickable-list-item.hidden-panel,
|
||||||
|
ha-clickable-list-item.hidden-panel span,
|
||||||
paper-icon-item.hidden-panel,
|
paper-icon-item.hidden-panel,
|
||||||
paper-icon-item.hidden-panel span,
|
paper-icon-item.hidden-panel span,
|
||||||
paper-icon-item.hidden-panel ha-icon[slot="item-icon"] {
|
paper-icon-item.hidden-panel ha-icon[slot="item-icon"] {
|
||||||
|
|||||||
Reference in New Issue
Block a user