Skip to content

Commit e906d36

Browse files
feat: replace balance wave loading with subtle header spinner (#100)
1 parent 1c7344f commit e906d36

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

src/app/layouts/PageLayout/Header.tsx

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC } from 'react';
1+
import React, { FC, useEffect, useState } from 'react';
22

33
import classNames from 'clsx';
44

@@ -9,7 +9,8 @@ import { openInFullPage, useAppEnv } from 'app/env';
99
import { ReactComponent as ChevronDownIcon } from 'app/icons/chevron-down.svg';
1010
import { ReactComponent as MaximiseIcon } from 'app/icons/maximise.svg';
1111
import ContentContainer from 'app/layouts/ContentContainer';
12-
import { useAccount } from 'lib/miden/front';
12+
import { useAccount, useAllBalances, useAllTokensBaseMetadata } from 'lib/miden/front';
13+
import { useWalletStore } from 'lib/store';
1314
import { Link } from 'lib/woozie';
1415

1516
import { HeaderSelectors } from './Header.selectors';
@@ -33,9 +34,39 @@ const Header: FC = () => {
3334

3435
export default Header;
3536

37+
const SyncSpinner: FC<{ visible: boolean }> = ({ visible }) => (
38+
<div
39+
className="animate-spin sync-spinner-fade"
40+
style={{
41+
width: 16,
42+
height: 16,
43+
border: '2px solid #E5E7EB',
44+
borderTopColor: '#F97316',
45+
borderRadius: '50%',
46+
opacity: visible ? 1 : 0,
47+
transition: 'opacity 300ms ease-in-out'
48+
}}
49+
/>
50+
);
51+
3652
const Control: FC = () => {
3753
const account = useAccount();
3854
const { popup } = useAppEnv();
55+
const allTokensBaseMetadata = useAllTokensBaseMetadata();
56+
const { isLoading: isLoadingBalances } = useAllBalances(account.publicKey, allTokensBaseMetadata);
57+
const hasCompletedInitialSync = useWalletStore(s => s.hasCompletedInitialSync);
58+
const isSyncing = isLoadingBalances || !hasCompletedInitialSync;
59+
60+
// Show spinner only if syncing takes > 1s, then fade out over 300ms
61+
const [showSpinner, setShowSpinner] = useState(false);
62+
useEffect(() => {
63+
if (isSyncing) {
64+
const showTimeout = setTimeout(() => setShowSpinner(true), 1000);
65+
return () => clearTimeout(showTimeout);
66+
}
67+
const hideTimeout = setTimeout(() => setShowSpinner(false), 300);
68+
return () => clearTimeout(hideTimeout);
69+
}, [isSyncing]);
3970

4071
const handleMaximiseViewClick = () => {
4172
openInFullPage();
@@ -69,6 +100,7 @@ const Control: FC = () => {
69100
</Link>
70101
</div>
71102
<div className="flex items-center gap-2">
103+
{showSpinner && <SyncSpinner visible={isSyncing} />}
72104
<NetworkSelect className="self-end" />
73105
{popup && (
74106
<Button

src/app/pages/Explore/Tokens.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import { useTranslation } from 'react-i18next';
66
import useMidenFaucetId from 'app/hooks/useMidenFaucetId';
77
import { Avatar } from 'components/Avatar';
88
import { CardItem } from 'components/CardItem';
9-
import { SyncWaveBackground } from 'components/SyncWaveBackground';
109
import { useAccount, useAllTokensBaseMetadata, useAllBalances } from 'lib/miden/front';
11-
import { useWalletStore } from 'lib/store';
1210
import { navigate } from 'lib/woozie';
1311
import { truncateAddress } from 'utils/string';
1412

@@ -17,14 +15,7 @@ const Tokens: FC = () => {
1715
const account = useAccount();
1816
const { t } = useTranslation();
1917
const allTokensBaseMetadata = useAllTokensBaseMetadata();
20-
const { data: allTokenBalances = [], isLoading: isLoadingBalances } = useAllBalances(
21-
account.publicKey,
22-
allTokensBaseMetadata
23-
);
24-
const hasCompletedInitialSync = useWalletStore(s => s.hasCompletedInitialSync);
25-
26-
// Show loading indicator during initial balance fetch and first chain sync
27-
const showLoadingWave = isLoadingBalances || !hasCompletedInitialSync;
18+
const { data: allTokenBalances = [] } = useAllBalances(account.publicKey, allTokensBaseMetadata);
2819

2920
return (
3021
<>
@@ -41,7 +32,6 @@ const Tokens: FC = () => {
4132
const { tokenId, metadata } = asset;
4233
return (
4334
<div key={tokenId} className="relative flex">
44-
<SyncWaveBackground isSyncing={showLoadingWave} className="rounded-lg" />
4535
<CardItem
4636
iconLeft={
4737
<Avatar size="lg" image={isMiden ? '/misc/miden.png' : '/misc/token-logos/default.svg'} />

src/main.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,8 @@ button,
263263
animation-duration: 1s !important;
264264
animation-delay: 0s !important;
265265
}
266+
267+
/* Re-enable sync spinner fade transition (override the global disable) */
268+
.extension-no-animations .sync-spinner-fade {
269+
transition: opacity 300ms ease-in-out !important;
270+
}

0 commit comments

Comments
 (0)