fix: make model selector label responsive to panel width (#443)

* fix: make model selector label responsive to panel width

* Apply suggestion from @DayuanJiang

Co-authored-by: Dayuan Jiang <34411969+DayuanJiang@users.noreply.github.com>

---------

Co-authored-by: Dayuan Jiang <34411969+DayuanJiang@users.noreply.github.com>
This commit is contained in:
Biki Kalita
2025-12-29 09:24:13 +05:30
committed by GitHub
parent 27f26d8b26
commit 49b086cef3

View File

@@ -8,7 +8,7 @@ import {
Server, Server,
Settings2, Settings2,
} from "lucide-react" } from "lucide-react"
import { useMemo, useState } from "react" import { useEffect, useMemo, useRef, useState } from "react"
import { import {
ModelSelectorContent, ModelSelectorContent,
ModelSelectorEmpty, ModelSelectorEmpty,
@@ -114,7 +114,42 @@ export function ModelSelector({
? `${selectedModel.modelId} ${dict.modelConfig.clickToChange}` ? `${selectedModel.modelId} ${dict.modelConfig.clickToChange}`
: `${dict.modelConfig.usingServerDefault} ${dict.modelConfig.clickToChange}` : `${dict.modelConfig.usingServerDefault} ${dict.modelConfig.clickToChange}`
const wrapperRef = useRef<HTMLDivElement | null>(null)
const [showLabel, setShowLabel] = useState(true)
// Threshold (px) under which we hide the label (tweak as needed)
const HIDE_THRESHOLD = 240
const SHOW_THRESHOLD = 260
useEffect(() => {
const el = wrapperRef.current
if (!el) return
const target = el.parentElement ?? el
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
const width = entry.contentRect.width
setShowLabel((prev) => {
// if currently showing and width dropped below hide threshold -> hide
if (prev && width <= HIDE_THRESHOLD) return false
// if currently hidden and width rose above show threshold -> show
if (!prev && width >= SHOW_THRESHOLD) return true
// otherwise keep previous state (hysteresis)
return prev
})
}
})
ro.observe(target)
const initialWidth = target.getBoundingClientRect().width
setShowLabel(initialWidth >= SHOW_THRESHOLD)
return () => ro.disconnect()
}, [])
return ( return (
<div ref={wrapperRef} className="inline-block">
<ModelSelectorRoot open={open} onOpenChange={setOpen}> <ModelSelectorRoot open={open} onOpenChange={setOpen}>
<ModelSelectorTrigger asChild> <ModelSelectorTrigger asChild>
<ButtonWithTooltip <ButtonWithTooltip
@@ -122,17 +157,33 @@ export function ModelSelector({
variant="ghost" variant="ghost"
size="sm" size="sm"
disabled={disabled} disabled={disabled}
className="hover:bg-accent gap-1.5 h-8 max-w-[180px] px-2" className={cn(
"hover:bg-accent gap-1.5 h-8 px-2 transition-all duration-150 ease-in-out",
!showLabel && "px-1.5 justify-center",
)}
// accessibility: expose label to screen readers
aria-label={tooltipContent}
> >
<Bot className="h-4 w-4 flex-shrink-0 text-muted-foreground" /> <Bot className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
{/* show/hide visible label based on measured width */}
{showLabel ? (
<span className="text-xs truncate"> <span className="text-xs truncate">
{selectedModel {selectedModel
? selectedModel.modelId ? selectedModel.modelId
: dict.modelConfig.default} : dict.modelConfig.default}
</span> </span>
) : (
// Keep an sr-only label for screen readers when hidden
<span className="sr-only">
{selectedModel
? selectedModel.modelId
: dict.modelConfig.default}
</span>
)}
<ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" /> <ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" />
</ButtonWithTooltip> </ButtonWithTooltip>
</ModelSelectorTrigger> </ModelSelectorTrigger>
<ModelSelectorContent title={dict.modelConfig.selectModel}> <ModelSelectorContent title={dict.modelConfig.selectModel}>
<ModelSelectorInput <ModelSelectorInput
placeholder={dict.modelConfig.searchModels} placeholder={dict.modelConfig.searchModels}
@@ -183,7 +234,9 @@ export function ModelSelector({
<ModelSelectorItem <ModelSelectorItem
key={model.id} key={model.id}
value={model.modelId} value={model.modelId}
onSelect={() => handleSelect(model.id)} onSelect={() =>
handleSelect(model.id)
}
className="cursor-pointer" className="cursor-pointer"
> >
<Check <Check
@@ -196,8 +249,9 @@ export function ModelSelector({
/> />
<ModelSelectorLogo <ModelSelectorLogo
provider={ provider={
PROVIDER_LOGO_MAP[provider] || PROVIDER_LOGO_MAP[
provider provider
] || provider
} }
className="mr-2" className="mr-2"
/> />
@@ -243,5 +297,6 @@ export function ModelSelector({
</ModelSelectorList> </ModelSelectorList>
</ModelSelectorContent> </ModelSelectorContent>
</ModelSelectorRoot> </ModelSelectorRoot>
</div>
) )
} }