mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add loading skeleton
This commit is contained in:
parent
a3dcf77f2a
commit
6123d932e1
@ -90,6 +90,7 @@
|
||||
"@polymer/paper-tabs": "3.1.0",
|
||||
"@polymer/polymer": "3.5.2",
|
||||
"@replit/codemirror-indentation-markers": "6.5.3",
|
||||
"@shoelace-style/shoelace": "2.20.0",
|
||||
"@thomasloven/round-slider": "0.6.0",
|
||||
"@vaadin/combo-box": "24.6.4",
|
||||
"@vaadin/vaadin-themable-mixin": "24.6.4",
|
||||
|
@ -1,4 +1,5 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@shoelace-style/shoelace/dist/components/skeleton/skeleton";
|
||||
import {
|
||||
mdiBell,
|
||||
mdiCalendar,
|
||||
@ -212,18 +213,10 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _unsubPersistentNotifications: UnsubscribeFunc | undefined;
|
||||
|
||||
@storage({
|
||||
key: "sidebarPanelOrder",
|
||||
state: true,
|
||||
subscribe: true,
|
||||
})
|
||||
@storage({ key: "sidebarPanelOrder", state: true, subscribe: true })
|
||||
private _devicePanelOrder?: string[];
|
||||
|
||||
@storage({
|
||||
key: "sidebarHiddenPanels",
|
||||
state: true,
|
||||
subscribe: true,
|
||||
})
|
||||
@storage({ key: "sidebarHiddenPanels", state: true, subscribe: true })
|
||||
private _deviceHiddenPanels?: string[];
|
||||
|
||||
@state()
|
||||
@ -232,11 +225,15 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
@state()
|
||||
private _userHiddenPanels: string[] = [];
|
||||
|
||||
@state()
|
||||
private _loadingUserPreferences = true;
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
const subscribeFunctions = [
|
||||
subscribeSidebarPreferences(this.hass, (sidebar) => {
|
||||
this._userPanelOrder = sidebar?.panelOrder || [];
|
||||
this._userHiddenPanels = sidebar?.hiddenPanels || [];
|
||||
this._loadingUserPreferences = false;
|
||||
}),
|
||||
];
|
||||
if (this.hass.user?.is_admin) {
|
||||
@ -402,35 +399,43 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
private _getPanelPreferencesMemoized = memoizeOne((userPreferences: SidebarPreferences, devicePreferences: SidebarPreferences): { panelOrder: string[], hiddenPanels: string[] } => {
|
||||
let panelOrder = userPreferences.panelOrder ?? [];
|
||||
let hiddenPanels = userPreferences.hiddenPanels ?? [];
|
||||
private _getPanelPreferencesMemoized = memoizeOne(
|
||||
(userPreferences: SidebarPreferences, devicePreferences: SidebarPreferences, userPreferencesLoading: boolean): { panelOrder: string[]; hiddenPanels: string[]; loading: boolean } => {
|
||||
let panelOrder = userPreferences.panelOrder ?? [];
|
||||
let hiddenPanels = userPreferences.hiddenPanels ?? [];
|
||||
|
||||
if (devicePreferences.panelOrder || devicePreferences.hiddenPanels) {
|
||||
panelOrder = devicePreferences.panelOrder ?? [];
|
||||
hiddenPanels = devicePreferences.hiddenPanels ?? [];
|
||||
let loading = userPreferencesLoading;
|
||||
|
||||
if (devicePreferences.panelOrder || devicePreferences.hiddenPanels) {
|
||||
panelOrder = devicePreferences.panelOrder ?? [];
|
||||
hiddenPanels = devicePreferences.hiddenPanels ?? [];
|
||||
loading = false;
|
||||
}
|
||||
|
||||
return {
|
||||
panelOrder,
|
||||
hiddenPanels,
|
||||
loading
|
||||
};
|
||||
}
|
||||
|
||||
return { panelOrder, hiddenPanels }
|
||||
})
|
||||
);
|
||||
|
||||
private _getPanelPreferences() {
|
||||
return this._getPanelPreferencesMemoized(
|
||||
{
|
||||
panelOrder: this._userPanelOrder,
|
||||
hiddenPanels: this._userHiddenPanels
|
||||
hiddenPanels: this._userHiddenPanels,
|
||||
},
|
||||
{
|
||||
panelOrder: this._devicePanelOrder,
|
||||
hiddenPanels: this._deviceHiddenPanels
|
||||
}
|
||||
)
|
||||
hiddenPanels: this._deviceHiddenPanels,
|
||||
},
|
||||
this._loadingUserPreferences
|
||||
);
|
||||
}
|
||||
|
||||
private _renderAllPanels() {
|
||||
// TODO render skeleton loading if panels are not loaded yet
|
||||
|
||||
const { panelOrder, hiddenPanels } = this._getPanelPreferences();
|
||||
const { panelOrder, hiddenPanels, loading } = this._getPanelPreferences();
|
||||
|
||||
const [beforeSpacer, afterSpacer] = computePanels(
|
||||
this.hass.panels,
|
||||
@ -457,12 +462,21 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
@keydown=${this._listboxKeydown}
|
||||
@iron-activate=${preventDefault}
|
||||
>
|
||||
${this.editMode
|
||||
? this._renderPanelsEdit(beforeSpacer)
|
||||
: this._renderPanels(beforeSpacer)}
|
||||
${this._renderSpacer()}
|
||||
${this._renderPanels(afterSpacer)}
|
||||
${this._renderExternalConfiguration()}
|
||||
${loading ? html`
|
||||
<div class="loading">
|
||||
<sl-skeleton effect="sheen"></sl-skeleton>
|
||||
<sl-skeleton effect="sheen"></sl-skeleton>
|
||||
<sl-skeleton effect="sheen"></sl-skeleton>
|
||||
<sl-skeleton effect="sheen"></sl-skeleton>
|
||||
</div>
|
||||
` : html`
|
||||
${this.editMode
|
||||
? this._renderPanelsEdit(beforeSpacer)
|
||||
: this._renderPanels(beforeSpacer)}
|
||||
${this._renderSpacer()}
|
||||
${this._renderPanels(afterSpacer)}
|
||||
${this._renderExternalConfiguration()}
|
||||
`}
|
||||
</paper-listbox>
|
||||
`;
|
||||
}
|
||||
@ -768,9 +782,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _handleExternalAppConfiguration(ev: Event) {
|
||||
ev.preventDefault();
|
||||
this.hass.auth.external!.fireMessage({
|
||||
type: "config_screen/show",
|
||||
});
|
||||
this.hass.auth.external!.fireMessage({ type: "config_screen/show" });
|
||||
}
|
||||
|
||||
private get _tooltip() {
|
||||
@ -813,13 +825,11 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
|
||||
const { panelOrder, hiddenPanels } = this._getPanelPreferences();
|
||||
|
||||
|
||||
// Make a copy for Memoize
|
||||
this._setHiddenPanels([...hiddenPanels, panel]);
|
||||
// Remove it from the panel order
|
||||
this._setPanelOrder(panelOrder.filter(
|
||||
(order) => order !== panel
|
||||
));
|
||||
this._setPanelOrder(panelOrder.filter((order) => order !== panel));
|
||||
}
|
||||
|
||||
private async _unhidePanel(ev: Event) {
|
||||
@ -868,9 +878,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
this._hideTooltip();
|
||||
}
|
||||
|
||||
@eventOptions({
|
||||
passive: true,
|
||||
})
|
||||
@eventOptions({ passive: true })
|
||||
private _listboxScroll() {
|
||||
// On keypresses on the listbox, we're going to ignore scroll events
|
||||
// for 100ms so that if pressing down arrow scrolls the sidebar, the tooltip
|
||||
@ -1201,6 +1209,32 @@ class HaSidebar extends SubscribeMixin(LitElement) {
|
||||
-webkit-transform: scaleX(var(--scale-direction));
|
||||
transform: scaleX(var(--scale-direction));
|
||||
}
|
||||
|
||||
.loading {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
sl-skeleton {
|
||||
--border-radius: 8px;
|
||||
height: 24px;
|
||||
--color: var(--outline-color);
|
||||
--sheen-color: var(--outline-hover-color);
|
||||
}
|
||||
|
||||
sl-skeleton:nth-child(2) {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
sl-skeleton:nth-child(3) {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
sl-skeleton:nth-child(4) {
|
||||
width: 90%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
89
yarn.lock
89
yarn.lock
@ -1388,6 +1388,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ctrl/tinycolor@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "@ctrl/tinycolor@npm:4.1.0"
|
||||
checksum: 10/e64569399139ef0abd2eb0ec9fb7267dfd7820f7ad7d4567a63e5fc35e5cfdcb8ecdb3bad65cb9244b47ba6c77bc51085826c00e981acf263a3221dc89343adc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@discoveryjs/json-ext@npm:0.5.7, @discoveryjs/json-ext@npm:^0.5.7":
|
||||
version: 0.5.7
|
||||
resolution: "@discoveryjs/json-ext@npm:0.5.7"
|
||||
@ -1667,6 +1674,32 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/core@npm:^1.6.0":
|
||||
version: 1.6.9
|
||||
resolution: "@floating-ui/core@npm:1.6.9"
|
||||
dependencies:
|
||||
"@floating-ui/utils": "npm:^0.2.9"
|
||||
checksum: 10/656fcd383da17fffca2efa0635cbe3c0b835c3312949e30bd19d05bf42479f2ac22aaf336a6a31cb160621fc6f35cfc9e115e76c5cf48ba96e33474d123ced22
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/dom@npm:^1.6.12":
|
||||
version: 1.6.13
|
||||
resolution: "@floating-ui/dom@npm:1.6.13"
|
||||
dependencies:
|
||||
"@floating-ui/core": "npm:^1.6.0"
|
||||
"@floating-ui/utils": "npm:^0.2.9"
|
||||
checksum: 10/4bb732baf3270007741bcdc91be1de767b2bb5d8b891eb838e5f1e7c4cccad998643dbdd4e8b8cec4c5d12c9898f80febc68e9793dd6e26a445283c4fb1b6a78
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/utils@npm:^0.2.9":
|
||||
version: 0.2.9
|
||||
resolution: "@floating-ui/utils@npm:0.2.9"
|
||||
checksum: 10/0ca786347db3dd8d9034b86d1449fabb96642788e5900cc5f2aee433cd7b243efbcd7a165bead50b004ee3f20a90ddebb6a35296fc41d43cfd361b6f01b69ffb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/ecma402-abstract@npm:2.3.3":
|
||||
version: 2.3.3
|
||||
resolution: "@formatjs/ecma402-abstract@npm:2.3.3"
|
||||
@ -2262,6 +2295,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@lit/react@npm:^1.0.6":
|
||||
version: 1.0.7
|
||||
resolution: "@lit/react@npm:1.0.7"
|
||||
peerDependencies:
|
||||
"@types/react": 17 || 18 || 19
|
||||
checksum: 10/9bdf90e233c91822065d0f09aa0d085544b5d70902b05bb6204075404f7e0e5a62a9a447eac55178761690ea1f707b1c13fecd8f8b109a25f978afe7a2c74fea
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@lit/reactive-element@npm:1.6.3":
|
||||
version: 1.6.3
|
||||
resolution: "@lit/reactive-element@npm:1.6.3"
|
||||
@ -4373,6 +4415,36 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shoelace-style/animations@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@shoelace-style/animations@npm:1.2.0"
|
||||
checksum: 10/73773147cebc5833f362f01f96245cc156e9619cc04a8ee342bd9d320661d0fce30ba2fee3a515603eb1141da005c163a608b6356fd5b478f50a483bc9806e16
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shoelace-style/localize@npm:^3.2.1":
|
||||
version: 3.2.1
|
||||
resolution: "@shoelace-style/localize@npm:3.2.1"
|
||||
checksum: 10/e22e108a27ce7da6b86a7b2f16f8db69e9b3c7d2aaf4e34fc39023c2f060aa7a5004d02ffd1cce2fbef3de7e5cd2a60e79c77fbba5cbd5e9456881fa3a452db1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shoelace-style/shoelace@npm:2.20.0":
|
||||
version: 2.20.0
|
||||
resolution: "@shoelace-style/shoelace@npm:2.20.0"
|
||||
dependencies:
|
||||
"@ctrl/tinycolor": "npm:^4.1.0"
|
||||
"@floating-ui/dom": "npm:^1.6.12"
|
||||
"@lit/react": "npm:^1.0.6"
|
||||
"@shoelace-style/animations": "npm:^1.2.0"
|
||||
"@shoelace-style/localize": "npm:^3.2.1"
|
||||
composed-offset-position: "npm:^0.0.6"
|
||||
lit: "npm:^3.2.1"
|
||||
qr-creator: "npm:^1.0.0"
|
||||
checksum: 10/202b226c9fa92950c6900c80899b6f95b13c0d79210c956a1c9be75ae6c87b4d7a210bfe355a6580ef423a78c32e141869dba302713dba055ec2339c9dbdc383
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sindresorhus/merge-streams@npm:^2.1.0":
|
||||
version: 2.3.0
|
||||
resolution: "@sindresorhus/merge-streams@npm:2.3.0"
|
||||
@ -6840,6 +6912,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"composed-offset-position@npm:^0.0.6":
|
||||
version: 0.0.6
|
||||
resolution: "composed-offset-position@npm:0.0.6"
|
||||
peerDependencies:
|
||||
"@floating-ui/utils": ^0.2.5
|
||||
checksum: 10/f0e403f11a6a677631d39b5e7a742c242067c44c2278c6616362d46ee2b9a376dd9cb2d676640bf1f395cc69da52e5ebac9cd5b4f4dc51d9f4d6f2cb60d4a49b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"compressible@npm:~2.0.16, compressible@npm:~2.0.18":
|
||||
version: 2.0.18
|
||||
resolution: "compressible@npm:2.0.18"
|
||||
@ -9378,6 +9459,7 @@ __metadata:
|
||||
"@rsdoctor/rspack-plugin": "npm:0.4.13"
|
||||
"@rspack/cli": "npm:1.2.3"
|
||||
"@rspack/core": "npm:1.2.3"
|
||||
"@shoelace-style/shoelace": "npm:2.20.0"
|
||||
"@thomasloven/round-slider": "npm:0.6.0"
|
||||
"@types/babel__plugin-transform-runtime": "npm:7.9.5"
|
||||
"@types/chromecast-caf-receiver": "npm:6.0.21"
|
||||
@ -12475,6 +12557,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qr-creator@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "qr-creator@npm:1.0.0"
|
||||
checksum: 10/77325a895fabfc899a54f0fc4598696dc234dc5056714181bbadb62bb15944366be7cd56ec19e36eb6e92a99f086143435f654855e512726bd8923149d94f709
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qr-scanner@npm:1.4.2":
|
||||
version: 1.4.2
|
||||
resolution: "qr-scanner@npm:1.4.2"
|
||||
|
Loading…
x
Reference in New Issue
Block a user