Viewer Frame
@genomics/viewer-frame
Loading, error, and empty states for async viewers.
Preview
phyloP conservation
chr17:7,668,421–7,687,550 · streamed from UCSC
19.1 kb
100-way vertebrate alignment · 5 bp bins
About
Domain data is never in hand at first paint — a bigWig arrives by HTTP range, a structure from AFDB, an alignment from a job queue — so a viewer has four states, not one. And 'empty' is its own message here: 'no features in this window' is a fact about where you're looking, not about what you loaded. ViewerFrame owns the header, toolbar slot, skeleton, error, and empty copy, holds a stable height so the page doesn't jump when data lands, and keeps children mounted through a refetch so a canvas or WebGL context survives. useViewerData pairs with it: abortable loads, last-good data retained, status derived.
Usage
import { ViewerFrame, useViewerData } from "@/components/ui/viewer-frame"
const { data, status, error, reload } = useViewerData(
(signal) => fetchFeatures(locus, signal),
[locus],
{ isEmpty: (d) => d.length === 0 }
)
<ViewerFrame title="GENCODE" status={status} error={error} onRetry={reload} height={220}>
<TrackViewer tracks={data ?? []} />
</ViewerFrame>Registry dependencies
Source:
components/ui/viewer-frame.tsx