mirror of
https://github.com/mue/mue.git
synced 2026-06-05 23:45:53 +02:00
feat(MainModal): implement sidebar skeleton loader and enhance loading experience
This commit is contained in:
@@ -182,7 +182,7 @@ function MainModal({ modalClose, deepLinkData }) {
|
||||
canGoForward={canGoForward}
|
||||
/>
|
||||
<div style={{ flex: 1, display: 'flex', overflow: 'hidden', minHeight: 0 }}>
|
||||
<Suspense fallback={<ModalLoader />}>
|
||||
<Suspense fallback={<ModalLoader currentTab={currentTab} />}>
|
||||
<TabComponent
|
||||
key={currentTab}
|
||||
changeTab={handleChangeTab}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import variables from 'config/variables';
|
||||
import SidebarSkeleton from './SidebarSkeleton';
|
||||
|
||||
const ModalLoader = () => (
|
||||
const ModalLoader = ({ currentTab }) => (
|
||||
<div style={{ display: 'flex', width: '100%', minHeight: '100%' }}>
|
||||
<div className="modalSidebar">
|
||||
<span className="mainTitle">Mue</span>
|
||||
<SidebarSkeleton currentTab={currentTab} />
|
||||
</div>
|
||||
<div className="modalTabContent">
|
||||
<div className="emptyItems">
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { TAB_TYPES } from '../constants/tabConfig';
|
||||
|
||||
// Tab-specific configurations with exact divider positions
|
||||
const TAB_CONFIGS = {
|
||||
[TAB_TYPES.SETTINGS]: {
|
||||
itemCount: 16, // Excluding experimental
|
||||
dividerPositions: [10, 12], // After Weather, Language
|
||||
textWidths: [80, 100, 70, 90, 85, 75, 80, 95, 90, 75, 85, 90, 85, 80, 70, 95], // Fixed widths in pixels
|
||||
},
|
||||
[TAB_TYPES.DISCOVER]: {
|
||||
itemCount: 5,
|
||||
dividerPositions: [0], // After "All"
|
||||
textWidths: [60, 95, 95, 110, 90], // Fixed widths
|
||||
},
|
||||
[TAB_TYPES.LIBRARY]: {
|
||||
itemCount: 0, // Library doesn't show sidebar
|
||||
dividerPositions: [],
|
||||
textWidths: [],
|
||||
},
|
||||
};
|
||||
|
||||
const SidebarSkeleton = ({ currentTab = TAB_TYPES.SETTINGS }) => {
|
||||
const config = TAB_CONFIGS[currentTab] || TAB_CONFIGS[TAB_TYPES.SETTINGS];
|
||||
|
||||
// Library tab doesn't show sidebar
|
||||
if (config.itemCount === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="sidebarSkeleton">
|
||||
{Array.from({ length: config.itemCount }).map((_, index) => {
|
||||
const hasDivider = config.dividerPositions.includes(index);
|
||||
const textWidth = config.textWidths[index] || 80;
|
||||
|
||||
return (
|
||||
<div key={index}>
|
||||
<div className="skeletonItem">
|
||||
<div className="iconPlaceholder pulse" />
|
||||
<div className="textPlaceholder pulse" style={{ width: `${textWidth}px` }} />
|
||||
</div>
|
||||
{hasDivider && <hr className="skeletonDivider" />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarSkeleton;
|
||||
@@ -74,3 +74,54 @@
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
// Sidebar skeleton loader
|
||||
.sidebarSkeleton {
|
||||
padding: 0.5rem 0.2rem;
|
||||
|
||||
.skeletonItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
margin: 0.2rem;
|
||||
pointer-events: none;
|
||||
|
||||
.iconPlaceholder {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
border-radius: 6px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
flex-shrink: 0;
|
||||
|
||||
@include themed {
|
||||
background: t($modal-sidebarActive);
|
||||
}
|
||||
}
|
||||
|
||||
.textPlaceholder {
|
||||
height: 18px;
|
||||
border-radius: 6px;
|
||||
|
||||
@include themed {
|
||||
background: t($modal-sidebarActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skeletonDivider {
|
||||
@include themed {
|
||||
height: 1px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent 0%,
|
||||
t($modal-sidebarActive) 20%,
|
||||
t($modal-sidebarActive) 80%,
|
||||
transparent 100%
|
||||
);
|
||||
margin: 0.5rem 1.75rem;
|
||||
border: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ body {
|
||||
width: 100%;
|
||||
background: linear-gradient(-90deg, #efefef 0%, #ccc 50%, #efefef 100%);
|
||||
background-size: 400% 400%;
|
||||
animation: pulse 1.2s ease-in-out infinite;
|
||||
animation: pulse 0.8s ease-in-out infinite;
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
@@ -230,7 +230,7 @@ body {
|
||||
width: 100%;
|
||||
background: linear-gradient(-90deg, #000 0%, rgb(83 83 83) 50%, #000 100%);
|
||||
background-size: 400% 400%;
|
||||
animation: pulse 1.2s ease-in-out infinite;
|
||||
animation: pulse 0.8s ease-in-out infinite;
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
|
||||
Reference in New Issue
Block a user