Skip to content

Commit

Permalink
Merge pull request #1279 from rainlanguage/1268-feedback-while-the-pa…
Browse files Browse the repository at this point in the history
…ge-is-loading

Add progress bar while navigating
  • Loading branch information
hardyjosh authored Feb 12, 2025
2 parents a4da043 + 746a6dc commit 5852d6e
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 13 deletions.
46 changes: 46 additions & 0 deletions packages/webapp/src/__tests__/LoadingWrapper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { render, screen, waitFor } from '@testing-library/svelte';
import { get } from 'svelte/store';
import LoadingWrapper from '$lib/components/LoadingWrapper.svelte';
import { isNavigating } from '$lib/stores/loading';

vi.mock('$app/navigation', () => ({
beforeNavigate: vi.fn((cb) => setTimeout(cb, 10)), // Simulate navigation start
afterNavigate: vi.fn((cb) => setTimeout(cb, 50)) // Simulate navigation end
}));

describe('LoadingWrapper', () => {
it('displays progress bar on navigation start', async () => {
render(LoadingWrapper);

// Simulate navigation start
await waitFor(() => {
expect(screen.getByTestId('progressbar')).toBeInTheDocument();
});
});

it('hides progress bar after navigation ends', async () => {
render(LoadingWrapper);

// Wait for navigation to finish
await waitFor(() => {
expect(get(isNavigating)).toBe(false);
});

// Ensure progress bar disappears
await waitFor(
() => {
const progressBar = screen.queryByTestId('progressbar');
expect(progressBar).not.toBeInTheDocument();
},
{ timeout: 600 }
);
});

it('does not show progress bar if no navigation occurs', () => {
render(LoadingWrapper);

// Progress bar should not exist initially
const progressBar = screen.queryByTestId('progressbar');
expect(progressBar).not.toBeInTheDocument();
});
});
44 changes: 44 additions & 0 deletions packages/webapp/src/lib/components/LoadingWrapper.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script lang="ts">
import { Progressbar } from 'flowbite-svelte';
import { beforeNavigate, afterNavigate } from '$app/navigation';
import { isNavigating } from '$lib/stores/loading';
import { tick } from 'svelte';
let progress = 0;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let interval: any;
// Gradually increase progress while navigating
const startLoading = () => {
isNavigating.set(true);
progress = 10; // Start at 10% so it's visible
clearInterval(interval);
interval = setInterval(() => {
if (progress < 90) {
progress += 5;
}
}, 300);
};
// Stop loading and reset progress
const stopLoading = async () => {
clearInterval(interval);
progress = 100;
await tick();
setTimeout(() => {
progress = 0; // Reset for next navigation
isNavigating.set(false);
}, 500);
};
beforeNavigate(startLoading);
afterNavigate(stopLoading);
</script>

{#if $isNavigating}
<div class="fixed left-0 top-0 z-50 w-full" data-testId="progressbar">
<Progressbar {progress} color="blue" animate size="h-1" />
</div>
{/if}

<slot />
3 changes: 3 additions & 0 deletions packages/webapp/src/lib/stores/loading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { writable } from 'svelte/store';

export const isNavigating = writable(false);
30 changes: 17 additions & 13 deletions packages/webapp/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import { injected } from '@wagmi/connectors';
import { type Chain } from '@wagmi/core/chains';
import { PUBLIC_WALLETCONNECT_PROJECT_ID } from '$env/static/public';
import { page } from '$app/stores';
import Homepage from '$lib/components/Homepage.svelte';
import LoadingWrapper from '$lib/components/LoadingWrapper.svelte';
// Query client for caching
const queryClient = new QueryClient({
defaultOptions: {
queries: {
Expand All @@ -36,16 +38,18 @@
</script>

<QueryClientProvider client={queryClient}>
{#if $page.url.pathname === '/'}
<Homepage {colorTheme} />
{:else}
<div
class="flex min-h-screen w-full justify-start bg-white dark:bg-gray-900 dark:text-gray-400"
>
<Sidebar {colorTheme} page={$page} />
<main class="mx-auto h-full w-full grow overflow-x-auto px-4 pt-14 lg:ml-64 lg:p-8">
<slot />
</main>
</div>
{/if}
<LoadingWrapper>
{#if $page.url.pathname === '/'}
<Homepage {colorTheme} />
{:else}
<div
class="flex min-h-screen w-full justify-start bg-white dark:bg-gray-900 dark:text-gray-400"
>
<Sidebar {colorTheme} page={$page} />
<main class="mx-auto h-full w-full grow overflow-x-auto px-4 pt-14 lg:ml-64 lg:p-8">
<slot />
</main>
</div>
{/if}
</LoadingWrapper>
</QueryClientProvider>

0 comments on commit 5852d6e

Please sign in to comment.