Skip to content

Commit 2a08f8f

Browse files
authored
feat(app): reintroduce model context tooltip in model selector (anomalyco#35087)
1 parent 9353559 commit 2a08f8f

3 files changed

Lines changed: 74 additions & 21 deletions

File tree

packages/app/src/components/dialog-select-model.tsx

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { Tooltip } from "@opencode-ai/ui/tooltip"
2424
import { Icon } from "@opencode-ai/ui/v2/icon"
2525
import { Tag as TagV2 } from "@opencode-ai/ui/v2/badge-v2"
2626
import { MenuV2 } from "@opencode-ai/ui/v2/menu-v2"
27+
import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2"
2728
import { ModelTooltip } from "./model-tooltip"
2829
import { useLanguage } from "@/context/language"
2930
import { decode64 } from "@/utils/base64"
@@ -92,6 +93,7 @@ const ModelList: Component<{
9293
class="w-full"
9394
placement="right-start"
9495
gutter={12}
96+
openDelay={0}
9597
value={<ModelTooltip model={item} latest={item.latest} free={isFree(item.provider.id, item.cost)} />}
9698
>
9799
{node}
@@ -446,26 +448,41 @@ export function ModelSelectorPopoverV2(props: {
446448
<MenuV2.RadioGroup value={current()}>
447449
<For each={group.items}>
448450
{(item) => (
449-
<MenuV2.RadioItem
450-
value={modelKey(item)}
451-
data-option-key={modelKey(item)}
452-
data-selected-model={current() === modelKey(item) ? true : undefined}
453-
class="scroll-my-6"
454-
classList={{ "!bg-v2-overlay-simple-overlay-hover": store.active === modelKey(item) }}
455-
onMouseEnter={() => {
456-
setStore("active", modelKey(item))
457-
setTimeout(() => searchRef?.focus())
458-
}}
459-
onSelect={() => selectModel(item)}
451+
<TooltipV2
452+
class="w-full"
453+
placement="right-start"
454+
gutter={6}
455+
openDelay={0}
456+
value={
457+
<ModelTooltip
458+
model={item}
459+
latest={item.latest}
460+
free={isFree(item.provider.id, item.cost)}
461+
v2
462+
/>
463+
}
460464
>
461-
<span class="min-w-0 truncate">{item.name}</span>
462-
<Show when={isFree(item.provider.id, item.cost)}>
463-
<TagV2 class="shrink-0">{language.t("model.tag.free")}</TagV2>
464-
</Show>
465-
<Show when={item.latest}>
466-
<TagV2 class="shrink-0">{language.t("model.tag.latest")}</TagV2>
467-
</Show>
468-
</MenuV2.RadioItem>
465+
<MenuV2.RadioItem
466+
value={modelKey(item)}
467+
data-option-key={modelKey(item)}
468+
data-selected-model={current() === modelKey(item) ? true : undefined}
469+
class="scroll-my-6 w-full"
470+
classList={{ "!bg-v2-overlay-simple-overlay-hover": store.active === modelKey(item) }}
471+
onMouseEnter={() => {
472+
setStore("active", modelKey(item))
473+
setTimeout(() => searchRef?.focus())
474+
}}
475+
onSelect={() => selectModel(item)}
476+
>
477+
<span class="min-w-0 truncate">{item.name}</span>
478+
<Show when={isFree(item.provider.id, item.cost)}>
479+
<TagV2 class="shrink-0">{language.t("model.tag.free")}</TagV2>
480+
</Show>
481+
<Show when={item.latest}>
482+
<TagV2 class="shrink-0">{language.t("model.tag.latest")}</TagV2>
483+
</Show>
484+
</MenuV2.RadioItem>
485+
</TooltipV2>
469486
)}
470487
</For>
471488
</MenuV2.RadioGroup>

packages/app/src/components/model-tooltip.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Show, type Component } from "solid-js"
1+
import { Show, type Component, type JSX } from "solid-js"
22
import { useLanguage } from "@/context/language"
33

44
type InputKey = "text" | "image" | "audio" | "video" | "pdf"
@@ -23,7 +23,16 @@ type ModelInfo = {
2323
}
2424
}
2525

26-
export const ModelTooltip: Component<{ model: ModelInfo; latest?: boolean; free?: boolean }> = (props) => {
26+
function ModelTooltipRow(props: { name: JSX.Element; value: JSX.Element }) {
27+
return (
28+
<div class="flex min-w-0 items-center gap-4">
29+
<span class="shrink-0 text-v2-text-text-muted">{props.name}</span>
30+
<span class="ml-auto min-w-0 truncate text-right text-v2-text-text-base">{props.value}</span>
31+
</div>
32+
)
33+
}
34+
35+
export const ModelTooltip: Component<{ model: ModelInfo; latest?: boolean; free?: boolean; v2?: boolean }> = (props) => {
2736
const language = useLanguage()
2837
const sourceName = (model: ModelInfo) => {
2938
const value = `${model.id} ${model.name}`.toLowerCase()
@@ -51,6 +60,13 @@ export const ModelTooltip: Component<{ model: ModelInfo; latest?: boolean; free?
5160
const suffix = tags.length ? ` (${tags.join(", ")})` : ""
5261
return `${sourceName(props.model)} ${props.model.name}${suffix}`
5362
}
63+
const name = () => {
64+
const tags: Array<string> = []
65+
if (props.latest) tags.push(language.t("model.tag.latest"))
66+
if (props.free) tags.push(language.t("model.tag.free"))
67+
const suffix = tags.length ? ` (${tags.join(", ")})` : ""
68+
return `${props.model.name}${suffix}`
69+
}
5470
const inputs = () => {
5571
if (props.model.capabilities) {
5672
const input = props.model.capabilities.input
@@ -73,6 +89,21 @@ export const ModelTooltip: Component<{ model: ModelInfo; latest?: boolean; free?
7389
: language.t("model.tooltip.reasoning.none")
7490
}
7591
const context = () => language.t("model.tooltip.context", { limit: props.model.limit.context.toLocaleString() })
92+
const contextLimit = () => props.model.limit.context.toLocaleString(language.intl())
93+
94+
if (props.v2) {
95+
return (
96+
<div class="flex w-[180px] flex-col gap-2">
97+
<ModelTooltipRow name={language.t("model.tooltip.model")} value={name()} />
98+
<ModelTooltipRow name={language.t("model.tooltip.provider")} value={props.model.provider.name} />
99+
<Show when={inputs()}>
100+
{(value) => <ModelTooltipRow name={language.t("model.tooltip.inputs")} value={value()} />}
101+
</Show>
102+
<ModelTooltipRow name={language.t("model.tooltip.reasoning")} value={reasoning()} />
103+
<ModelTooltipRow name={language.t("model.tooltip.context.label")} value={contextLimit()} />
104+
</div>
105+
)
106+
}
76107

77108
return (
78109
<div class="flex flex-col gap-1 py-1">

packages/app/src/i18n/en.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ export const dict = {
212212
"model.input.video": "video",
213213
"model.input.pdf": "pdf",
214214
"model.tooltip.allows": "Allows: {{inputs}}",
215+
"model.tooltip.context.label": "Context",
216+
"model.tooltip.inputs": "Inputs",
217+
"model.tooltip.model": "Model",
218+
"model.tooltip.provider": "Provider",
219+
"model.tooltip.reasoning": "Reasoning",
215220
"model.tooltip.reasoning.allowed": "Allows reasoning",
216221
"model.tooltip.reasoning.none": "No reasoning",
217222
"model.tooltip.context": "Context limit {{limit}}",

0 commit comments

Comments
 (0)