Browse Source

Add loading indicator to sidebar links (#4693)

* add loading indicator to sidebar links

* fix clicking on same route whould show indicator

* maybe final?

* handle routeChangeError as well as cleaning up timeout

* clearing timeout before creating one instead of routeChangeError

* rm unused

* add license header

* Update usePendingRoute.ts

Co-authored-by: dan <dan.abramov@gmail.com>
main
Yousef M. El-Gohary 3 years ago
committed by GitHub
parent
commit
9721c9d11d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      beta/src/components/Layout/Sidebar/SidebarLink.tsx
  2. 6
      beta/src/components/Layout/Sidebar/SidebarRouteTree.tsx
  3. 41
      beta/src/hooks/usePendingRoute.ts

5
beta/src/components/Layout/Sidebar/SidebarLink.tsx

@ -21,6 +21,7 @@ interface SidebarLinkProps {
isExpanded?: boolean;
isBreadcrumb?: boolean;
hideArrow?: boolean;
isPending: boolean;
}
export function SidebarLink({
@ -32,6 +33,7 @@ export function SidebarLink({
isExpanded,
isBreadcrumb,
hideArrow,
isPending,
}: SidebarLinkProps) {
const ref = React.useRef<HTMLAnchorElement>(null);
const isMobile = useIsMobile();
@ -67,8 +69,11 @@ export function SidebarLink({
!selected && !heading,
'text-base text-link dark:text-link-dark bg-highlight dark:bg-highlight-dark border-blue-40 hover:bg-highlight hover:text-link dark:hover:bg-highlight-dark dark:hover:text-link-dark':
selected,
'dark:bg-gray-60 bg-gray-3 dark:hover:bg-gray-60 hover:bg-gray-3':
isPending,
}
)}>
{/* This here needs to be refactored ofc */}
{title}
{isExpanded != null && !heading && !hideArrow && (
<span

6
beta/src/components/Layout/Sidebar/SidebarRouteTree.tsx

@ -11,6 +11,7 @@ import {useRouteMeta} from '../useRouteMeta';
import {SidebarLink} from './SidebarLink';
import useCollapse from 'react-collapsed';
import {useLayoutEffect} from 'react';
import usePendingRoute from 'hooks/usePendingRoute';
interface SidebarRouteTreeProps {
isMobile?: boolean;
@ -77,8 +78,9 @@ export function SidebarRouteTree({
}: SidebarRouteTreeProps) {
const {breadcrumbs} = useRouteMeta(routeTree);
const {pathname} = useRouter();
const slug = pathname;
const pendingRoute = usePendingRoute();
const slug = pathname;
const currentRoutes = routeTree.routes as RouteItem[];
const expandedPath = currentRoutes.reduce(
(acc: string | undefined, curr: RouteItem) => {
@ -121,6 +123,7 @@ export function SidebarRouteTree({
<SidebarLink
key={`${title}-${path}-${level}-link`}
href={pagePath}
isPending={pendingRoute === pagePath}
selected={selected}
level={level}
title={title}
@ -143,6 +146,7 @@ export function SidebarRouteTree({
return (
<li key={`${title}-${path}-${level}-link`}>
<SidebarLink
isPending={pendingRoute === pagePath}
href={pagePath}
selected={selected}
level={level}

41
beta/src/hooks/usePendingRoute.ts

@ -0,0 +1,41 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
import {useRouter} from 'next/router';
import React from 'react';
const usePendingRoute = () => {
const {events} = useRouter();
const [pendingRoute, setPendingRoute] = React.useState<string | null>(null);
const currentRoute = React.useRef<string | null>(null);
React.useEffect(() => {
let routeTransitionTimer: any = null;
const handleRouteChangeStart = (url: string) => {
clearTimeout(routeTransitionTimer);
routeTransitionTimer = setTimeout(() => {
if (currentRoute.current !== url) {
currentRoute.current = url;
setPendingRoute(url);
}
}, 100);
};
const handleRouteChangeComplete = () => {
setPendingRoute(null);
clearTimeout(routeTransitionTimer);
};
events.on('routeChangeStart', handleRouteChangeStart);
events.on('routeChangeComplete', handleRouteChangeComplete);
return () => {
events.off('routeChangeStart', handleRouteChangeStart);
events.off('routeChangeComplete', handleRouteChangeComplete);
clearTimeout(routeTransitionTimer);
};
}, []);
return pendingRoute;
};
export default usePendingRoute;
Loading…
Cancel
Save