From 87053d2e76a362da9ee417110195ec02673080fd Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 11 Oct 2025 16:16:50 +0100 Subject: feat: make list dropdown searchable in Manage Lists modal (#2029) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace simple Select component with searchable Command/Popover component - Add search input that filters lists as you type (like tags) - Maintain sidebar ordering using allPaths - Add visual checkmark for selected list - Improve UX with keyboard navigation and accessibility Fixes #2025 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Co-authored-by: Mohamed Bassem --- .../dashboard/lists/BookmarkListSelector.tsx | 105 +++++++++++++++------ 1 file changed, 75 insertions(+), 30 deletions(-) (limited to 'apps/web/components/dashboard/lists') diff --git a/apps/web/components/dashboard/lists/BookmarkListSelector.tsx b/apps/web/components/dashboard/lists/BookmarkListSelector.tsx index 9ce56031..a267c692 100644 --- a/apps/web/components/dashboard/lists/BookmarkListSelector.tsx +++ b/apps/web/components/dashboard/lists/BookmarkListSelector.tsx @@ -1,13 +1,21 @@ +import { useState } from "react"; +import { Button } from "@/components/ui/button"; import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; import LoadingSpinner from "@/components/ui/spinner"; import { cn } from "@/lib/utils"; +import { Check, ChevronsUpDown } from "lucide-react"; import { useBookmarkLists } from "@karakeep/shared-react/hooks/lists"; import { ZBookmarkList } from "@karakeep/shared/types/lists"; @@ -29,6 +37,7 @@ export function BookmarkListSelector({ hideBookmarkIds?: string[]; listTypes?: ZBookmarkList["type"][]; }) { + const [open, setOpen] = useState(false); const { data, isPending: isFetchingListsPending } = useBookmarkLists(); let { allPaths } = data ?? {}; @@ -49,29 +58,65 @@ export function BookmarkListSelector({ return !path.map((p) => p.id).includes(hideSubtreeOf); }); + // Find the selected list's display name + const selectedListPath = allPaths?.find( + (path) => path[path.length - 1].id === value, + ); + const selectedListName = selectedListPath + ? selectedListPath.map((p) => `${p.icon} ${p.name}`).join(" / ") + : null; + return ( - + + + + + + + + + + {allPaths && allPaths.length === 0 + ? "You don't currently have any lists." + : "No lists found."} + + + {allPaths?.map((path) => { + const l = path[path.length - 1]; + const name = path.map((p) => `${p.icon} ${p.name}`).join(" / "); + return ( + { + onChange(currentValue); + setOpen(false); + }} + className="cursor-pointer" + > + + {name} + + ); + })} + + + + + ); } -- cgit v1.2.3-70-g09d2