Skip to content

Commit 3199f27

Browse files
bpierreo-az
authored andcommitted
fix(explorer): smooth header loading states
1 parent b522581 commit 3199f27

2 files changed

Lines changed: 70 additions & 50 deletions

File tree

apps/explorer/src/comps/Breadcrumbs.tsx

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -180,62 +180,82 @@ export function Breadcrumbs(props: Breadcrumbs.Props) {
180180

181181
const isEmpty =
182182
(resolvedPathname === '/' && !hasPendingCrumb) || displayCrumbs.length === 0
183+
const [isVisible, setIsVisible] = React.useState(false)
184+
185+
React.useEffect(() => {
186+
if (isEmpty) {
187+
setIsVisible(false)
188+
return
189+
}
190+
191+
const frame = requestAnimationFrame(() => setIsVisible(true))
192+
return () => cancelAnimationFrame(frame)
193+
}, [isEmpty])
183194

184195
return (
185196
<nav
186197
aria-label="Breadcrumb"
198+
aria-hidden={isEmpty}
187199
className={cx(
188-
'flex items-center gap-1 text-[12px] text-secondary overflow-x-auto overflow-y-hidden scrollbar-none h-5 pl-0.5',
189-
isEmpty && 'invisible',
200+
'flex items-center gap-1 text-[12px] text-secondary overflow-x-auto overflow-y-hidden scrollbar-none h-5 pl-0.5 origin-left transition-[opacity,scale] duration-[80ms]',
201+
isVisible
202+
? 'opacity-100 scale-100'
203+
: 'opacity-0 scale-[0.97] pointer-events-none',
190204
className,
191205
)}
192206
>
193-
<Link
194-
to="/"
195-
className="flex items-center gap-1 text-tertiary hover:text-accent press-down shrink-0 outline-none focus-visible:text-accent"
196-
title="Home"
197-
>
198-
<Home className="size-3.5" />
199-
</Link>
200-
201-
{displayCrumbs.map((crumb, index) => {
202-
const isLast = index === displayCrumbs.length - 1
203-
const isPending = isLast && hasPendingCrumb
204-
return (
205-
<React.Fragment key={crumb.path}>
206-
<ChevronRight className="size-3 text-tertiary shrink-0" />
207-
{isLast ? (
208-
<span
209-
className={cx(
210-
'font-medium truncate max-w-[120px]',
211-
isPending ? 'text-secondary animate-pulse' : 'text-primary',
207+
{!isEmpty && (
208+
<>
209+
<Link
210+
to="/"
211+
className="flex items-center gap-1 text-tertiary hover:text-accent press-down shrink-0 outline-none focus-visible:text-accent"
212+
title="Home"
213+
>
214+
<Home className="size-3.5" />
215+
</Link>
216+
217+
{displayCrumbs.map((crumb, index) => {
218+
const isLast = index === displayCrumbs.length - 1
219+
const isPending = isLast && hasPendingCrumb
220+
return (
221+
<React.Fragment key={crumb.path}>
222+
<ChevronRight className="size-3 text-tertiary shrink-0" />
223+
{isLast ? (
224+
<span
225+
className={cx(
226+
'font-medium truncate max-w-[120px]',
227+
isPending
228+
? 'text-secondary animate-pulse'
229+
: 'text-primary',
230+
)}
231+
title={crumb.path}
232+
>
233+
{crumb.label}
234+
</span>
235+
) : (
236+
<Link
237+
to={crumb.path}
238+
className="text-secondary hover:text-accent press-down truncate max-w-[120px] outline-none focus-visible:text-accent"
239+
title={crumb.path}
240+
>
241+
{crumb.label}
242+
</Link>
212243
)}
213-
title={crumb.path}
214-
>
215-
{crumb.label}
216-
</span>
217-
) : (
218-
<Link
219-
to={crumb.path}
220-
className="text-secondary hover:text-accent press-down truncate max-w-[120px] outline-none focus-visible:text-accent"
221-
title={crumb.path}
222-
>
223-
{crumb.label}
224-
</Link>
225-
)}
226-
</React.Fragment>
227-
)
228-
})}
229-
230-
{crumbs.length > 1 && (
231-
<button
232-
type="button"
233-
onClick={clearCrumbs}
234-
className="text-tertiary hover:text-primary press-down shrink-0 outline-none focus-visible:text-accent cursor-pointer"
235-
title="Clear navigation history"
236-
>
237-
<X className="size-3" />
238-
</button>
244+
</React.Fragment>
245+
)
246+
})}
247+
248+
{crumbs.length > 1 && (
249+
<button
250+
type="button"
251+
onClick={clearCrumbs}
252+
className="text-tertiary hover:text-primary press-down shrink-0 outline-none focus-visible:text-accent cursor-pointer"
253+
title="Clear navigation history"
254+
>
255+
<X className="size-3" />
256+
</button>
257+
)}
258+
</>
239259
)}
240260
</nav>
241261
)
@@ -257,7 +277,7 @@ export function BreadcrumbsSlot(props: BreadcrumbsSlot.Props) {
257277
return () => setSlotEl(null)
258278
}, [setSlotEl])
259279

260-
return <div ref={ref} className={className} />
280+
return <div ref={ref} className={cx('min-h-5', className)} />
261281
}
262282

263283
export namespace BreadcrumbsSlot {

apps/explorer/src/comps/Header.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ export namespace Header {
176176
params={{ id: blockNumber != null ? String(blockNumber) : 'latest' }}
177177
className={cx(
178178
className,
179-
'flex items-center gap-[6px] text-[15px] font-medium text-secondary press-down transition-opacity duration-300',
180-
isReady ? 'opacity-100' : 'opacity-0',
179+
'flex items-center gap-[6px] text-[15px] font-medium text-secondary press-down origin-right transition-[opacity,scale] duration-[80ms]',
180+
isReady ? 'opacity-100 scale-100' : 'opacity-0 scale-[0.97]',
181181
)}
182182
title="View latest block"
183183
>

0 commit comments

Comments
 (0)