From 319b57f1f15ce23bb5cd373b3ce5acff47ac7c2b Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2026 21:26:32 -0500 Subject: [PATCH 1/3] fix: add filter display setting and revert name changes (#548) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add a "Filter Display" setting in Settings > Models to toggle between showing provider names (default) or icons in model selector filter tabs - Revert "Meta Llama" → "Llama" renaming from PR #551 (keep original names) - Persist filter display preference in localStorage via the UI store Co-Authored-By: Claude Opus 4.5 --- apps/web/src/components/model-selector.tsx | 15 ++++++-- apps/web/src/routes/settings.tsx | 44 ++++++++++++++++++++++ apps/web/src/stores/model.ts | 4 +- apps/web/src/stores/ui.ts | 11 ++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/model-selector.tsx b/apps/web/src/components/model-selector.tsx index 792df0db..b7d390f4 100644 --- a/apps/web/src/components/model-selector.tsx +++ b/apps/web/src/components/model-selector.tsx @@ -4,6 +4,7 @@ import type { Model } from "@/stores/model"; import { cn } from "@/lib/utils"; import { getModelById, useModels, useModelStore } from "@/stores/model"; import { useFavoriteModels } from "@/hooks/use-favorite-models"; +import { useUIStore } from "@/stores/ui"; import { CheckIcon, ChevronDownIcon, SearchIcon } from "@/components/icons"; function useIsMobile() { @@ -243,6 +244,7 @@ export function ModelSelector({ const { models, isLoading } = useModels(); const { favorites, toggleFavorite, isFavorite, addDefaults, missingDefaultsCount } = useFavoriteModels(); + const filterStyle = useUIStore((s) => s.filterStyle); const deferredQuery = useDeferredValue(query); const isSearching = deferredQuery.trim().length > 0; @@ -573,7 +575,9 @@ export function ModelSelector({ : "bg-muted/50 text-muted-foreground active:bg-accent active:text-foreground", )} > - + {filterStyle === "icons" ? ( + + ) : null} {provider.name} ))} @@ -708,14 +712,19 @@ export function ModelSelector({ } }} className={cn( - "flex size-9 items-center justify-center rounded-xl transition-all duration-200", + "flex items-center justify-center rounded-xl transition-all duration-200", + filterStyle === "icons" ? "size-9" : "h-9 w-full px-2", selectedProvider === provider.id ? "bg-accent text-foreground shadow-sm" : "text-muted-foreground hover:bg-accent/60 hover:text-foreground hover:scale-105", )} title={provider.name} > - + {filterStyle === "icons" ? ( + + ) : ( + {provider.name} + )} ))} diff --git a/apps/web/src/routes/settings.tsx b/apps/web/src/routes/settings.tsx index 2f58362b..a3a17491 100644 --- a/apps/web/src/routes/settings.tsx +++ b/apps/web/src/routes/settings.tsx @@ -14,6 +14,7 @@ import { useOpenRouterKey } from "@/stores/openrouter"; import { useProviderStore, DAILY_LIMIT_CENTS } from "@/stores/provider"; import { useModels, getCacheStatus } from "@/stores/model"; import { useChatTitleStore, type ChatTitleLength } from "@/stores/chat-title"; +import { useUIStore } from "@/stores/ui"; import { OpenRouterConnectModal } from "@/components/openrouter-connect-modal"; import { DeleteAccountModal } from "@/components/delete-account-modal"; import { Switch } from "@/components/ui/switch"; @@ -721,6 +722,8 @@ function ModelsSection() { const { models, isLoading, reload, totalCount, error } = useModels(); const cacheStatus = getCacheStatus(); const [isReloading, setIsReloading] = useState(false); + const filterStyle = useUIStore((s) => s.filterStyle); + const setFilterStyle = useUIStore((s) => s.setFilterStyle); const handleReload = async () => { setIsReloading(true); @@ -744,6 +747,47 @@ function ModelsSection() { return (
+ {/* Filter Display */} +
+

+ Filter Display +

+
+
+
+

Provider filters

+

+ Show provider names or icons in the model selector filters. +

+
+
+ + +
+
+
+
+ {/* Model Source Info */}

diff --git a/apps/web/src/stores/model.ts b/apps/web/src/stores/model.ts index 1f86fae0..cff1bec2 100644 --- a/apps/web/src/stores/model.ts +++ b/apps/web/src/stores/model.ts @@ -61,7 +61,7 @@ const PROVIDER_INFO: Record = { openai: { name: "OpenAI", logoId: "openai" }, anthropic: { name: "Anthropic", logoId: "anthropic" }, google: { name: "Google", logoId: "google" }, - "meta-llama": { name: "Llama", logoId: "llama" }, + "meta-llama": { name: "Meta Llama", logoId: "llama" }, mistralai: { name: "Mistral", logoId: "mistral" }, deepseek: { name: "DeepSeek", logoId: "deepseek" }, "x-ai": { name: "xAI", logoId: "xai" }, @@ -457,7 +457,7 @@ function getFallbackModels(): Model[] { { id: "meta-llama/llama-3.3-70b-instruct", name: "Llama 3.3 70B", - provider: "Llama", + provider: "Meta Llama", providerId: "meta-llama", logoId: "llama", family: "Llama 3.3", diff --git a/apps/web/src/stores/ui.ts b/apps/web/src/stores/ui.ts index 62e80836..d7df25cd 100644 --- a/apps/web/src/stores/ui.ts +++ b/apps/web/src/stores/ui.ts @@ -5,6 +5,8 @@ import { create } from "zustand"; import { persist, devtools } from "zustand/middleware"; +export type FilterStyle = "names" | "icons"; + interface UIState { // Sidebar sidebarOpen: boolean; @@ -13,12 +15,16 @@ interface UIState { // Command palette commandPaletteOpen: boolean; + // Model selector filter display + filterStyle: FilterStyle; + // Actions toggleSidebar: () => void; setSidebarOpen: (open: boolean) => void; setSidebarCollapsed: (collapsed: boolean) => void; toggleCommandPalette: () => void; setCommandPaletteOpen: (open: boolean) => void; + setFilterStyle: (style: FilterStyle) => void; } export const useUIStore = create()( @@ -28,6 +34,7 @@ export const useUIStore = create()( sidebarOpen: true, sidebarCollapsed: false, commandPaletteOpen: false, + filterStyle: "names" as FilterStyle, toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen }), false, "ui/toggleSidebar"), @@ -46,11 +53,15 @@ export const useUIStore = create()( setCommandPaletteOpen: (open) => set({ commandPaletteOpen: open }, false, "ui/setCommandPaletteOpen"), + + setFilterStyle: (style) => + set({ filterStyle: style }, false, "ui/setFilterStyle"), }), { name: "ui-store", partialize: (state) => ({ sidebarCollapsed: state.sidebarCollapsed, + filterStyle: state.filterStyle, }), }, ), From a65b18915615a551b5ea812c05d0f7ab0a6d1177 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 22 Jan 2026 21:44:04 -0500 Subject: [PATCH 2/3] fix: toggle between company/model names, always show icons - Change filter setting from names/icons to company/model name toggle - Icons (provider logos) are now always shown in filter tabs - Add modelName field (e.g., "GPT", "Claude", "Llama") for model-name mode - Default to model names as requested in #548 comments Co-Authored-By: Claude Opus 4.5 --- apps/web/src/components/model-selector.tsx | 22 ++++++++---------- apps/web/src/routes/settings.tsx | 16 ++++++------- apps/web/src/stores/model.ts | 26 ++++++++++++++-------- apps/web/src/stores/ui.ts | 4 ++-- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/apps/web/src/components/model-selector.tsx b/apps/web/src/components/model-selector.tsx index b7d390f4..97a92e23 100644 --- a/apps/web/src/components/model-selector.tsx +++ b/apps/web/src/components/model-selector.tsx @@ -252,7 +252,7 @@ export function ModelSelector({ const selectedModel = useMemo(() => getModelById(models, value), [models, value]); const uniqueProviders = useMemo(() => { - const providerMap = new Map(); + const providerMap = new Map(); for (const model of models) { const existing = providerMap.get(model.providerId); if (existing) { @@ -261,6 +261,7 @@ export function ModelSelector({ providerMap.set(model.providerId, { id: model.providerId, name: model.provider, + modelName: model.modelName, logoId: model.logoId, count: 1, }); @@ -575,10 +576,10 @@ export function ModelSelector({ : "bg-muted/50 text-muted-foreground active:bg-accent active:text-foreground", )} > - {filterStyle === "icons" ? ( - - ) : null} - {provider.name} + + + {filterStyle === "company" ? provider.name : provider.modelName} + ))}

@@ -712,19 +713,14 @@ export function ModelSelector({ } }} className={cn( - "flex items-center justify-center rounded-xl transition-all duration-200", - filterStyle === "icons" ? "size-9" : "h-9 w-full px-2", + "flex size-9 items-center justify-center rounded-xl transition-all duration-200", selectedProvider === provider.id ? "bg-accent text-foreground shadow-sm" : "text-muted-foreground hover:bg-accent/60 hover:text-foreground hover:scale-105", )} - title={provider.name} + title={filterStyle === "company" ? provider.name : provider.modelName} > - {filterStyle === "icons" ? ( - - ) : ( - {provider.name} - )} + ))} diff --git a/apps/web/src/routes/settings.tsx b/apps/web/src/routes/settings.tsx index a3a17491..10fed105 100644 --- a/apps/web/src/routes/settings.tsx +++ b/apps/web/src/routes/settings.tsx @@ -755,33 +755,33 @@ function ModelsSection() {
-

Provider filters

+

Provider filter labels

- Show provider names or icons in the model selector filters. + Show company names (OpenAI, Meta Llama) or model names (GPT, Llama) in filters.

diff --git a/apps/web/src/stores/model.ts b/apps/web/src/stores/model.ts index cff1bec2..6263c6c5 100644 --- a/apps/web/src/stores/model.ts +++ b/apps/web/src/stores/model.ts @@ -38,7 +38,8 @@ interface OpenRouterModel { export interface Model { id: string; name: string; - provider: string; // Provider display name (e.g., "Anthropic") + provider: string; // Provider/company name (e.g., "Anthropic", "Meta Llama") + modelName: string; // Model/product name for filters (e.g., "Claude", "Llama") providerId: string; // Provider slug from model ID (e.g., "meta-llama", "qwen") logoId: string; // Logo slug for models.dev (e.g., "llama", "alibaba") family?: string; // Model family (e.g., "claude-3.5") @@ -57,20 +58,20 @@ export interface Model { // Provider mapping for display names and logo IDs // ============================================================================ -const PROVIDER_INFO: Record = { - openai: { name: "OpenAI", logoId: "openai" }, - anthropic: { name: "Anthropic", logoId: "anthropic" }, - google: { name: "Google", logoId: "google" }, - "meta-llama": { name: "Meta Llama", logoId: "llama" }, +const PROVIDER_INFO: Record = { + openai: { name: "OpenAI", modelName: "GPT", logoId: "openai" }, + anthropic: { name: "Anthropic", modelName: "Claude", logoId: "anthropic" }, + google: { name: "Google", modelName: "Gemini", logoId: "google" }, + "meta-llama": { name: "Meta Llama", modelName: "Llama", logoId: "llama" }, mistralai: { name: "Mistral", logoId: "mistral" }, deepseek: { name: "DeepSeek", logoId: "deepseek" }, - "x-ai": { name: "xAI", logoId: "xai" }, + "x-ai": { name: "xAI", modelName: "Grok", logoId: "xai" }, cohere: { name: "Cohere", logoId: "cohere" }, perplexity: { name: "Perplexity", logoId: "perplexity" }, qwen: { name: "Qwen", logoId: "alibaba" }, nvidia: { name: "NVIDIA", logoId: "nvidia" }, - microsoft: { name: "Microsoft", logoId: "azure" }, - amazon: { name: "Amazon", logoId: "amazon-bedrock" }, + microsoft: { name: "Microsoft", modelName: "Phi", logoId: "azure" }, + amazon: { name: "Amazon", modelName: "Nova", logoId: "amazon-bedrock" }, ai21: { name: "AI21", logoId: "ai21" }, together: { name: "Together", logoId: "togetherai" }, "fireworks-ai": { name: "Fireworks", logoId: "fireworks-ai" }, @@ -292,6 +293,7 @@ function transformModel(raw: OpenRouterModel): Model { id, name: raw.name || id, provider: info.name, + modelName: info.modelName || info.name, providerId: providerSlug, logoId: info.logoId, family: extractFamily(id, raw.name || ""), @@ -413,6 +415,7 @@ function getFallbackModels(): Model[] { id: "anthropic/claude-3.5-sonnet", name: "Claude 3.5 Sonnet", provider: "Anthropic", + modelName: "Claude", providerId: "anthropic", logoId: "anthropic", family: "Claude 3.5", @@ -422,6 +425,7 @@ function getFallbackModels(): Model[] { id: "openai/gpt-4o", name: "GPT-4o", provider: "OpenAI", + modelName: "GPT", providerId: "openai", logoId: "openai", family: "GPT-4o", @@ -431,6 +435,7 @@ function getFallbackModels(): Model[] { id: "openai/gpt-4o-mini", name: "GPT-4o Mini", provider: "OpenAI", + modelName: "GPT", providerId: "openai", logoId: "openai", family: "GPT-4o", @@ -440,6 +445,7 @@ function getFallbackModels(): Model[] { id: "google/gemini-2.5-flash", name: "Gemini 2.5 Flash", provider: "Google", + modelName: "Gemini", providerId: "google", logoId: "google", family: "Gemini 2.5", @@ -449,6 +455,7 @@ function getFallbackModels(): Model[] { id: "deepseek/deepseek-chat", name: "DeepSeek Chat", provider: "DeepSeek", + modelName: "DeepSeek", providerId: "deepseek", logoId: "deepseek", family: "DeepSeek", @@ -458,6 +465,7 @@ function getFallbackModels(): Model[] { id: "meta-llama/llama-3.3-70b-instruct", name: "Llama 3.3 70B", provider: "Meta Llama", + modelName: "Llama", providerId: "meta-llama", logoId: "llama", family: "Llama 3.3", diff --git a/apps/web/src/stores/ui.ts b/apps/web/src/stores/ui.ts index d7df25cd..946eedc4 100644 --- a/apps/web/src/stores/ui.ts +++ b/apps/web/src/stores/ui.ts @@ -5,7 +5,7 @@ import { create } from "zustand"; import { persist, devtools } from "zustand/middleware"; -export type FilterStyle = "names" | "icons"; +export type FilterStyle = "company" | "model"; interface UIState { // Sidebar @@ -34,7 +34,7 @@ export const useUIStore = create()( sidebarOpen: true, sidebarCollapsed: false, commandPaletteOpen: false, - filterStyle: "names" as FilterStyle, + filterStyle: "model" as FilterStyle, toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen }), false, "ui/toggleSidebar"), From 85fd43dd014120d990932cdc8953ede678ec3fe5 Mon Sep 17 00:00:00 2001 From: Leo Date: Fri, 23 Jan 2026 06:20:18 -0500 Subject: [PATCH 3/3] fix: show only icons in mobile filter tabs (match desktop) Mobile filter tabs now show icon-only buttons like the desktop sidebar, with provider name available as tooltip on long-press. Co-Authored-By: Claude Opus 4.5 --- apps/web/src/components/model-selector.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/model-selector.tsx b/apps/web/src/components/model-selector.tsx index 97a92e23..9356c067 100644 --- a/apps/web/src/components/model-selector.tsx +++ b/apps/web/src/components/model-selector.tsx @@ -570,16 +570,14 @@ export function ModelSelector({ } }} className={cn( - "flex h-9 shrink-0 items-center gap-2 rounded-full px-3.5 text-sm font-medium transition-all duration-200", + "flex size-9 shrink-0 items-center justify-center rounded-full transition-all duration-200", selectedProvider === provider.id ? "bg-accent text-foreground" : "bg-muted/50 text-muted-foreground active:bg-accent active:text-foreground", )} + title={filterStyle === "company" ? provider.name : provider.modelName} > - - - {filterStyle === "company" ? provider.name : provider.modelName} - + ))}