refactor: simplify alert descriptions, improved icons, improved UI in LLM settings

This commit is contained in:
Anish Sarkar 2026-04-10 19:07:35 +05:30
parent 0925f89b7c
commit 42572ad09d
11 changed files with 28 additions and 117 deletions

View file

@ -190,7 +190,7 @@ export function ImageModelManager({ searchSpaceId }: ImageModelManagerProps) {
? "model"
: "models"}
</span>{" "}
available from your administrator. Use the model selector to view and select them.
available from your administrator.
</p>
</AlertDescription>
</Alert>

View file

@ -10,7 +10,6 @@ import {
FileText,
ImageIcon,
RefreshCw,
Shuffle,
} from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
@ -44,7 +43,6 @@ import {
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { Spinner } from "@/components/ui/spinner";
import { getProviderIcon } from "@/lib/provider-icons";
import { cn } from "@/lib/utils";
const ROLE_DESCRIPTIONS = {
@ -79,8 +77,8 @@ const ROLE_DESCRIPTIONS = {
icon: Eye,
title: "Vision LLM",
description: "Vision-capable model for screenshot analysis and context extraction",
color: "text-amber-600 dark:text-amber-400",
bgColor: "bg-amber-500/10",
color: "text-muted-foreground",
bgColor: "bg-muted",
prefKey: "vision_llm_config_id" as const,
configType: "vision" as const,
},
@ -205,11 +203,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
),
];
const isAssignmentComplete =
allLLMConfigs.some((c) => c.id === assignments.agent_llm_id) &&
allLLMConfigs.some((c) => c.id === assignments.document_summary_llm_id) &&
allImageConfigs.some((c) => c.id === assignments.image_generation_config_id);
const isLoading =
configsLoading ||
preferencesLoading ||
@ -231,7 +224,7 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
return (
<div className="space-y-5 md:space-y-6">
{/* Header actions */}
<div className="flex items-center justify-between">
<div className="flex items-center justify-start">
<Button
variant="secondary"
size="sm"
@ -239,15 +232,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
disabled={isLoading}
className="gap-2"
>
<RefreshCw className="h-3.5 w-3.5" />
<RefreshCw className={cn("h-3.5 w-3.5", isLoading && "animate-spin")} />
Refresh
</Button>
{isAssignmentComplete && !isLoading && !hasError && (
<Badge variant="outline" className="text-xs gap-1.5 text-muted-foreground">
<CircleCheck className="h-3 w-3" />
All roles assigned
</Badge>
)}
</div>
{/* Error Alert */}
@ -343,8 +330,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
const assignedConfig = roleAllConfigs.find((config) => config.id === currentAssignment);
const isAssigned = !!assignedConfig;
const isAutoMode =
assignedConfig && "is_auto_mode" in assignedConfig && assignedConfig.is_auto_mode;
return (
<div key={key}>
@ -389,7 +374,7 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
<SelectTrigger className="w-full h-9 md:h-10 text-xs md:text-sm">
<SelectValue placeholder="Select a configuration" />
</SelectTrigger>
<SelectContent className="max-w-[calc(100vw-2rem)]">
<SelectContent className="max-w-[calc(100vw-2rem)] select-none">
<SelectItem
value="unassigned"
className="text-xs md:text-sm py-1.5 md:py-2"
@ -412,21 +397,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
className="text-xs md:text-sm py-1.5 md:py-2"
>
<div className="flex items-center gap-1 md:gap-1.5 flex-wrap min-w-0">
{isAuto ? (
<Shuffle className="size-3 md:size-3.5 shrink-0 text-muted-foreground" />
) : (
getProviderIcon(config.provider, {
className: "size-3 md:size-3.5 shrink-0",
})
)}
<span className="truncate text-xs md:text-sm">
{config.name}
</span>
{!isAuto && (
<span className="text-muted-foreground text-[10px] md:text-[11px] truncate">
({config.model_name})
</span>
)}
{isAuto && (
<Badge
variant="secondary"
@ -455,15 +428,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
className="text-xs md:text-sm py-1.5 md:py-2"
>
<div className="flex items-center gap-1 md:gap-1.5 flex-wrap min-w-0">
{getProviderIcon(config.provider, {
className: "size-3 md:size-3.5 shrink-0",
})}
<span className="truncate text-xs md:text-sm">
{config.name}
</span>
<span className="text-muted-foreground text-[10px] md:text-[11px] truncate">
({config.model_name})
</span>
</div>
</SelectItem>
))}
@ -473,62 +440,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
</Select>
</div>
{/* Assigned Config Summary */}
{assignedConfig && (
<div
className={cn(
"rounded-lg p-3 border",
isAutoMode
? "bg-violet-50 dark:bg-violet-900/10 border-violet-200/50 dark:border-violet-800/30"
: "bg-muted/40 border-border/50"
)}
>
{isAutoMode ? (
<div className="flex items-center gap-2">
<Shuffle
className={cn(
"w-3.5 h-3.5 shrink-0 text-violet-600 dark:text-violet-400"
)}
/>
<div className="min-w-0">
<p className="text-xs font-medium text-violet-700 dark:text-violet-300">
Auto Mode
</p>
<p className="text-[10px] text-violet-600/70 dark:text-violet-400/70 mt-0.5">
Routes across all available providers
</p>
</div>
</div>
) : (
<div className="flex items-start gap-2">
<IconComponent className="w-3.5 h-3.5 shrink-0 mt-0.5 text-muted-foreground" />
<div className="min-w-0 flex-1">
<div className="flex items-center gap-1.5 flex-wrap">
<span className="text-xs font-medium">{assignedConfig.name}</span>
{"is_global" in assignedConfig && assignedConfig.is_global && (
<Badge variant="secondary" className="text-[9px] px-1.5 py-0">
🌐 Global
</Badge>
)}
</div>
<div className="flex items-center gap-1.5 mt-1">
{getProviderIcon(assignedConfig.provider, {
className: "size-3 shrink-0",
})}
<code className="text-[10px] text-muted-foreground font-mono truncate">
{assignedConfig.model_name}
</code>
</div>
{assignedConfig.api_base && (
<p className="text-[10px] text-muted-foreground/60 mt-1 truncate">
{assignedConfig.api_base}
</p>
)}
</div>
</div>
)}
</div>
)}
</CardContent>
</Card>
</div>

View file

@ -196,7 +196,7 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
<span className="font-medium">
{globalConfigs.length} global {globalConfigs.length === 1 ? "model" : "models"}
</span>{" "}
available from your administrator. Use the model selector to view and select them.
available from your administrator.
</p>
</AlertDescription>
</Alert>

View file

@ -2,15 +2,15 @@
import { useAtom } from "jotai";
import {
BookMarked,
Bot,
BookText,
Brain,
CircleUser,
Earth,
Eye,
FileText,
Globe,
ImageIcon,
MessageSquare,
Shield,
ListChecks,
UserKey
} from "lucide-react";
import dynamic from "next/dynamic";
import { useTranslations } from "next-intl";
@ -86,9 +86,9 @@ export function SearchSpaceSettingsDialog({ searchSpaceId }: SearchSpaceSettings
const [state, setState] = useAtom(searchSpaceSettingsDialogAtom);
const navItems = [
{ value: "general", label: t("nav_general"), icon: <FileText className="h-4 w-4" /> },
{ value: "general", label: t("nav_general"), icon: <CircleUser className="h-4 w-4" /> },
{ value: "roles", label: t("nav_role_assignments"), icon: <ListChecks className="h-4 w-4" /> },
{ value: "models", label: t("nav_agent_configs"), icon: <Bot className="h-4 w-4" /> },
{ value: "roles", label: t("nav_role_assignments"), icon: <Brain className="h-4 w-4" /> },
{
value: "image-models",
label: t("nav_image_models"),
@ -99,18 +99,18 @@ export function SearchSpaceSettingsDialog({ searchSpaceId }: SearchSpaceSettings
label: t("nav_vision_models"),
icon: <Eye className="h-4 w-4" />,
},
{ value: "team-roles", label: t("nav_team_roles"), icon: <Shield className="h-4 w-4" /> },
{ value: "team-roles", label: t("nav_team_roles"), icon: <UserKey className="h-4 w-4" /> },
{
value: "prompts",
label: t("nav_system_instructions"),
icon: <MessageSquare className="h-4 w-4" />,
icon: <BookText className="h-4 w-4" />,
},
{
value: "team-memory",
label: "Team Memory",
icon: <BookMarked className="h-4 w-4" />,
icon: <Brain className="h-4 w-4" />,
},
{ value: "public-links", label: t("nav_public_links"), icon: <Globe className="h-4 w-4" /> },
{ value: "public-links", label: t("nav_public_links"), icon: <Earth className="h-4 w-4" /> },
];
const content: Record<string, React.ReactNode> = {

View file

@ -188,7 +188,7 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
<AlertDescription className="text-xs md:text-sm">
<p>
SurfSense uses this shared memory to provide team-wide context across all conversations
in this search space. Use the input below to add, update, or remove memory entries.
in this search space.
</p>
</AlertDescription>
</Alert>

View file

@ -1,7 +1,7 @@
"use client";
import { useAtom } from "jotai";
import { Brain, Globe, KeyRound, Monitor, Receipt, Sparkles, User } from "lucide-react";
import { Brain, CircleUser, Globe, KeyRound, Monitor, ReceiptText, Sparkles } from "lucide-react";
import dynamic from "next/dynamic";
import { useTranslations } from "next-intl";
import { useMemo } from "react";
@ -66,7 +66,7 @@ export function UserSettingsDialog() {
const navItems = useMemo(
() => [
{ value: "profile", label: t("profile_nav_label"), icon: <User className="h-4 w-4" /> },
{ value: "profile", label: t("profile_nav_label"), icon: <CircleUser className="h-4 w-4" /> },
{
value: "api-key",
label: t("api_key_nav_label"),
@ -90,7 +90,7 @@ export function UserSettingsDialog() {
{
value: "purchases",
label: "Purchase History",
icon: <Receipt className="h-4 w-4" />,
icon: <ReceiptText className="h-4 w-4" />,
},
...(isDesktop
? [{ value: "desktop", label: "Desktop", icon: <Monitor className="h-4 w-4" /> }]

View file

@ -191,7 +191,7 @@ export function VisionModelManager({ searchSpaceId }: VisionModelManagerProps) {
? "model"
: "models"}
</span>{" "}
available from your administrator. Use the model selector to view and select them.
available from your administrator.
</p>
</AlertDescription>
</Alert>