/ tutorials / wave-acoustics
Sign in
tutorials / wave-acoustics
wave-acoustics / src / plot / Legend.tsx
62 lines · 1.9 KBCodeBlameHistory
3export interface LegendItem {
4 label: string
5 color: string
6 /** stroke-dasharray for a line swatch */
7 dash?: string
8 shape?: 'line' | 'dot' | 'cross'
9 /** e.g. the max error for this series, shown after the label */
10 value?: string
13/**
14 * Identity is never carried by colour alone: every series that appears in a
15 * plot appears here too, and the ones the reader most needs are also labelled
16 * directly on the plot.
17 */
18export default function Legend({
19 items,
20 onHover,
21 active,
22}: {
23 items: LegendItem[]
24 /** hovering an entry reports its index, so the plot can pick that curve out */
25 onHover?: (k: number | null) => void
26 /** the entry to show as picked out; the others are dimmed */
27 active?: number | null
28}) {
29 return (
30 <div className="legend" onPointerLeave={onHover ? () => onHover(null) : undefined}>
31 {items.map((it, k) => (
32 <span
33 className={active != null && active !== k ? 'legend-item dim' : 'legend-item'}
34 key={it.label}
35 onPointerEnter={onHover ? () => onHover(k) : undefined}
36 style={onHover ? { cursor: 'default' } : undefined}
37 >
38 <svg width={18} height={10} aria-hidden="true">
39 {it.shape === 'dot' ? (
40 <circle cx={9} cy={5} r={3.5} fill={it.color} stroke={ink.grid} strokeWidth={1} />
41 ) : it.shape === 'cross' ? (
42 <path d="M5 1 L13 9 M13 1 L5 9" stroke={it.color} strokeWidth={2} strokeLinecap="round" />
43 ) : (
44 <line
45 x1={1}
46 x2={17}
47 y1={5}
48 y2={5}
49 stroke={it.color}
50 strokeWidth={2}
51 strokeDasharray={it.dash}
52 strokeLinecap="round"
53 />
54 )}
55 </svg>
56 <span>{it.label}</span>
57 {it.value && <span className="legend-value">{it.value}</span>}
58 </span>
59 ))}
60 </div>
61 )
↑↓ move↵openescclose