Files
Sam SelikoffandGitHub a345140862 Instant navs devtools revamp (#94027)
This updates the Instant Navs DevTools panel to better model capture
state across pending, SPA, and MPA navigations.

- Revamps the Navigation Inspector UI states, controls, focus behavior,
and panel transitions
- Resets capture state when closing the panel from active capture states
- Keeps MPA reloads and root-layout-crossing navigations from briefly
showing stale or optimistic SPA state
- Consolidates the panel state flow so cookie state, re-arming, and
rendered UI status are easier to follow
- Expands the instant navs fixture and tests to cover SPA captures, MPA
captures, reloads, close/reset, Continue Rendering, and root-layout MPA
links
2026-05-22 12:54:48 -05:00

141 lines
2.9 KiB
TypeScript

'use client'
import { Suspense } from 'react'
import { useSearchParams, usePathname, useParams } from 'next/navigation'
function Box({
label,
children,
}: {
label: string
children: React.ReactNode
}) {
return (
<div
style={{
background: '#fff',
border: '1px solid #ddd',
borderRadius: 8,
padding: '1rem',
marginBottom: '0.75rem',
}}
>
<div
style={{
fontSize: '0.7rem',
textTransform: 'uppercase',
letterSpacing: '0.05em',
color: '#888',
marginBottom: '0.5rem',
}}
>
{label}
</div>
{children}
</div>
)
}
function PathnameDisplay() {
const pathname = usePathname()
return (
<p style={{ margin: 0 }}>
<code>{pathname}</code>
</p>
)
}
function ParamsDisplay() {
const params = useParams()
return (
<p style={{ margin: 0 }} data-testid="client-params">
<code>slug={String(params.slug ?? '(none)')}</code>
</p>
)
}
function SearchParamsDisplay() {
const searchParams = useSearchParams()
return (
<p style={{ margin: 0 }} data-testid="client-search-param">
<code>?search={searchParams.get('search') ?? '(none)'}</code>
</p>
)
}
export function ClientFeatures() {
return (
<>
<Box label="Static Client Content">
<p style={{ margin: 0 }}>
This text is rendered by a Client Component. It is part of the JS
bundle and renders immediately.
</p>
</Box>
<Box label="usePathname()">
<Suspense
fallback={
<p style={{ margin: 0 }}>
<span
className="skeleton"
style={{
display: 'inline-block',
width: 120,
height: '1em',
verticalAlign: 'middle',
}}
/>
</p>
}
>
<PathnameDisplay />
</Suspense>
</Box>
<Box label="useParams()">
<Suspense
fallback={
<p style={{ margin: 0 }}>
<span
className="skeleton"
style={{
display: 'inline-block',
width: 120,
height: '1em',
verticalAlign: 'middle',
}}
/>
</p>
}
>
<ParamsDisplay />
</Suspense>
</Box>
<Box label="useSearchParams()">
<Suspense
fallback={
<p style={{ margin: 0 }}>
<span
className="skeleton"
style={{
display: 'inline-block',
width: 120,
height: '1em',
verticalAlign: 'middle',
}}
/>
</p>
}
>
<SearchParamsDisplay />
</Suspense>
</Box>
</>
)
}