feat(tasks): filterable branch picker in New Task dialog#131
Conversation
The New Task dialog picked the base branch from a native <select>, which can only be navigated by scrolling. Repos with many branches make finding the right base branch slow. Replace it with a type-to-filter combobox: a text input that filters the branch list by case-insensitive substring (prefix matches first), plus a dropdown selectable by mouse or keyboard. The committed branch value stays the source of truth — the picker only ever commits an existing branch. - Add pure filterBranches/matchExactBranch helpers with unit tests - Add BranchCombobox component (ARIA combobox, arrow-key nav, Esc closes only the dropdown) - Wire it into NewTaskDialog, replacing the native <select> - Add OpenSpec change add-filterable-branch-picker Closes johannesjo#129 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for taking this on — picker reads cleanly and the pure Needs changes1. Enter falls through to form submit — The handler only calls } else if (e.key === 'Enter') {
e.preventDefault();
if (open() && matches().length > 0) commit(matches()[highlight()]);
else closeAndResolve();
}2. Stale text while dropdown is open — The mirror effect only syncs Cleanest fix is to derive the displayed value reactively instead of writing back into a signal: const display = createMemo(() => (open() || dirty()) ? query() : props.value);
// <input value={display()} ... />This also keeps the 3.
Gate the scroll to keyboard-driven highlight changes (e.g. a Optional
Considered and (mostly) dismissed
Verified non-issuesXSS, prototype pollution, IPC trust boundary — none. SolidJS escapes branch names rendered as text-node children; the picker only ever commits a value from the server-supplied list ( Happy to re-review once W1–W3 are addressed. |
|
Thanks for the thorough review! All three blocking items plus the optionals are addressed in Needs changes
Optional — applied
Ready for re-review whenever you have a moment. |
e9066f3 to
63ba609
Compare
|
Update: All blocking and optional items from the review are addressed and pushed ( |
|
Thanks for the updates. I re-reviewed the current head and found a few interaction issues that still look worth fixing before merge. Needs changes
Mouse selection uses
During branch refetch/project switch, the dialog clears Low-risk edge case
Verified locally: |
Address re-review feedback on PR johannesjo#131: - Focus now opens the list with an empty search query instead of seeding the committed branch into the input, so typing filters instead of appending (no more "mainfeature"). - Add an input click handler to reopen the dropdown after a mouse commit keeps focus on the input. - Clear the committed base branch during branch reload and block submit while branches load or after a failed fetch (inline error + Retry), so a task can't be created with a stale/empty base branch. - Clamp the highlighted index lower bound to 0 so ArrowDown with zero matches can't later commit matches()[-1]. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the re-review. All four items addressed in Needs changes
Low-risk edge case
Verified locally: Ready for re-review whenever you have a moment. |
|
Thank you very much! <3 |
|
Thanks — all four items are addressed cleanly. Verified at
Pure helpers ( One tiny follow-up, not a blocker: after a successful Retry, focus is on the now-unmounted Retry button, so the user has to click the field to interact. A |
Summary
Replaces the native
<select>base-branch picker in the New Task dialog with a type-to-filter combobox, so users with many branches can narrow the list by typing instead of scrolling.Closes #129.
Demo
Demo video: to be attached.
Changes
src/lib/branch-filter.ts— pure helpers:filterBranches(case-insensitive substring match, prefix matches ordered first) andmatchExactBranch.src/components/BranchCombobox.tsx— new combobox component: text input + filtered dropdown, ARIA combobox roles, arrow-key navigation, Enter to select,Esccloses only the dropdown (not the dialog), mouse selection.src/components/NewTaskDialog.tsx— swaps the native<select>for<BranchCombobox>; the section label is nowfor-linked to the input.openspec/changes/add-filterable-branch-picker/— OpenSpec change (proposal, tasks,task-creationspec).Design notes
baseBranchvalue stays the source of truth — the picker only ever commits a branch that exists in the repo.keydownlistener is used soEsccanstopPropagationand close just the dropdown, leaving the dialog open.GetBrancheschannel.Checks
npm run typecheck— passnpm run lint(--max-warnings 0) — passnpm run format:check— passnpm run test— 527 pass (10 newbranch-filtertests)openspec validate --all --strict— pass (10/10 items)Alternatives considered
<datalist>— would shrink the component to a few lines, but loses control over commit-on-blur, exact-match revert of partial text, and the prefix-before-substring ordering. Rejected for that reason; the custom combobox keeps those semantics explicit.Notes / open questions
🤖 Generated with Claude Code