From 99d4296ee142e97ee8fbf1955c5441f33dd252a2 Mon Sep 17 00:00:00 2001
From: michaelschal <35957947-michaelschal@users.noreply.replit.com>
Date: Sat, 11 Oct 2025 07:18:44 +0000
Subject: [PATCH] Enhance AI model selection with search and scroll
functionality
Replace standard select components with a new ModelCombobox component in both the AI chat and settings pages. This component supports searching and vertical scrolling for a better user experience when selecting AI models.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/cesUZ4w
---
client/src/components/ai-chat.tsx | 38 ++-----
client/src/components/model-combobox.tsx | 134 +++++++++++++++++++++++
client/src/pages/settings.tsx | 25 ++---
3 files changed, 156 insertions(+), 41 deletions(-)
create mode 100644 client/src/components/model-combobox.tsx
diff --git a/client/src/components/ai-chat.tsx b/client/src/components/ai-chat.tsx
index bb2d530..55320bd 100644
--- a/client/src/components/ai-chat.tsx
+++ b/client/src/components/ai-chat.tsx
@@ -6,7 +6,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { Bot, User, Lightbulb, History, Zap, Sparkles, Loader2 } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { ModelCombobox } from "@/components/model-combobox";
interface Message {
role: "user" | "assistant";
@@ -114,32 +114,16 @@ export default function AiChat() {
-
+
diff --git a/client/src/components/model-combobox.tsx b/client/src/components/model-combobox.tsx
new file mode 100644
index 0000000..90f6de2
--- /dev/null
+++ b/client/src/components/model-combobox.tsx
@@ -0,0 +1,134 @@
+import { useState } from "react";
+import { Check, ChevronsUpDown, Loader2 } from "lucide-react";
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@/components/ui/command";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+
+interface Model {
+ id: string;
+ name: string;
+ pricing?: {
+ prompt: string;
+ completion: string;
+ };
+}
+
+interface ModelComboboxProps {
+ models: Model[];
+ value: string;
+ onValueChange: (value: string) => void;
+ placeholder?: string;
+ isLoading?: boolean;
+ disabled?: boolean;
+ className?: string;
+ testId?: string;
+}
+
+export function ModelCombobox({
+ models,
+ value,
+ onValueChange,
+ placeholder = "Sélectionner un modèle",
+ isLoading = false,
+ disabled = false,
+ className,
+ testId,
+}: ModelComboboxProps) {
+ const [open, setOpen] = useState(false);
+ const [searchQuery, setSearchQuery] = useState("");
+
+ const selectedModel = models.find((model) => model.id === value);
+
+ const filteredModels = models.filter((model) =>
+ model.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ model.id.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ Aucun modèle trouvé.
+
+ {filteredModels.map((model) => (
+ {
+ onValueChange(currentValue);
+ setOpen(false);
+ setSearchQuery("");
+ }}
+ data-testid={`${testId}-option-${model.id}`}
+ >
+
+
+ {model.name}
+ {model.pricing && (
+
+ Prompt: ${model.pricing.prompt} | Completion: ${model.pricing.completion}
+
+ )}
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/client/src/pages/settings.tsx b/client/src/pages/settings.tsx
index 788aabb..e3bf3cb 100644
--- a/client/src/pages/settings.tsx
+++ b/client/src/pages/settings.tsx
@@ -8,10 +8,10 @@ import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { useToast } from "@/hooks/use-toast";
import { apiRequest, queryClient } from "@/lib/queryClient";
+import { ModelCombobox } from "@/components/model-combobox";
export default function Settings() {
const [sidebarOpen, setSidebarOpen] = useState(false);
@@ -33,7 +33,7 @@ export default function Settings() {
queryKey: ['/api/openrouter/config'],
});
- const { data: openrouterModels } = useQuery({
+ const { data: openrouterModels, isLoading: modelsLoading } = useQuery({
queryKey: ['/api/openrouter/models'],
});
@@ -227,18 +227,15 @@ export default function Settings() {
-
+
Choisissez le modèle d'IA pour générer vos publications