mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-22 22:48:11 +02:00
feat(ui): sélecteur de modèle dans le composer, retiré du TopBar
Le chip modèle du composer était décoratif (pastille orange fixe) alors que le TopBar montrait le vrai état de chargement. Le sélecteur complet (liste + pastille GPU/CPU/à charger/préchargement) vit maintenant dans la carte du chat, menu vers le haut. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
bb8e87b612
commit
b0018e8313
3 files changed
+23
-14
No files matched your search
@@ -2,8 +2,15 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import { useStore } from "../store/useStore";
|
import { useStore } from "../store/useStore";
|
||||||
import { ChevronDown } from "./Icon";
|
import { ChevronDown } from "./Icon";
|
||||||
|
|
||||||
/** Sélecteur de modèle Ollama (chip orange de la barre supérieure). */
|
/** Sélecteur de modèle Ollama (chip orange, pastille = état de chargement).
|
||||||
export function ModelSelector() {
|
|
||||||
|
variant "composer" : taille alignée sur les chips du composer, menu vers
|
||||||
|
le haut. */
|
||||||
|
export function ModelSelector({
|
||||||
|
variant = "top",
|
||||||
|
}: {
|
||||||
|
variant?: "top" | "composer";
|
||||||
|
}) {
|
||||||
const {
|
const {
|
||||||
models,
|
models,
|
||||||
selectedModel,
|
selectedModel,
|
||||||
@@ -31,7 +38,11 @@ export function ModelSelector() {
|
|||||||
<div className="relative" ref={ref}>
|
<div className="relative" ref={ref}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setOpen((v) => !v)}
|
onClick={() => setOpen((v) => !v)}
|
||||||
className="flex h-[34px] min-w-0 max-w-[260px] items-center gap-2 border-[3px] border-white bg-accent px-3 text-white shadow-accent-soft"
|
className={
|
||||||
|
variant === "composer"
|
||||||
|
? "flex h-8 min-w-0 max-w-[220px] items-center gap-1.5 border-2 border-line bg-accent px-2.5 text-[13px] text-white"
|
||||||
|
: "flex h-[34px] min-w-0 max-w-[260px] items-center gap-2 border-[3px] border-white bg-accent px-3 text-white shadow-accent-soft"
|
||||||
|
}
|
||||||
title={selectedModel || undefined}
|
title={selectedModel || undefined}
|
||||||
style={{ borderRadius: 7 }}
|
style={{ borderRadius: 7 }}
|
||||||
>
|
>
|
||||||
@@ -62,7 +73,13 @@ export function ModelSelector() {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{open && (
|
{open && (
|
||||||
<div className="absolute right-0 top-11 z-20 w-64 border-[3px] border-line bg-card p-1 shadow-hard">
|
<div
|
||||||
|
className={`absolute z-20 w-64 border-[3px] border-line bg-card p-1 shadow-hard ${
|
||||||
|
variant === "composer"
|
||||||
|
? "bottom-[calc(100%+6px)] left-0"
|
||||||
|
: "right-0 top-11"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{models.length === 0 && (
|
{models.length === 0 && (
|
||||||
<div className="px-3 py-2 text-xs text-muted-2">
|
<div className="px-3 py-2 text-xs text-muted-2">
|
||||||
Aucun modèle installé
|
Aucun modèle installé
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { useEffect, useState } from "react";
|
|||||||
import { useStore } from "../store/useStore";
|
import { useStore } from "../store/useStore";
|
||||||
import { getVersion } from "../api/client";
|
import { getVersion } from "../api/client";
|
||||||
import { LokiMark } from "./Icon";
|
import { LokiMark } from "./Icon";
|
||||||
import { ModelSelector } from "./ModelSelector";
|
|
||||||
import { SessionMenu } from "./SessionMenu";
|
import { SessionMenu } from "./SessionMenu";
|
||||||
|
|
||||||
/** Barre supérieure sombre : logo, fil d'Ariane, statut Ollama, sélecteur. */
|
/** Barre supérieure sombre : logo, fil d'Ariane, statut Ollama, sélecteur. */
|
||||||
@@ -72,8 +71,6 @@ export function TopBar() {
|
|||||||
{connected ? status?.host.replace(/^https?:\/\//, "") : "déconnecté"}
|
{connected ? status?.host.replace(/^https?:\/\//, "") : "déconnecté"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModelSelector />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import { ChevronDown, LokiMark, SendIcon } from "../components/Icon";
|
|||||||
import { ToolCard } from "../components/ToolCard";
|
import { ToolCard } from "../components/ToolCard";
|
||||||
import { MessageContent } from "../components/MessageContent";
|
import { MessageContent } from "../components/MessageContent";
|
||||||
import { ProjectChip } from "../components/ProjectChip";
|
import { ProjectChip } from "../components/ProjectChip";
|
||||||
|
import { ModelSelector } from "../components/ModelSelector";
|
||||||
import type { Message, ToolCall } from "../api/client";
|
import type { Message, ToolCall } from "../api/client";
|
||||||
|
|
||||||
/** Panneau central : barre de contexte, fil de conversation, composer. */
|
/** Panneau central : barre de contexte, fil de conversation, composer. */
|
||||||
@@ -138,13 +139,7 @@ export function ChatPanel() {
|
|||||||
<div className="mt-1.5 flex items-center gap-2">
|
<div className="mt-1.5 flex items-center gap-2">
|
||||||
<ModeSelector />
|
<ModeSelector />
|
||||||
<ProjectChip />
|
<ProjectChip />
|
||||||
<div
|
<ModelSelector variant="composer" />
|
||||||
className="flex h-8 min-w-0 max-w-[180px] items-center gap-1.5 border-2 border-line px-2.5 text-[13px] text-ink-2"
|
|
||||||
title={selectedModel || undefined}
|
|
||||||
>
|
|
||||||
<span className="h-2 w-2 border-2 border-line bg-accent" />
|
|
||||||
<span className="min-w-0 truncate">{selectedModel || "—"}</span>
|
|
||||||
</div>
|
|
||||||
{streaming && !showingStreaming ? (
|
{streaming && !showingStreaming ? (
|
||||||
<span className="min-w-0 flex-1 truncate text-[13px] text-accent">
|
<span className="min-w-0 flex-1 truncate text-[13px] text-accent">
|
||||||
Travail en cours : {workingSession?.title ?? "session ouverte"}
|
Travail en cours : {workingSession?.title ?? "session ouverte"}
|
||||||
|
|||||||
Reference in new issue
Block a user