Skip to content
File

Blob: worker/src/client/exhibit/details/signal-popover.tsx

typescript50 lines
1import type { Hardware } from '@/shared/contracts/hardware.ts';
2import { HardwareDetails } from './hardware-details.tsx';
3import { AnchoredDialog } from '@/client/ui/anchored-dialog.tsx';
4import { descriptions } from './signal-descriptions.ts';
5import type { SignalDetails } from '@/client/exhibit/diagram/diagram-model.ts';
6import type { SpectrumStats } from '@/shared/contracts/robot.ts';
7 
8export function SignalPopover({
9 details,
10 analysis,
11 hardware,
12 radioStack,
13 close,
14}: {
15 details: SignalDetails | null;
16 analysis?: SpectrumStats;
17 hardware?: Hardware | null;
18 radioStack?: number;
19 close: () => void;
20}) {
21 const detail = details ? descriptions[details.selection] : undefined;
22 return (
23 <AnchoredDialog
24 id="signal-detail"
25 closeLabel="Close signal explanation"
26 anchor={details?.anchor ?? null}
27 title={detail?.title}
28 onClose={close}
29 >
30 {detail?.chain ? (
31 <p className="mb-3 font-mono text-[11px] leading-relaxed text-spectrum">{detail.chain}</p>
32 ) : null}
33 <p>{detail?.body}</p>
34 {details?.selection === 'board' ? (
35 <HardwareDetails
36 hardware={hardware}
37 radioStack={radioStack}
38 analysisStack={analysis?.stackFree}
39 />
40 ) : null}
41 {details?.selection === 'spectrum' && analysis ? (
42 <p className="mt-3 border-t border-line pt-3 text-xs leading-relaxed text-muted">
43 Analysis: {(analysis.meanUs / 1000).toFixed(2)} ms/packet average · {analysis.errors}{' '}
44 decode errors. Task timing, not CPU use.
45 </p>
46 ) : null}
47 </AnchoredDialog>
48 );
49}