SPB Git forge

spb/market-atlas

Public
12commits 1branches 0releases
1.1 MBsize
maindefault branch
10 days agolast push
TypeScript 96.7% SQL 1.6% CSS 0.8% JavaScript 0.5%
2.5 KB · 54 lines tsx
Raw Blame History
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