Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/tangle-cloud/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Navigate, Route, Routes } from 'react-router';
import { lazy, Suspense, type FC, type ReactNode } from 'react';
import Layout from '../components/Layout';
import ScrollToTop from '../components/ScrollToTop';
import Providers from './providers';
import { PagePath } from '../types';
import { Skeleton } from '@tangle-network/sandbox-ui/primitives';
Expand Down Expand Up @@ -70,6 +71,7 @@ const withLayout = (LayoutCmp: FC<{ children: ReactNode }>, Page: FC) => (
const App: FC = () => {
return (
<Providers>
<ScrollToTop />
<Layout>
<Routes>
<Route
Expand Down
33 changes: 33 additions & 0 deletions apps/tangle-cloud/src/components/ScrollToTop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

/**
* Reset the window scroll position to (0, 0) on every pathname change.
*
* The default `react-router-dom` `<BrowserRouter>` is path-aware but
* scroll-naive: navigating from a long /blueprints listing to /rewards
* lands the next page already scrolled wherever the previous page was,
* which makes transitions feel broken (the user has to scroll up to
* read the heading of the new page).
*
* Drop this component anywhere inside the router tree — it renders
* `null` and only runs an effect.
*
* NOTE: pathname-only dependency is deliberate. We do NOT scroll on
* search-param or hash changes, because some pages use those for in-page
* tab state and an unsolicited scroll would yank the viewport away.
*/
const ScrollToTop = () => {
const { pathname } = useLocation();

useEffect(() => {
// Use 'instant' (not 'smooth') so the new page is at the top before
// the first paint — smooth-scroll across route transitions looks
// janky because the previous page's content briefly remains visible.
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
}, [pathname]);

return null;
};

export default ScrollToTop;
2 changes: 1 addition & 1 deletion apps/tangle-cloud/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const SIDEBAR_ITEMS: SidebarItem[] = [
Icon: CoinsLineIcon,
},
{
name: 'Payments',
name: 'Private Payments',
href: PagePath.PAYMENTS_POOL,
isInternal: true,
Icon: ShieldKeyholeLineIcon,
Expand Down
13 changes: 12 additions & 1 deletion apps/tangle-cloud/src/pages/rewards/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,18 @@ const RewardsPage: FC = () => {
<Skeleton className="h-16 rounded-md" />
</div>
) : rewardHistoryError ? (
<ErrorMessage>Could not load claim history.</ErrorMessage>
// Render an empty-state instead of a red error when the
// indexer is simply absent (e.g. `testnet` env with no
// VITE_ENVIO_TESTNET_ENDPOINT configured). The original
// `<ErrorMessage>` here surfaced an alarming
// "Could not load claim history" banner on every page
// load — that's the UX equivalent of a 500, but the
// actual cause is "no historical data source", which is
// a legitimate empty state.
<EmptyState
title="Claim history unavailable on this network"
description="The indexed history endpoint is not configured for this network. Past reward claims will appear here once the indexer is online."
/>
) : rewardHistory?.length ? (
<RewardClaimsTable
entries={rewardHistory}
Expand Down
Loading