✨ feat(ui): Replace Spin with animated Skeleton in UsageLogsActions
Summary • Swapped out the obsolete `<Spin>` loader for a modern, animated Semi-UI `<Skeleton>` implementation in `UsageLogsActions.jsx`. Details 1. Added animated Skeleton placeholders mirroring real Tag sizes (108 × 26, 65 × 26, 64 × 26). 2. Introduced `showSkeleton` state with 500 ms minimum display to eliminate flicker. 3. Leveraged existing `showStat` flag to decide when real data is ready. 4. Ensured only the three Tags are under loading state - `CompactModeToggle` renders immediately. 5. Adopted CardTable‐style `Skeleton` pattern (`loading` + `placeholder`) for consistency. 6. Removed all references to the original `Spin` component. Outcome A smoother and more consistent loading experience across devices, aligning UI behaviour with the project’s latest Skeleton standards.
This commit is contained in:
@@ -17,21 +17,51 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
For commercial licensing, please contact support@quantumnous.com
|
For commercial licensing, please contact support@quantumnous.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { Tag, Space, Spin } from '@douyinfe/semi-ui';
|
import { Tag, Space, Skeleton } from '@douyinfe/semi-ui';
|
||||||
import { renderQuota } from '../../../helpers';
|
import { renderQuota } from '../../../helpers';
|
||||||
import CompactModeToggle from '../../common/ui/CompactModeToggle';
|
import CompactModeToggle from '../../common/ui/CompactModeToggle';
|
||||||
|
|
||||||
const LogsActions = ({
|
const LogsActions = ({
|
||||||
stat,
|
stat,
|
||||||
loadingStat,
|
loadingStat,
|
||||||
|
showStat,
|
||||||
compactMode,
|
compactMode,
|
||||||
setCompactMode,
|
setCompactMode,
|
||||||
t,
|
t,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [showSkeleton, setShowSkeleton] = useState(loadingStat);
|
||||||
|
const needSkeleton = !showStat || showSkeleton;
|
||||||
|
const loadingStartRef = useRef(Date.now());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loadingStat) {
|
||||||
|
loadingStartRef.current = Date.now();
|
||||||
|
setShowSkeleton(true);
|
||||||
|
} else {
|
||||||
|
const elapsed = Date.now() - loadingStartRef.current;
|
||||||
|
const remaining = Math.max(0, 500 - elapsed);
|
||||||
|
if (remaining === 0) {
|
||||||
|
setShowSkeleton(false);
|
||||||
|
} else {
|
||||||
|
const timer = setTimeout(() => setShowSkeleton(false), remaining);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [loadingStat]);
|
||||||
|
|
||||||
|
// Skeleton placeholder layout (three tag-size blocks)
|
||||||
|
const placeholder = (
|
||||||
|
<Space>
|
||||||
|
<Skeleton.Title style={{ width: 108, height: 26, borderRadius: 6 }} />
|
||||||
|
<Skeleton.Title style={{ width: 65, height: 26, borderRadius: 6 }} />
|
||||||
|
<Skeleton.Title style={{ width: 64, height: 26, borderRadius: 6 }} />
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Spin spinning={loadingStat}>
|
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-2 w-full">
|
||||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-2 w-full">
|
<Skeleton loading={needSkeleton} active placeholder={placeholder}>
|
||||||
<Space>
|
<Space>
|
||||||
<Tag
|
<Tag
|
||||||
color='blue'
|
color='blue'
|
||||||
@@ -68,14 +98,14 @@ const LogsActions = ({
|
|||||||
TPM: {stat.tpm}
|
TPM: {stat.tpm}
|
||||||
</Tag>
|
</Tag>
|
||||||
</Space>
|
</Space>
|
||||||
|
</Skeleton>
|
||||||
|
|
||||||
<CompactModeToggle
|
<CompactModeToggle
|
||||||
compactMode={compactMode}
|
compactMode={compactMode}
|
||||||
setCompactMode={setCompactMode}
|
setCompactMode={setCompactMode}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user