فهرست منبع

Merge pull request #5586 from abdulrahimpds/fix/settings-search-ui

Fixed settings search UI clipping and layout issues
Kevin van Dijk 5 روز پیش
والد
کامیت
c5a3afff57

+ 5 - 0
.changeset/fix-settings-search-ui.md

@@ -0,0 +1,5 @@
+---
+"kilo-code": patch
+---
+
+Fixed UI issues in Settings search bar: clipping of results and layout shift when expanding

+ 27 - 19
webview-ui/src/components/settings/SettingsSearch.tsx

@@ -1,6 +1,7 @@
 import { useRef, useEffect, useState, useCallback } from "react"
 import type { LucideIcon } from "lucide-react"
 
+import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
 import { useSettingsSearch, SearchResult, SearchableSettingData } from "./useSettingsSearch"
 import { SectionName } from "./SettingsView"
 import { SettingsSearchInput } from "./SettingsSearchInput"
@@ -98,26 +99,33 @@ export function SettingsSearch({ index, onNavigate, sections }: SettingsSearchPr
 	}, [highlightedResultId, isOpen])
 
 	return (
-		<div className="relative justify-end">
-			<SettingsSearchInput
-				value={searchQuery}
-				onChange={setSearchQuery}
-				onFocus={() => setIsOpen(true)}
-				onBlur={() => setTimeout(() => setIsOpen(false), 200)}
-				onKeyDown={handleSearchKeyDown}
-				inputRef={inputRef}
-			/>
-			{searchQuery && isOpen && (
-				<div className="absolute top-full min-w-[300px] right-0 mt-2 border border-vscode-dropdown-border bg-vscode-dropdown-background rounded-2xl overflow-hidden shadow-xl z-50">
-					<SettingsSearchResults
-						results={results}
-						query={searchQuery}
-						onSelectResult={handleSelectResult}
-						sections={sections}
-						highlightedResultId={highlightedResultId}
+		<Popover open={searchQuery !== "" && isOpen} modal={false}>
+			<PopoverTrigger asChild>
+				<div className="relative justify-end">
+					<SettingsSearchInput
+						value={searchQuery}
+						onChange={setSearchQuery}
+						onFocus={() => setIsOpen(true)}
+						onKeyDown={handleSearchKeyDown}
+						inputRef={inputRef}
 					/>
 				</div>
-			)}
-		</div>
+			</PopoverTrigger>
+			<PopoverContent
+				className="min-w-[300px] p-0 border-vscode-dropdown-border bg-vscode-dropdown-background rounded-2xl overflow-hidden shadow-xl"
+				align="end"
+				side="bottom"
+				sideOffset={8}
+				onOpenAutoFocus={(e) => e.preventDefault()}
+				onCloseAutoFocus={(e) => e.preventDefault()}>
+				<SettingsSearchResults
+					results={results}
+					query={searchQuery}
+					onSelectResult={handleSelectResult}
+					sections={sections}
+					highlightedResultId={highlightedResultId}
+				/>
+			</PopoverContent>
+		</Popover>
 	)
 }

+ 31 - 25
webview-ui/src/components/settings/SettingsSearchInput.tsx

@@ -41,33 +41,39 @@ export function SettingsSearchInput({
 	const isWide = isExpanded || !!value
 
 	return (
-		<div className="relative flex items-center justify-end">
-			<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 size-3.5 text-vscode-descriptionForeground pointer-events-none z-10" />
-			<Input
-				ref={inputRef}
-				data-testid="settings-search-input"
-				type="text"
-				value={value}
-				onChange={(e) => onChange(e.target.value)}
-				onFocus={handleFocus}
-				onBlur={handleBlur}
-				onKeyDown={onKeyDown}
-				placeholder={isWide ? t("settings:search.placeholder") : ""}
+		<div className="relative flex items-center justify-end w-8">
+			<div
 				className={cn(
-					"pl-8 h-7 text-sm rounded-full border border-vscode-input-border bg-vscode-input-background focus:border-vscode-focusBorder transition-all duration-200 ease-in-out",
-					isWide ? "w-40 pr-2.5" : "w-8 pr-0 cursor-pointer",
-					value && "pr-7",
+					"absolute right-0 flex items-center transition-all duration-200 ease-in-out",
+					isWide ? "w-40" : "w-8",
+				)}>
+				<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 size-3.5 text-vscode-descriptionForeground pointer-events-none z-10" />
+				<Input
+					ref={inputRef}
+					data-testid="settings-search-input"
+					type="text"
+					value={value}
+					onChange={(e) => onChange(e.target.value)}
+					onFocus={handleFocus}
+					onBlur={handleBlur}
+					onKeyDown={onKeyDown}
+					placeholder={isWide ? t("settings:search.placeholder") : ""}
+					className={cn(
+						"pl-8 h-7 text-sm rounded-full border border-vscode-input-border bg-vscode-input-background focus:border-vscode-focusBorder transition-all duration-200 ease-in-out w-full",
+						isWide ? "pr-2.5" : "pr-0 cursor-pointer",
+						value && "pr-7",
+					)}
+				/>
+				{value && (
+					<button
+						type="button"
+						onClick={() => onChange("")}
+						className="absolute cursor-pointer right-2 top-1/2 -translate-y-1/2 text-vscode-descriptionForeground hover:text-vscode-foreground focus:outline-none"
+						aria-label="Clear search">
+						<X className="size-3.5" />
+					</button>
 				)}
-			/>
-			{value && (
-				<button
-					type="button"
-					onClick={() => onChange("")}
-					className="absolute cursor-pointer right-2 top-1/2 -translate-y-1/2 text-vscode-descriptionForeground hover:text-vscode-foreground focus:outline-none"
-					aria-label="Clear search">
-					<X className="size-3.5" />
-				</button>
-			)}
+			</div>
 		</div>
 	)
 }