Ref picker: default branch not selectable in the list; type-select becomes Branches/Tags pills #482
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#482
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ref picker: default branch missing from the list + type-select becomes Branches/Tags pills
Two related gaps in the branch/tag ref dropdown (the
main @ 1ca4c5b4header button popover,RefPickerinweb/src/pages/Repo.jsx), reported together by the user from one screenshot. Evidence is a static read of the freshly pulled tree (e9ea1f0) - no runtime repro (standing rule).Part 1: the default branch is not selectable in the list
The picker's header pill shows
main @ <sha>, butmainnever appears as a pickable row in the dropdown.Mechanism (static analysis):
repo.refStream(getKind(), { q: getQuery(), n: 50 }, ...)(Repo.jsx:241) againstGET …/api/refs/branches(internal/api/refs.gorefsList).RefList(internal/api/bind_wal.go:360) iteratessnap.Refs(sorted by name), applies theq/afterfilters, and stops atn(client sendsn: 50). There is no default-branch filter -refs/heads/mainIS in the snapshot and IS returned by the endpoint.fix/…(111),feat/…(2) anddocs/…(1), andrefs/heads/fix/…<refs/heads/mainalphabetically.mainsits at position ~115 of the name-sorted list - far past the single 50-ref page the client requests.event: done {"more": true}frame (internal/api/refs.gostreamRefs, SDKrepo.js_consume) is dropped -RefPickerhas noafter-based follow-up request. So the default branch is structurally unreachable for any repo whose default sorts late (any repo with 50+ branches nameda…m-ish, including walhub itself).This is the same class as the skill-noted "default is filtered as 'the current one'" hypothesis, but the actual filter is the 50-ref page window, not an explicit exclusion.
Fix: pin the default branch at the top of the branch list, client-side, from data the picker already has.
Repo.jsxalready passes the summary head into the picker:head={() => pillHead(getViewed(), s().head)}(Repo.jsx:604). The summaryheadis the default-branch target (internal/api/refs.gorefsHead→Head()→snap.HeadTarget), i.e.{name: "refs/heads/main", sha}. No wire change, no new endpoint.RefPicker, synthesize a pinned row from the summary head whengetKind() === "branches"andhead()carries arefs/heads/name:.ref-list, above the streamed alphabetical list, visually separated (a subtle divider or a one-line "default" group label - implementer's call within the app's card/pill idiom).defaulttag/badge (the app's.pillchip idiom,web/src/ui.css:85) so it reads as pinned, not just first.pick()path (/{full}/tree/{shortRef(name)}).?pin=<refname>param onrefs/{branches|tags}that hoists that ref to the front of the page. The client-side pin alone satisfies the acceptance criteria; do not block on the wire change.Part 2: replace the type-select dropdown with two pills above the filter input
Today the popover's first row is a
<select class="input">(branches / tags) sitting beside the filter input (Repo.jsx:293-311,.ref-controlsflex row). Replace it with a two-segment pill toggle, filter input below:btn px-2 py-1 text-smbuttons withclassList={{ primary: getKind() === "branches" }}/… === "tags" }(sameprimaryactive-state treatment as WatchToggle/StarToggle), joined as a segmented pair (shared border radius, divider between). Opaque popover rules per #405 apply (the popover already carriesbackground: var(--panel)in.ref-drop- do not regress it).<button type="button">witharia-pressed; the group getsrole="group"+aria-label="Ref type". Keyboard order becomes pill 1 -> pill 2 -> filter input -> list (native Tab walk); the existing Esc handler (Repo.jsx:265-271, #255 outside-click close) is untouched.setKind(...), clearssetRefs([])and re-runsstream.run()- exactly the current<select>onChange behavior. The filter query persists across the switch (current contract:getQuery()is untouched on kind change) - keep that; the user's typed filter follows them between Branches and Tags..ref-controlsbecomes a column context - pills row on top, input below (flex-col, or a new wrapper). Keepgap-2spacing consistent with the header gap conventions (#463).Acceptance criteria
default-badged first row of the branch list in every repo, including repos where HEAD targets a non-mainname and repos with 50+ alphabetically-earlier branches (walhub itself is the live test case: 115 heads,mainat ~115)/{full}/tree/{default-branch}via the existingpick()path<select>is gone; two toggle pills (Branches | Tags) sit above the filter input, active state via thebtn … primaryidiom.ref-dropkeeps itsvar(--panel)background)#278max-width: calc(100vw - 1rem)bound on.ref-dropinweb/src/ui.css:204is preserved)web/test/unit/ref-picker-pill.test.jscurrently pins<option value="branches">branches</option>/<option value="tags">tags</option>- replace with pill-toggle assertions; add a default-branch-present assertion (pinned row derived from the summary head, dedupe rule) as a headless pure-function test inweb/src/lib/(theref-pill.jsconvention) if the pin derivation is extractedReferences
web/src/pages/Repo.jsx:224-330(select block 293-311, stream 240-243, pick 255-260)internal/api/bind_wal.go:360(RefList, name-sorted +ncap),internal/api/refs.go:125(refsList, SSE dialect),streamRefsdone {more}frame the client ignoresprimaryactive state), #252 (pill head context-first)PR open: #488 (branch fix/issue-482) — client-only pin + pills, no wire change. Tests: node --test 1047 total / 1045 pass / 2 pre-existing live-server smoke failures (identical on main); vite+esbuild green.
Reviewed PR #488 (fix/issue-482) in scratch worktree /tmp/pr488 against the 9 acceptance criteria. One real defect found and fixed (pushed
352b816to origin/fix/issue-482); rest verified.DEFECT (fixed, pushed): the pin derived from the wrong head. RefPicker computed pinnedDefault(head(), kind), but head() is the context-first pill head (pillHead(getViewed(), s().head), #252) — Tree.jsx:197 / Blob.jsx:194 publish the VIEWED ref, so viewing any fix/* branch pinned that branch badged as 'default' while the real default stayed unreachable past the 50-ref window (the exact walhub-itself scenario in criterion 1). Fix (web/src/pages/Repo.jsx): new summaryHead prop carrying s().head straight through (call site :661), pin reads pinnedDefault(summaryHead(), getKind()); pill label keeps head() unchanged. Code now matches its own #482 comments + the issue intent ('derived from the summary head'). Test pins the wiring both ways (pin reads summaryHead(), never head(); call site passes raw s().head). Docs entry updated (prop split + measured counts).
Criteria: (1) pin now reflects HeadTarget in all viewed states (branch incl. non-main defaults, tag/sha-addressed views, empty repo pins nothing); (2) dedupeRefs by full refname, sound, null-safe; (3) pinned row onClick pick(p()), and pick() keys off r.name (refs/tags/ prefix test), so heads/ always take the shortRef tree path — criterion met; (4) / gone from picker scope, two btn+primary buttons, role=group + aria-label Ref type, aria-pressed, switchKind = setKind+clear+re-stream with query untouched; (5) Esc+refocus and outside-click handlers byte-untouched; DOM order gives pill1-pill2-input-rows Tab walk; (6) no CSS touched: repo.css .ref-drop keeps var(--panel) background, ui.css:204 max-width bound intact, theme-independent; (7) 390px by arithmetic: w-80=320px popover under the 374px cap, two short pills + full-width input fit — no browser driven (per review instructions; noted explicitly); (8) option asserts replaced with stronger select-gone + pill/switch/pin/opacity pins, nothing dropped; (9) zero .go files, no manifest changes (no new deps, law 1), 12_web_ui.md entry appended in same change (law 12).
Verify: node --test web/test/unit/*.test.js = 1047 total / 1045 pass / 2 fail; the 2 are the pre-existing live-server smoke subtests (identical pass-1/fail-2 on pristine main — zero PR-caused). Targeted ref-pin-482 + ref-picker-pill: 18/18 pass. vite build + esbuild bundle green. Main worktree untouched (read-only fetch + test run only).
RECOMMENDATION: ready to merge (no browser proof — shared-daemon loopback guard; headless + builds green).
Fixed by PR #488 (review clean + one real defect fixed by reviewer: pin now reads summary head, not viewed ref; all 9 criteria pass), merged. Closing.