authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-17 20:17:51-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 20:17:51-07:00
log8583eac643b8c248bcd835e8de81c7c0d7182ad3
tree4e0b4fa55a2483f03f4956cfe11c4b58251a42a3
parent53510d44ea7b4a44c10c122dd9245194f2f14d09
signature Signed by PGP key B5690EEEBB952194

refactor(web): reuse searchable picker inputs (#12353)


5 files changed, 28 insertions(+), 82 deletions(-)

apps/web/src/components/BranchToolbarBranchSelector.tsx+7-20
......@@ -9,7 +9,7 @@ import {
99} from "@t3tools/client-runtime/state/runtime";
1010import type { ContextMenuItem, EnvironmentId, VcsRef, ThreadId } from "@t3tools/contracts";
1111import { LegendList, type LegendListRef } from "@legendapp/list/react";
12import { ChevronDownIcon, GitBranchIcon, SearchIcon } from "lucide-react";
12import { ChevronDownIcon, GitBranchIcon } from "lucide-react";
1313import {
1414 useCallback,
1515 useDeferredValue,
......@@ -64,7 +64,7 @@ import { getVirtualizedScrollFadeClassName } from "./ui/scroll-area";
6464import {
6565 Combobox,
6666 ComboboxEmpty,
67 ComboboxInput,
67 ComboboxSearchInput,
6868 ComboboxItem,
6969 ComboboxListVirtualized,
7070 ComboboxPopup,
......@@ -824,24 +824,11 @@ export function BranchToolbarBranchSelector({
824824 className="flex w-80 flex-col"
825825 {...composerFloatingLayerProps}
826826 >
827 <div className="shrink-0 px-3 pt-2.5">
828 <div className="relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring">
829 <SearchIcon
830 aria-hidden="true"
831 className="pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55"
832 />
833 <ComboboxInput
834 className="[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5"
835 inputClassName="rounded-none bg-transparent text-sm"
836 placeholder="Search refs..."
837 showTrigger={false}
838 size="sm"
839 unstyled
840 value={branchQuery}
841 onChange={(event) => setBranchQuery(event.target.value)}
842 />
843 </div>
844 </div>
827 <ComboboxSearchInput
828 placeholder="Search refs..."
829 value={branchQuery}
830 onChange={(event) => setBranchQuery(event.target.value)}
831 />
845832 <div className="flex min-h-0 flex-1 flex-col overflow-hidden">
846833 <ComboboxEmpty>No refs found.</ComboboxEmpty>
847834 <div className="relative min-h-0 w-full max-h-56 flex-1 overflow-hidden">
apps/web/src/components/DiffPanel.tsx+6-20
......@@ -19,7 +19,6 @@ import {
1919 FolderTreeIcon,
2020 PilcrowIcon,
2121 Rows3Icon,
22 SearchIcon,
2322 TextWrapIcon,
2423} from "lucide-react";
2524import * as Schema from "effect/Schema";
......@@ -64,7 +63,7 @@ import { Switch } from "./ui/switch";
6463import {
6564 Combobox,
6665 ComboboxEmpty,
67 ComboboxInput,
66 ComboboxSearchInput,
6867 ComboboxItem,
6968 ComboboxList,
7069 ComboboxPopup,
......@@ -757,24 +756,11 @@ export default function DiffPanel({
757756 align="start"
758757 className="w-72 min-w-0 max-w-[calc(100vw-1rem)] overflow-hidden"
759758 >
760 <div className="min-w-0 shrink-0 px-3 pt-2.5">
761 <div className="relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring">
762 <SearchIcon
763 aria-hidden="true"
764 className="pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55"
765 />
766 <ComboboxInput
767 className="[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5"
768 inputClassName="rounded-none bg-transparent text-sm"
769 placeholder="Search refs..."
770 showTrigger={false}
771 size="sm"
772 unstyled
773 value={baseRefQuery}
774 onChange={(event) => setBaseRefQuery(event.target.value)}
775 />
776 </div>
777 </div>
759 <ComboboxSearchInput
760 placeholder="Search refs..."
761 value={baseRefQuery}
762 onChange={(event) => setBaseRefQuery(event.target.value)}
763 />
778764 <div className="grid shrink-0 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 border-b border-border/70 ps-3 pe-6.5 pt-2 pb-1.5 font-medium text-[10px] text-muted-foreground uppercase tracking-wide">
779765 <span aria-hidden="true" />
780766 <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center">
apps/web/src/components/pullRequest/PullRequestCandidatePicker.tsx+7-21
......@@ -6,13 +6,12 @@
66 * The same combobox as the project and branch pickers, and dressed the same, rather than a menu:
77 * a menu's typeahead claims every keypress to jump between rows, which a search box cannot share.
88 */
9import { SearchIcon } from "lucide-react";
109import type { ReactNode } from "react";
1110
1211import { Button } from "../ui/button";
1312import {
1413 Combobox,
15 ComboboxInput,
14 ComboboxSearchInput,
1615 ComboboxItem,
1716 ComboboxList,
1817 ComboboxPopup,
......@@ -123,25 +122,12 @@ export function PullRequestCandidatePicker<T>({
123122 }
124123 />
125124 <ComboboxPopup align="start" side="bottom" className="w-72">
126 <div className="shrink-0 px-3 pt-2.5">
127 <div className="relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring">
128 <SearchIcon
129 aria-hidden="true"
130 className="pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55"
131 />
132 <ComboboxInput
133 aria-label={searchLabel}
134 className="[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5"
135 inputClassName="rounded-none bg-transparent text-sm"
136 placeholder={searchLabel}
137 showTrigger={false}
138 size="sm"
139 unstyled
140 value={query}
141 onChange={(event) => onQueryChange(event.target.value)}
142 />
143 </div>
144 </div>
125 <ComboboxSearchInput
126 aria-label={searchLabel}
127 placeholder={searchLabel}
128 value={query}
129 onChange={(event) => onQueryChange(event.target.value)}
130 />
145131 <ComboboxList className="max-h-72">
146132 {isPending ? (
147133 <PullRequestPeopleGhost rows={4} />
apps/web/src/components/settings/FontFamilyPicker.tsx+7-20
......@@ -1,11 +1,11 @@
11import { LegendList, type LegendListRef } from "@legendapp/list/react";
2import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
2import { CheckIcon, ChevronDownIcon } from "lucide-react";
33import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
44import { isMonospaceFamily, queryInstalledFontFamilies } from "../../appearanceFonts";
55import {
66 Combobox,
77 ComboboxEmpty,
8 ComboboxInput,
8 ComboboxSearchInput,
99 ComboboxItem,
1010 ComboboxListVirtualized,
1111 ComboboxPopup,
......@@ -211,24 +211,11 @@ export function FontFamilyPicker({
211211 <ChevronDownIcon className="-me-1 size-3 opacity-50" />
212212 </ComboboxTrigger>
213213 <ComboboxPopup align="end" className="flex w-72 flex-col">
214 <div className="shrink-0 px-3 pt-2.5">
215 <div className="relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring">
216 <SearchIcon
217 aria-hidden="true"
218 className="pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55"
219 />
220 <ComboboxInput
221 className="[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5"
222 inputClassName="rounded-none bg-transparent text-sm"
223 placeholder="Search fonts…"
224 showTrigger={false}
225 size="sm"
226 unstyled
227 value={query}
228 onChange={(event) => setQuery(event.target.value)}
229 />
230 </div>
231 </div>
214 <ComboboxSearchInput
215 placeholder="Search fonts…"
216 value={query}
217 onChange={(event) => setQuery(event.target.value)}
218 />
232219 <div className="flex min-h-0 flex-1 flex-col overflow-hidden">
233220 <ComboboxEmpty>No fonts found.</ComboboxEmpty>
234221 <div className="relative min-h-0 max-h-72 w-full flex-1 overflow-hidden">
apps/web/src/components/ui/combobox.tsx+1-1
......@@ -132,7 +132,7 @@ function ComboboxInput({
132132
133133function ComboboxSearchInput(props: React.ComponentProps<typeof ComboboxInput>) {
134134 return (
135 <div className="shrink-0 px-3 pt-2.5">
135 <div className="min-w-0 shrink-0 px-3 pt-2.5">
136136 <div className="relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring">
137137 <SearchIcon
138138 aria-hidden="true"