Release composer: replace the tag datalist with a proper recent-tags dropdown #254
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#254
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?
What's requested
In the "new release" interface (
/:owner/:name/releases/new), the tag field should offer a real dropdown of recent tags rather than relying on the browser's datalist behavior.Current state (code evidence)
web/src/pages/ReleaseNew.jsx:100-118: the tag input uses a native<datalist id="release-tags">fed bytagNames()(fromctx.repoClient.tags({n:100}), line 16). The data is already there and sorted by the tags stream.RefPickerinweb/src/pages/Repo.jsx:216+— button trigger, streamed list, keyboard/Esc handling, outside-click close).Proposed design
input#release-tagstays the source of truth (keep typing to filter), plus a dropdown trigger/button showing recent tags (most recent first — the tags stream order) as a styled popover.RefPicker's trigger/list/keyboard pattern, or the lighter<details>approach the clone menu uses. Filter options as the user types (client-side ontagNames()— no new fetches;useDatacache keytags:{full}already single-flights).aria-expanded, listbox semantics, arrow-key navigation, Enter selects, Esc closes — mirrorRefPicker's keyboard handling.Acceptance criteria
/releases/newshows recent tags in a styled dropdown (recent first), consistent with the app's popover styling in light/dark themes.tags:{full}cache entry.Fixed by PR #264 (branch fix/issue-254): tag datalist → styled combobox. #264
Review of PR #264 (fix/issue-254, tag dropdown combobox) — verified in scratch worktree at
b4aa966; no browser per instructions (node tests + reasoning only).INPUT SOURCE OF TRUTH — PASS. web/src/pages/ReleaseNew.jsx:176 value={getTag()} stays bound; :178 trims as before; chooseTag (:92-96) sets input + closes + refocuses. Free-typed non-listed tag submittable as before: submit enabled on any non-empty tag (:331) and create (:49-54) has no list-membership check; title placeholder still defaults to typed tag (:270).
ORDER — PASS. Dropdown renders filteredTags() (:217) over tagNames() stream order (:73-74, tags({n:100}) call :17 unchanged); filterTagNames (web/src/lib/releases.js:29-34) is filter-only, never re-sorts. Tests assert passthrough order (releases-panel.test.js:50-57).
FILTER — PASS. Case-insensitive substring, blank/whitespace/undefined→all, non-array→[] (:29-34); covered by tests :59-71.
KEYBOARD — PASS. :112-135 arrows preventDefault, open-if-closed at index 0, wrap via modulo; Enter selects+refocuses when active valid, else just closes (input already focused — correct, lets native submit proceed); Esc via document handler :100-105 closes + refocuses input (works from input, trigger, or option).
OUTSIDE-CLICK — PASS. :97-99 contains-check + :106-111 listeners with onCleanup removal (LabelPicker/MilestonePicker idiom as commented :81-82). Trigger lives inside comboRoot so toggle isn't swallowed.
ARIA — PASS. Input role=combobox :168 with aria-expanded/controls=release-tag-list/autocomplete=activedescendant (:169-174, omitted when inactive); list role=listbox :212 with matching id + label; rows role=option :227 with indexed ids :228 matching activedescendant and aria-selected :229; trigger aria-haspopup=listbox :193.
EMPTY STATE — PASS, truthful post-#253. Filtered-empty :219-221 and no-tags help :251 both say 'create it from a commit' — releases still can't create tags, commit view can. No-tags case keeps popover shut (:209) with trigger disabled (:198), so guidance line is the single channel.
OPAQUE PANEL + SCROLL — PASS. .tag-drop added to the shared solid-panel rule (web/src/ui.css:133, ordered after .card); popover carries scroll-slim + max-h-72 overflow-y-auto (:214).
FETCHES/DEPS — PASS. Same tags:{full} cache key (:17), no new useData; no package.json/lock change (verified empty diff).
DOCS — PASS. docs/go/12_web_ui.md: #49 entry notes supersede by #254, new #254 entry matches implementation (combobox, tags:{full}, keyboard, truthful empty state, no backend/SDK/deps, headless cover, browser-proof-open note). AGENTS laws 1/7/8/12 hold (no new deps, listeners cleaned, no seam changes, doc updated in same change).
TESTS (scratch worktree, node_modules symlinked read-only from main checkout — no main files touched): releases-panel.test.js 8/8 pass; all other unit files 518/518 pass (192+154+172 across three batches); smoke.test.js 3/3 assertions pass with the known file-level event-loop hang — file untouched by this PR so pre-existing as the PR description claims. vite build green (139 modules, 1.87s), esbuild SDK bundle green.
No fixes pushed — nothing to fix. MERGE RECOMMENDATION: ready to merge.
Fixed by PR #264 (review clean; 518/518 node tests), merged. Closing.