fix(app): use filled clear icon in model and branch searches (#53511)

Co-authored-by: Brendonovich <14191578+Brendonovich@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot]
2026-10-07 17:12:10 +08:00
committed by GitHub
Unverified
parent f655e7b2b5
commit 2e3d3a735a
4 changed files with 60 additions and 89 deletions
@@ -327,7 +327,7 @@ export function PromptWorkspaceSelector(props: {
setTimeout(() => requestAnimationFrame(() => branchSearchInput?.focus({ preventScroll: true })))
}}
>
<div class="flex h-7 shrink-0 items-center gap-2 rounded-sm pl-3 pr-2.5 text-v2-icon-icon-muted">
<div class="flex h-7 shrink-0 items-center gap-2 rounded-sm pl-3 pr-1 text-v2-icon-icon-muted">
<Icon name="magnifying-glass" size="small" class="shrink-0" />
<input
ref={(element) => {
@@ -355,7 +355,7 @@ export function PromptWorkspaceSelector(props: {
<Show when={search.branches.trim()}>
<button
type="button"
class="flex size-5 items-center justify-center rounded-sm text-v2-icon-icon-muted hover:bg-v2-overlay-simple-overlay-hover"
class="flex size-5 items-center justify-center rounded-sm bg-transparent text-v2-icon-icon-faint transition-colors hover:text-v2-icon-icon-base focus-visible:text-v2-icon-icon-base active:text-v2-icon-icon-base"
onPointerDown={(event) => event.preventDefault()}
onClick={() => {
setSearch("branches", "")
@@ -363,7 +363,7 @@ export function PromptWorkspaceSelector(props: {
}}
aria-label={language.t("common.clear")}
>
<Icon name="close-small" size="small" />
<Icon name="circle-xmark" />
</button>
</Show>
</div>
+19 -30
View File
@@ -1,7 +1,5 @@
import { Button } from "@opencode/ui/button"
import { Dialog, DialogBody, DialogHeader, DialogTitleGroup } from "@opencode/ui/dialog"
import { Icon } from "@opencode/ui/icon"
import { IconButton } from "@opencode/ui/icon-button"
import { Switch } from "@opencode/ui/switch"
import { TextInput } from "@opencode/ui/text-input"
import { useFilteredList } from "@opencode/ui/hooks"
@@ -24,7 +22,7 @@ export const DialogManageModels: Component = () => {
const local = useLocal()
const language = useLanguage()
const dialog = useDialog()
const [store, setStore] = createStore({ collapsed: {} as Record<string, boolean> })
const [store, setStore] = createStore<{ collapsed: Record<string, boolean> }>({ collapsed: {} })
const directory = () => decode64(local.slug())
const handleConnectProvider = () => {
@@ -107,33 +105,24 @@ export const DialogManageModels: Component = () => {
</DialogHeader>
<DialogBody class="flex min-h-0 flex-1 flex-col">
<div class="px-4 pt-px pb-3">
<div class="relative">
<TextInput
type="search"
appearance="base"
class="!w-full self-stretch"
value={list.filter()}
onInput={(event) => list.onInput(event.currentTarget.value)}
placeholder={language.t("dialog.model.search.placeholder")}
spellcheck={false}
autocorrect="off"
autocomplete="off"
autocapitalize="off"
autofocus
aria-label={language.t("dialog.model.search.placeholder")}
/>
<Show when={list.filter()}>
<IconButton
type="button"
variant="ghost-muted"
size="small"
class="settings-tab-search-clear"
icon={<Icon name="close" size="large" class="text-v2-icon-icon-muted" />}
onClick={() => list.clear()}
aria-label={language.t("common.clear")}
/>
</Show>
</div>
<TextInput
type="search"
appearance="base"
class="!w-full self-stretch"
value={list.filter()}
onInput={(event) => list.onInput(event.currentTarget.value)}
placeholder={language.t("dialog.model.search.placeholder")}
spellcheck={false}
autocorrect="off"
autocomplete="off"
autocapitalize="off"
autofocus
aria-label={language.t("dialog.model.search.placeholder")}
showClearButton={!!list.filter()}
clearIcon="circle-xmark"
clearLabel={language.t("common.clear")}
onClearClick={() => list.clear()}
/>
</div>
<div data-slot="manage-models-scroll" class="relative min-h-0 flex-1">
<div class="settings-panel settings-models h-full px-4 pt-1 pb-4">
@@ -9,7 +9,6 @@ import { Button } from "@opencode/ui/button"
import { Badge } from "@opencode/ui/badge"
import { Dialog, DialogBody, DialogHeader, DialogTitleGroup } from "@opencode/ui/dialog"
import { Icon } from "@opencode/ui/icon"
import { IconButton } from "@opencode/ui/icon-button"
import { ScrollView } from "@opencode/ui/scroll-view"
import { Tooltip } from "@opencode/ui/tooltip"
import { Menu } from "@opencode/ui/menu"
@@ -186,55 +185,46 @@ const ModelList: Component<{
return (
<div class="flex min-h-0 flex-1 flex-col">
<div data-slot="model-selector-search" class="shrink-0 pt-px pb-3" classList={{ "px-4": !props.mobile }}>
<div class="relative">
<TextInput
type="search"
appearance="base"
class="!w-full self-stretch"
placeholder={language.t("dialog.model.search.placeholder")}
value={store.search}
autofocus={!props.mobile}
spellcheck={false}
autocorrect="off"
autocomplete="off"
autocapitalize="off"
onInput={(event) => setSearch(event.currentTarget.value)}
onKeyDown={(event) => {
if (event.altKey || event.metaKey) return
<TextInput
type="search"
appearance="base"
class="!w-full self-stretch"
placeholder={language.t("dialog.model.search.placeholder")}
value={store.search}
autofocus={!props.mobile}
spellcheck={false}
autocorrect="off"
autocomplete="off"
autocapitalize="off"
onInput={(event) => setSearch(event.currentTarget.value)}
onKeyDown={(event) => {
if (event.altKey || event.metaKey) return
if (event.key === "ArrowDown") {
event.preventDefault()
moveActive(1)
if (event.key === "ArrowDown") {
event.preventDefault()
moveActive(1)
return
}
return
}
if (event.key === "ArrowUp") {
event.preventDefault()
moveActive(-1)
if (event.key === "ArrowUp") {
event.preventDefault()
moveActive(-1)
return
}
return
}
if (event.key === "Enter" && !event.isComposing) {
event.preventDefault()
selectActive()
}
}}
aria-label={language.t("dialog.model.search.placeholder")}
/>
<Show when={store.search}>
<IconButton
type="button"
variant="ghost-muted"
size="small"
class="settings-tab-search-clear"
icon={<Icon name="close" size="large" class="text-v2-icon-icon-muted" />}
onClick={() => setSearch("")}
aria-label={language.t("common.clear")}
/>
</Show>
</div>
if (event.key === "Enter" && !event.isComposing) {
event.preventDefault()
selectActive()
}
}}
aria-label={language.t("dialog.model.search.placeholder")}
showClearButton={!!store.search}
clearIcon="circle-xmark"
clearLabel={language.t("common.clear")}
onClearClick={() => setSearch("")}
/>
</div>
<div class="relative min-h-0" classList={{ "flex-1": !props.mobile }}>
<div
@@ -613,7 +603,7 @@ export function ModelSelectorPopoverView(props: {
onCloseAutoFocus={dismiss.onCloseAutoFocus}
>
<div class="flex flex-col p-0.5">
<div class="flex h-7 items-center gap-2 rounded-sm pl-3 pr-2.5 text-v2-icon-icon-muted">
<div class="flex h-7 items-center gap-2 rounded-sm pl-3 pr-1 text-v2-icon-icon-muted">
<Icon name="magnifying-glass" size="small" class="shrink-0" />
<input
ref={(el) => (searchRef = el)}
@@ -663,12 +653,12 @@ export function ModelSelectorPopoverView(props: {
<Show when={store.search.trim()}>
<button
type="button"
class="flex size-5 items-center justify-center rounded-sm text-v2-icon-icon-muted hover:bg-v2-overlay-simple-overlay-hover"
class="flex size-5 items-center justify-center rounded-sm bg-transparent text-v2-icon-icon-faint transition-colors hover:text-v2-icon-icon-base focus-visible:text-v2-icon-icon-base active:text-v2-icon-icon-base"
onPointerDown={(event) => event.preventDefault()}
onClick={() => setSearch("")}
aria-label={language.t("common.clear")}
>
<Icon name="close" size="small" />
<Icon name="circle-xmark" />
</button>
</Show>
</div>
-8
View File
@@ -1217,14 +1217,6 @@
.settings-project-card[data-menu="true"] {
background: var(--v2-background-bg-layer-02);
}
.settings-tab-search-clear {
position: absolute;
top: 50%;
inset-inline-end: 6px;
z-index: 1;
transform: translateY(-50%);
}
.settings-models {
gap: 12px;
}