spb/market-atlas
Public
TypeScript 96.7%
SQL 1.6%
CSS 0.8%
JavaScript 0.5%
1import Link from "next/link";2import { ChangeCell } from "@/components/ui/price";3import { cx, EVENT_TYPE_LABEL, formatInt, instrumentHref } from "@/lib/format";4import type { Changes } from "@/lib/types";56/** "What changed" across markets in a window — counts derived from Market Atlas' own bars/events. */7export function ChangesPanel({ changes, className }: { changes: Changes; className?: string }) {8 return (9 <div className={cx("rounded-md border border-rule bg-surface p-4", className)}>10 <div className="flex items-baseline justify-between">11 <h3 className="text-[11px] font-medium uppercase tracking-wide text-ink-3">What changed · last {changes.window}</h3>12 <span className="text-[11px] text-ink-3">derived</span>13 </div>14 <div className="mt-2 grid grid-cols-3 gap-3">15 <Num n={changes.instruments_moved_over_1pct} label="moved >1%" sub={`of ${formatInt(changes.instruments_tracked)} tracked`} />16 <Num n={changes.events} label="events" />17 <Num n={changes.filings} label="filings" />18 </div>19 {changes.events_by_type.length > 0 && (20 <div className="mt-3 flex flex-wrap gap-1.5">21 {changes.events_by_type.slice(0, 6).map((t) => (22 <Link key={t.type} href={`/events?type=${t.type}`} className="rounded-full border border-rule px-2 py-0.5 text-[11px] text-ink-2 hover:border-rule-strong">23 {EVENT_TYPE_LABEL[t.type] ?? t.type} <span className="mono">{t.n}</span>24 </Link>25 ))}26 </div>27 )}28 {changes.top_movers.length > 0 && (29 <ul className="mt-3 divide-y divide-rule text-sm">30 {changes.top_movers.slice(0, 6).map((m) => (31 <li key={m.id} className="flex items-center justify-between py-1.5">32 <Link href={instrumentHref(m.id)} className="min-w-0">33 <span className="mono font-medium">{m.symbol}</span>34 <span className="ml-2 hidden truncate text-xs text-ink-3 sm:inline">{m.name}</span>35 </Link>36 <ChangeCell value={m.window_change_percent} className="text-xs" />37 </li>38 ))}39 </ul>40 )}41 </div>42 );43}4445function Num({ n, label, sub }: { n: number; label: string; sub?: string }) {46 return (47 <div>48 <div className="mono text-xl font-semibold tnum">{formatInt(n)}</div>49 <div className="text-[11px] text-ink-3">{label}</div>50 {sub && <div className="text-[10.5px] text-ink-3">{sub}</div>}51 </div>52 );53}54