PairExplorer

Screenshot pending.
When to use
When you have a small set of ranked item pairs (e.g. “sentence pairs ranked by disagreement across mask variants”) and want readers to click any row in the list to swap the right-hand detail panel — without a page reload, hash change, or tab reset. The detail panel renders the pair’s two sentences and a RanksBlock-style bar chart of each mask’s percentile.
This is the interactive successor to the static <PairList> + <SentencePair> + <RanksBlock> triple. One component, single source of truth, no <a href="#"> navigation traps.
Example
import PairExplorer from '../../components/widgets/PairExplorer.astro';
export const sentences = {
"1": "Two of the dice come up the same…",
"10": "The problem says that initially…",
"20": "The original pair plus two of the re-rolled…",
"36": "Or: The three re-rolled dice form a three-of-a-kind…",
};
export const masks = [
{ key: "gm", label: "geometric mean", code: "geometric_mean" },
{ key: "t20", label: "temp. 20", code: "tempered_snis T=20" },
{ key: "ta", label: "thought anchors", code: "answer_kl (sanity)" },
];
export const pairs = [
{ rank: 1, i: 10, j: 1, scores: { gm:[0, "6.243e-02"], t20:[22, "6.013e-02"], ta:[100, "2.435e+00"] } },
{ rank: 2, i: 36, j: 20, scores: { gm:[5, "6.248e-02"], t20:[25, "6.051e-02"], ta:[60, "5.994e-03"] } },
];
<PairExplorer sentences={sentences} masks={masks} pairs={pairs} />
Props
| Prop | Type | Required | Notes |
|---|---|---|---|
heading | string | no | Label shown at the top of the pair-list column. Defaults to Sentence pairs · ranked by reward_gap disagreement. |
sentences | Record<string, string> | yes | Sentence index → text. Values may contain trusted inline HTML (e.g. <code>). |
masks | Mask[] | yes | Bar rows. The mask with key: "ta" is treated as a sanity baseline and rendered separately. |
pairs | Pair[] | yes | Ranked pairs; the first pair is selected on initial render. |
Mask shape:
| Field | Type | Notes |
|---|---|---|
key | string | Index into scores for each pair. "ta" triggers sanity-baseline styling. |
label | string | Display label (first line of the row). |
code | string | Mono-font subtitle (e.g. tempered_snis T=20). |
Pair shape:
| Field | Type | Notes |
|---|---|---|
rank | number | Display rank (#1, #2, …). |
i, j | number | Sentence indices (must exist in sentences). |
scores | Record<string, [number, string]> | Per-mask [percentile, raw_value]. Keys must match masks[*].key. |
Interaction notes
- Clicks call
e.preventDefault()and togglearia-selectedon the list buttons — no URL change, no hash, no tab-state reset. - View Transitions: the script re-initialises on
astro:page-load. - Data is shipped to the client via a
<script type="application/json">block (read withtextContent, parsed once on init). NoinnerHTMLinjection of untrusted strings.
When not to use
- For more than ~20 pairs. The list column gets cramped; reach for a proper table with column sorting.
- When you only need a static snapshot. The plain
<PairList>+<SentencePair>+<RanksBlock>triple is lighter. - When the detail content varies in structure between rows. The detail panel template is fixed.