authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-09-20 20:32:35-03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-20 20:32:35-03:00
log67285e4b8719000eecb9de2a424609ca5c6f0274
tree90d7d1ccdae7b04b0fc3a54ad1f6ce8f12c3d068
parent584450a1f198c8592d28947a0a7a060d28013298
signature Signed by PGP key B5690EEEBB952194

fix(web): route keyboard submit through the primary worktree action (#12526)


2 files changed, 45 insertions(+), 13 deletions(-)

apps/web/src/components/BranchToolbarBranchSelector.tsx+41-12
......@@ -545,6 +545,7 @@ export function BranchToolbarBranchSelector({
545545 setIsBranchMenuOpen(open);
546546 if (!open) {
547547 setBranchQuery("");
548 highlightedBranchValueRef.current = null;
548549 }
549550 }, []);
550551
......@@ -594,6 +595,9 @@ export function BranchToolbarBranchSelector({
594595 }, [fetchNextBranchPage, hasNextPage, isBranchMenuOpen, isFetchingNextPage]);
595596
596597 const branchListRef = useRef<LegendListRef | null>(null);
598 // Tracks the highlighted picker value so Enter can activate it even when the
599 // virtualized row is not mounted (Base UI Enter clicks the mounted element).
600 const highlightedBranchValueRef = useRef<string | null>(null);
597601 const updateBranchListScrollFades = useCallback(() => {
598602 const scrollElement = branchListRef.current?.getScrollableNode?.();
599603 if (!(scrollElement instanceof HTMLElement)) {
......@@ -676,6 +680,20 @@ export function BranchToolbarBranchSelector({
676680 const prUrl = currentLinkedPr?.url ?? displayedPr?.url;
677681 const openPrLink = useOpenPrLink(threadRef);
678682
683 function selectPickerItem(itemValue: string) {
684 highlightedBranchValueRef.current = null;
685 if (itemValue === checkoutPullRequestItemValue && prReference && onCheckoutPullRequestRequest) {
686 handleOpenChange(false);
687 onComposerFocusRequest?.();
688 onCheckoutPullRequestRequest(prReference);
689 } else if (itemValue === createBranchItemValue) {
690 createRef(trimmedBranchQuery);
691 } else {
692 const refName = branchByName.get(itemValue);
693 if (refName) selectBranch(refName);
694 }
695 }
696
679697 function renderPickerItem(itemValue: string, index: number) {
680698 if (checkoutPullRequestItemValue && itemValue === checkoutPullRequestItemValue) {
681699 return (
......@@ -685,15 +703,7 @@ export function BranchToolbarBranchSelector({
685703 index={index}
686704 value={itemValue}
687705 className="pe-2"
688 onClick={() => {
689 if (!prReference || !onCheckoutPullRequestRequest) {
690 return;
691 }
692 setIsBranchMenuOpen(false);
693 setBranchQuery("");
694 onComposerFocusRequest?.();
695 onCheckoutPullRequestRequest(prReference);
696 }}
706 onClick={() => selectPickerItem(itemValue)}
697707 >
698708 <div className="flex min-w-0 items-center gap-2 py-1">
699709 <SourceControlIcon className="size-3.5 shrink-0 text-muted-foreground" />
......@@ -715,7 +725,7 @@ export function BranchToolbarBranchSelector({
715725 index={index}
716726 value={itemValue}
717727 className="pe-1.5"
718 onClick={() => createRef(trimmedBranchQuery)}
728 onClick={() => selectPickerItem(itemValue)}
719729 >
720730 <span className="truncate">Create new ref &quot;{newRefName}&quot;</span>
721731 </ComboboxItem>
......@@ -743,7 +753,7 @@ export function BranchToolbarBranchSelector({
743753 index={index}
744754 value={itemValue}
745755 className="pe-1.5"
746 onClick={() => selectBranch(refName)}
756 onClick={() => selectPickerItem(itemValue)}
747757 onContextMenu={(event) => handleBranchContextMenu(event, itemValue)}
748758 >
749759 <div className="flex w-full min-w-0 items-center justify-between gap-2">
......@@ -760,7 +770,8 @@ export function BranchToolbarBranchSelector({
760770 filteredItems={filteredBranchPickerItems}
761771 autoHighlight
762772 virtualized
763 onItemHighlighted={(_value, eventDetails) => {
773 onItemHighlighted={(value, eventDetails) => {
774 highlightedBranchValueRef.current = typeof value === "string" ? value : null;
764775 if (!isBranchMenuOpen || eventDetails.index < 0 || eventDetails.reason !== "keyboard") {
765776 return;
766777 }
......@@ -828,6 +839,24 @@ export function BranchToolbarBranchSelector({
828839 placeholder="Search refs..."
829840 value={branchQuery}
830841 onChange={(event) => setBranchQuery(event.target.value)}
842 onKeyDown={(event) => {
843 if (event.key !== "Enter" || event.nativeEvent.isComposing || event.keyCode === 229) {
844 return;
845 }
846 const highlightedValue = highlightedBranchValueRef.current;
847 if (
848 highlightedValue === null ||
849 !filteredBranchPickerItems.includes(highlightedValue)
850 ) {
851 return;
852 }
853 (
854 event as typeof event & { preventBaseUIHandler?: () => void }
855 ).preventBaseUIHandler?.();
856 event.preventDefault();
857 event.stopPropagation();
858 selectPickerItem(highlightedValue);
859 }}
831860 />
832861 <div className="flex min-h-0 flex-1 flex-col overflow-hidden">
833862 <ComboboxEmpty>No refs found.</ComboboxEmpty>
apps/web/src/components/PullRequestThreadDialog.tsx+4-1
......@@ -222,9 +222,12 @@ export function PullRequestThreadDialog({
222222 if (event.key !== "Enter") {
223223 return;
224224 }
225 if (event.nativeEvent.isComposing || event.keyCode === 229) {
226 return;
227 }
225228 event.preventDefault();
226229 if (!isResolving && !preparePullRequestThreadAction.isPending) {
227 void handleConfirm("local");
230 void handleConfirm("worktree");
228231 }
229232 }}
230233 />