From 9cbda709b69f62d47785d1ea13d5f53dceed29f5 Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Fri, 17 Jul 2026 10:15:35 +0700 Subject: [PATCH] refactor(ui): finish the Spinner migration, retire the Loader2 alias from JSX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The remaining 20 rendered Loader2 spinners carried a deliberate size or colour, so the earlier pass left them. They convert cleanly after all: Loader2 is a lucide alias of LoaderCircle (`LoaderCircle as Loader2` in lucide-react's d.ts) and that is exactly what Spinner variant="circle" renders, while Circle merges an incoming className over its built-in animate-spin. So each site keeps its size/colour class and only drops the now-redundant animate-spin. Every rendered spinner in the app is the Spinner primitive now. flow-status-icon and flow-task-status-icon keep Loader2: there it is a value in a Record map, not a rendered spinner, and Spinner is a variant wrapper rather than a LucideIcon — it does not fit that slot. Co-Authored-By: Claude Opus 4.8 --- .../src/components/dashboard/chart-card.tsx | 8 ++++-- .../markdown-editor/markdown-editor-field.tsx | 7 +++-- .../markdown-editor/markdown-editor.tsx | 7 +++-- frontend/src/components/ui/sonner.tsx | 10 +++++-- .../dashboard/flow-dashboard-overview.tsx | 8 ++++-- .../pages/dashboard/dashboard-analytics.tsx | 8 ++++-- .../pages/dashboard/dashboard-overview.tsx | 8 ++++-- frontend/src/pages/flows/flow.tsx | 6 +++-- frontend/src/pages/flows/flows.tsx | 7 +++-- frontend/src/pages/knowledges/knowledges.tsx | 7 +++-- frontend/src/pages/login.tsx | 7 +++-- .../pages/settings/settings-api-tokens.tsx | 6 +++-- .../src/pages/settings/settings-prompt.tsx | 6 +++-- .../src/pages/settings/settings-prompts.tsx | 27 ++++++++++++++----- .../src/pages/settings/settings-provider.tsx | 6 +++-- .../src/pages/settings/settings-providers.tsx | 7 +++-- 16 files changed, 99 insertions(+), 36 deletions(-) diff --git a/frontend/src/components/dashboard/chart-card.tsx b/frontend/src/components/dashboard/chart-card.tsx index 03e38304..12cec260 100644 --- a/frontend/src/components/dashboard/chart-card.tsx +++ b/frontend/src/components/dashboard/chart-card.tsx @@ -1,9 +1,10 @@ import type { ReactNode } from 'react'; -import { BarChart2, Loader2 } from 'lucide-react'; +import { BarChart2 } from 'lucide-react'; import { ResponsiveContainer } from 'recharts'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Spinner } from '@/components/ui/spinner'; export function ChartCard({ children, @@ -34,7 +35,10 @@ export function ChartCard({ className="flex items-center justify-center" style={{ height }} > - + ) : empty ? (
- +
} > diff --git a/frontend/src/components/shared/markdown-editor/markdown-editor.tsx b/frontend/src/components/shared/markdown-editor/markdown-editor.tsx index 857d4aa4..2ff3aba6 100644 --- a/frontend/src/components/shared/markdown-editor/markdown-editor.tsx +++ b/frontend/src/components/shared/markdown-editor/markdown-editor.tsx @@ -4,9 +4,9 @@ import type { AriaAttributes, Ref } from 'react'; import { history } from '@tiptap/pm/history'; import { EditorState, TextSelection } from '@tiptap/pm/state'; import { EditorContent, useEditor } from '@tiptap/react'; -import { Loader2 } from 'lucide-react'; import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; +import { Spinner } from '@/components/ui/spinner'; import { cn } from '@/lib/utils'; import { createMarkdownExtensions } from './markdown-editor-extensions'; @@ -121,7 +121,10 @@ function MarkdownEditor({ )} data-slot="markdown-editor" > - + ); } diff --git a/frontend/src/components/ui/sonner.tsx b/frontend/src/components/ui/sonner.tsx index 2023aa39..6a49145f 100644 --- a/frontend/src/components/ui/sonner.tsx +++ b/frontend/src/components/ui/sonner.tsx @@ -1,8 +1,9 @@ 'use client'; -import { CircleCheckIcon, InfoIcon, Loader2Icon, OctagonXIcon, TriangleAlertIcon } from 'lucide-react'; +import { CircleCheckIcon, InfoIcon, OctagonXIcon, TriangleAlertIcon } from 'lucide-react'; import { Toaster as Sonner, type ToasterProps } from 'sonner'; +import { Spinner } from '@/components/ui/spinner'; import { useTheme } from '@/hooks/use-theme'; function Toaster({ ...props }: ToasterProps) { @@ -14,7 +15,12 @@ function Toaster({ ...props }: ToasterProps) { icons={{ error: , info: , - loading: , + loading: ( + + ), success: , warning: , }} diff --git a/frontend/src/features/flows/dashboard/flow-dashboard-overview.tsx b/frontend/src/features/flows/dashboard/flow-dashboard-overview.tsx index 6bf3d18a..d9788a34 100644 --- a/frontend/src/features/flows/dashboard/flow-dashboard-overview.tsx +++ b/frontend/src/features/flows/dashboard/flow-dashboard-overview.tsx @@ -1,5 +1,5 @@ import { useQuery } from '@apollo/client/react'; -import { Activity, CircleDollarSign, Cpu, GitFork, Loader2 } from 'lucide-react'; +import { Activity, CircleDollarSign, Cpu, GitFork } from 'lucide-react'; import { useMemo } from 'react'; import type { UsageStatsFragmentFragment } from '@/graphql/types'; @@ -7,6 +7,7 @@ import type { UsageStatsFragmentFragment } from '@/graphql/types'; import { MetricCard } from '@/components/dashboard'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Spinner } from '@/components/ui/spinner'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import FlowAgentIcon from '@/features/flows/agents/flow-agent-icon'; import { @@ -304,7 +305,10 @@ export function FlowDashboardOverview({ flowId }: { flowId: string }) { function LoadingTable() { return (
- +
); } diff --git a/frontend/src/pages/dashboard/dashboard-analytics.tsx b/frontend/src/pages/dashboard/dashboard-analytics.tsx index 64ed6d19..56ea9762 100644 --- a/frontend/src/pages/dashboard/dashboard-analytics.tsx +++ b/frontend/src/pages/dashboard/dashboard-analytics.tsx @@ -1,6 +1,6 @@ import { useQuery } from '@apollo/client/react'; import { format } from 'date-fns'; -import { ChevronRight, Clock, Loader2, Wrench } from 'lucide-react'; +import { ChevronRight, Clock, Wrench } from 'lucide-react'; import { memo, useDeferredValue, useMemo, useRef, useState } from 'react'; import { Area, AreaChart, Bar, BarChart, CartesianGrid, Tooltip, XAxis, YAxis } from 'recharts'; @@ -11,6 +11,7 @@ import { FlowStatusBadge } from '@/components/icons/flow-status-badge'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; +import { Spinner } from '@/components/ui/spinner'; import { FlowsDocument, FlowsExecutionStatsByPeriodDocument, @@ -362,7 +363,10 @@ export function DashboardAnalytics({ period }: { period: UsageStatsPeriod }) { {executionStatsLoading ? (
- +
) : !deferredExecutionStats.length ? (

diff --git a/frontend/src/pages/dashboard/dashboard-overview.tsx b/frontend/src/pages/dashboard/dashboard-overview.tsx index af215e1c..6781f740 100644 --- a/frontend/src/pages/dashboard/dashboard-overview.tsx +++ b/frontend/src/pages/dashboard/dashboard-overview.tsx @@ -1,11 +1,12 @@ import { useQuery } from '@apollo/client/react'; -import { Activity, CircleDollarSign, Cpu, GitFork, Loader2 } from 'lucide-react'; +import { Activity, CircleDollarSign, Cpu, GitFork } from 'lucide-react'; import type { UsageStatsFragmentFragment } from '@/graphql/types'; import { MetricCard } from '@/components/dashboard'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Spinner } from '@/components/ui/spinner'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { FlowsStatsTotalDocument, @@ -165,7 +166,10 @@ export function DashboardOverview() { function LoadingTable() { return (

- +
); } diff --git a/frontend/src/pages/flows/flow.tsx b/frontend/src/pages/flows/flow.tsx index 1a889b2f..e6fac13a 100644 --- a/frontend/src/pages/flows/flow.tsx +++ b/frontend/src/pages/flows/flow.tsx @@ -9,7 +9,6 @@ import { ExternalLink, GitFork, GripVertical, - Loader2, NotepadText, Pause, PencilLine, @@ -376,7 +375,10 @@ function Flow() {
{isFlowLoading && (
- +
)} {isDesktop ? ( diff --git a/frontend/src/pages/flows/flows.tsx b/frontend/src/pages/flows/flows.tsx index ba00d0f7..1865bda9 100644 --- a/frontend/src/pages/flows/flows.tsx +++ b/frontend/src/pages/flows/flows.tsx @@ -1,7 +1,7 @@ import type { ColumnDef } from '@tanstack/react-table'; import { useMutation } from '@apollo/client/react'; -import { Ellipsis, Eye, GitFork, Loader2, Pause, Pencil, PencilLine, Plus, Star, Trash } from 'lucide-react'; +import { Ellipsis, Eye, GitFork, Pause, Pencil, PencilLine, Plus, Star, Trash } from 'lucide-react'; import { CheckCircle2, XCircle } from 'lucide-react'; import { useCallback, useMemo, useRef, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -593,7 +593,10 @@ function Flows() { - + Loading flows... Please wait while we fetch your conversation flows diff --git a/frontend/src/pages/knowledges/knowledges.tsx b/frontend/src/pages/knowledges/knowledges.tsx index 6e7d351e..f6d2f9ed 100644 --- a/frontend/src/pages/knowledges/knowledges.tsx +++ b/frontend/src/pages/knowledges/knowledges.tsx @@ -1,6 +1,6 @@ import type { ColumnDef } from '@tanstack/react-table'; -import { Ellipsis, LibraryBig, Loader2, Pencil, PencilLine, Plus, Trash } from 'lucide-react'; +import { Ellipsis, LibraryBig, Pencil, PencilLine, Plus, Trash } from 'lucide-react'; import { useCallback, useRef, useState } from 'react'; import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { toast } from 'sonner'; @@ -408,7 +408,10 @@ function Knowledges() { - + Loading knowledges... Please wait while we fetch your knowledge documents diff --git a/frontend/src/pages/login.tsx b/frontend/src/pages/login.tsx index 88029164..06dffbc2 100644 --- a/frontend/src/pages/login.tsx +++ b/frontend/src/pages/login.tsx @@ -1,7 +1,7 @@ -import { Loader2 } from 'lucide-react'; import { useLocation, useSearchParams } from 'react-router-dom'; import Logo from '@/components/icons/logo'; +import { Spinner } from '@/components/ui/spinner'; import LoginForm from '@/features/authentication/login-form'; import { routes } from '@/lib/routes'; import { getSafeReturnUrl } from '@/lib/utils/auth'; @@ -28,7 +28,10 @@ function Login() { returnUrl={returnUrl} /> ) : ( - + )}
diff --git a/frontend/src/pages/settings/settings-api-tokens.tsx b/frontend/src/pages/settings/settings-api-tokens.tsx index db78cfe5..a2ae53a9 100644 --- a/frontend/src/pages/settings/settings-api-tokens.tsx +++ b/frontend/src/pages/settings/settings-api-tokens.tsx @@ -11,7 +11,6 @@ import { Ellipsis, ExternalLink, Key, - Loader2, Pencil, Plus, Trash, @@ -872,7 +871,10 @@ function SettingsAPITokens() { - + Loading tokens... Please wait while we fetch your API tokens diff --git a/frontend/src/pages/settings/settings-prompt.tsx b/frontend/src/pages/settings/settings-prompt.tsx index ec1439d0..a839cc38 100644 --- a/frontend/src/pages/settings/settings-prompt.tsx +++ b/frontend/src/pages/settings/settings-prompt.tsx @@ -9,7 +9,6 @@ import { Ellipsis, FileDiff, FileText, - Loader2, RotateCcw, Save, User, @@ -734,7 +733,10 @@ function SettingsPrompt() { - + Loading prompt data... Please wait while we fetch prompt information diff --git a/frontend/src/pages/settings/settings-prompts.tsx b/frontend/src/pages/settings/settings-prompts.tsx index aafdf63b..e3e5c566 100644 --- a/frontend/src/pages/settings/settings-prompts.tsx +++ b/frontend/src/pages/settings/settings-prompts.tsx @@ -9,7 +9,6 @@ import { Code, Ellipsis, FileText, - Loader2, Pencil, RotateCcw, Settings, @@ -40,6 +39,7 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/empty'; +import { Spinner } from '@/components/ui/spinner'; import { DeletePromptDocument, SettingsPromptsDocument } from '@/graphql/types'; import { usePageStorageKeys } from '@/hooks/use-page-storage-keys'; import { routes } from '@/lib/routes'; @@ -414,7 +414,10 @@ function SettingsPrompts() { resetOperation?.promptName === agent.name && resetOperation?.type === 'system' ? ( <> - + Resetting... ) : ( @@ -438,7 +441,10 @@ function SettingsPrompts() { resetOperation?.promptName === agent.name && resetOperation?.type === 'human' ? ( <> - + Resetting... ) : ( @@ -462,7 +468,10 @@ function SettingsPrompts() { resetOperation?.promptName === agent.name && resetOperation?.type === 'all' ? ( <> - + Resetting... ) : ( @@ -565,7 +574,10 @@ function SettingsPrompts() { resetOperation?.promptName === tool.name && resetOperation?.type === 'tool' ? ( <> - + Resetting... ) : ( @@ -786,7 +798,10 @@ function SettingsPrompts() { - + Loading prompts... Please wait while we fetch your prompt templates diff --git a/frontend/src/pages/settings/settings-provider.tsx b/frontend/src/pages/settings/settings-provider.tsx index 6ae2344f..5914dd64 100644 --- a/frontend/src/pages/settings/settings-provider.tsx +++ b/frontend/src/pages/settings/settings-provider.tsx @@ -7,7 +7,6 @@ import { Clock, Ellipsis, Lightbulb, - Loader2, Play, Plug, Save, @@ -1564,7 +1563,10 @@ function SettingsProvider() { - + Loading provider data... Please wait while we fetch provider configuration diff --git a/frontend/src/pages/settings/settings-providers.tsx b/frontend/src/pages/settings/settings-providers.tsx index 10132f34..2ab49838 100644 --- a/frontend/src/pages/settings/settings-providers.tsx +++ b/frontend/src/pages/settings/settings-providers.tsx @@ -1,7 +1,7 @@ import type { ColumnDef, Row } from '@tanstack/react-table'; import { useMutation, useQuery } from '@apollo/client/react'; -import { AlertCircle, ChevronDown, Copy, Ellipsis, Loader2, Pencil, Plug, Plus, Settings, Trash } from 'lucide-react'; +import { AlertCircle, ChevronDown, Copy, Ellipsis, Pencil, Plug, Plus, Settings, Trash } from 'lucide-react'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; @@ -412,7 +412,10 @@ function SettingsProviders() { - + Loading providers... Please wait while we fetch your provider configurations