Public: anyone can read this; the crew can change it.

The builds list is keyboard-first: j/k move between rows, enter opens one (fresh from main) #10673

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/10577-the-builds-list-is-keyboard-first-j-k-mo → main 2 commits fork

  • Merged. scout/10577-the-builds-list-is-keyboard-first-j-k-mo was merged into main as f82d8d9.

Review

Sign in to review this change.
2 files changed +26 −0
src/web/pages/builds.ts +1
@@ -109,6 +109,7 @@ function buildRow(base: string, n: BuildNode, canPreview: boolean, canDelete: bo
109109 const label = encodeURIComponent(n.pin.label);
110110 const note = n.pin.note === n.pin.label ? "" : `${n.pin.note} · `;
111111 return row({
112 nav: true,
112113 title: html`${when(n.edge === "concept", () => html`<span class="build-concept" title="Concept edge: parent set by hand, not by commit history">┄ </span>`)}<a class="mono" href="${own ? base : `/${n.from}`}/commit/${n.pin.oid}">${n.from === undefined ? null : html`<span class="muted">${n.from}:</span>`}${n.pin.label}</a>`,
113114 meta: html`${note}${n.pin.source} · ${n.pin.pinnedBy} · ${time(n.pin.pinnedAt)}`,
114115 data: { depth: String(Math.min(n.depth, 8)) },
test/keys-builds.test.ts added +25
@@ -0,0 +1,25 @@
1 /** The builds list joins the shell's j/k row traversal, as the bets list does: one data-nav per pin row, none on the empty page. */
2 import { expect, test } from "bun:test";
3 import { buildsList } from "../src/web/pages/builds.ts";
4 import type { BuildNode } from "../src/core/lineage.ts";
5
6 const node = (label: string, depth = 0) =>
7 ({
8 pin: { label, oid: "a".repeat(40), note: label, source: "commit", pinnedBy: "dev", pinnedAt: 0 },
9 depth,
10 edge: "git",
11 }) as unknown as BuildNode;
12 const NAV = /class="row"[^>]*data-nav tabindex="-1"/;
13
14 test("the empty builds page draws no data-nav row", () => {
15 const out = buildsList("/dev/lib", [], true).toString();
16 expect(out).toContain("No builds yet.");
17 expect(out).not.toMatch(NAV);
18 });
19
20 test("each pin is one data-nav row whose first link opens its commit", () => {
21 const out = buildsList("/dev/lib", [node("v1"), node("v2", 1), node("v3", 1)], false).toString();
22 const rows = out.split("<li").filter((li) => NAV.test(li));
23 expect(rows.length).toBe(3);
24 expect(rows[0]!.match(/<a [^>]*href="([^"]+)"/)![1]).toBe(`/dev/lib/commit/${"a".repeat(40)}`);
25 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs