refactor(site): use standard Spinner in AgentsPage (#22811)

This commit is contained in:
Danielle Maywood
2026-03-09 15:50:36 +00:00
committed by GitHub
parent 5dfd563e4b
commit c6b68b2991
9 changed files with 38 additions and 31 deletions
@@ -112,9 +112,13 @@ export const LoadingSpinner: Story = {
const canvas = within(canvasElement);
const sendButton = canvas.getByRole("button", { name: "Send" });
expect(sendButton).toBeDisabled();
// The Loader2Icon renders with the animate-spin class when
// isLoading is true.
expect(sendButton.querySelector(".animate-spin")).toBeTruthy();
// The Spinner component renders an SVG with a "Loading spinner"
// title when isLoading is true.
const spinnerSvg = sendButton.querySelector("svg");
expect(spinnerSvg).toBeTruthy();
expect(spinnerSvg?.querySelector("title")?.textContent).toBe(
"Loading spinner",
);
},
};
+4 -6
View File
@@ -8,6 +8,7 @@ import {
ChatMessageInput,
type ChatMessageInputRef,
} from "components/ChatMessageInput/ChatMessageInput";
import { Spinner } from "components/Spinner/Spinner";
import {
Tooltip,
TooltipContent,
@@ -17,7 +18,6 @@ import {
AlertTriangleIcon,
ArrowUpIcon,
ImageIcon,
Loader2Icon,
Square,
XIcon,
} from "lucide-react";
@@ -274,7 +274,7 @@ export const AttachmentPreview = memo<{
)}
{uploadState?.status === "uploading" && (
<div className="absolute inset-0 flex items-center justify-center rounded-md bg-overlay">
<Loader2Icon className="h-5 w-5 animate-spin text-white" />
<Spinner className="h-5 w-5 text-white" loading />
</div>
)}
{uploadState?.status === "error" && (
@@ -565,9 +565,7 @@ export const AgentChatInput = memo<AgentChatInputProps>(
{isEditingHistoryMessage && editingQueuedMessageID === null && (
<div className="flex items-center justify-between border-b border-border-default/70 px-3 py-1.5">
<span className="flex items-center gap-1.5 text-sm text-content-secondary">
{isLoading && (
<Loader2Icon className="h-3.5 w-3.5 animate-spin" />
)}
{isLoading && <Spinner className="h-3.5 w-3.5" loading />}
{isLoading ? "Saving edit..." : "Editing message"}
</span>
<Button
@@ -672,7 +670,7 @@ export const AgentChatInput = memo<AgentChatInputProps>(
disabled={!canSend}
>
{isLoading ? (
<Loader2Icon className="animate-spin" />
<Spinner size="sm" loading aria-hidden="true" />
) : (
<ArrowUpIcon />
)}
@@ -8,7 +8,8 @@ import {
Tool,
} from "components/ai-elements";
import { FileIcon } from "components/FileIcon/FileIcon";
import { ChevronDownIcon, Loader2Icon } from "lucide-react";
import { Spinner } from "components/Spinner/Spinner";
import { ChevronDownIcon } from "lucide-react";
import {
type FC,
memo,
@@ -348,9 +349,10 @@ const ChatMessageItem = memo<{
{parsed.markdown || ""}
</span>
{isSavingMessage && (
<Loader2Icon
className="mt-0.5 h-3.5 w-3.5 shrink-0 animate-spin text-content-secondary"
<Spinner
className="mt-0.5 h-3.5 w-3.5 shrink-0 text-content-secondary"
aria-label="Saving message edit"
loading
/>
)}
</div>
+2 -1
View File
@@ -23,6 +23,7 @@ import { ExternalImage } from "components/ExternalImage/ExternalImage";
import { CoderIcon } from "components/Icons/CoderIcon";
import { ScrollArea } from "components/ScrollArea/ScrollArea";
import { Skeleton } from "components/Skeleton/Skeleton";
import { Spinner } from "components/Spinner/Spinner";
import { useAuthenticated } from "hooks";
import {
AlertTriangleIcon,
@@ -445,7 +446,7 @@ const ChatTreeNode = memo<ChatTreeNodeProps>(({ chat, isChildNode }) => {
</NavLink>
<div className="relative mr-1 mt-1 flex h-6 w-7 shrink-0 items-center justify-end">
{isArchivingThisChat ? (
<Loader2Icon className="h-3.5 w-3.5 animate-spin text-content-secondary" />
<Spinner className="h-3.5 w-3.5 text-content-secondary" loading />
) : (
<>
<span className="flex items-center justify-end text-xs text-content-secondary/50 tabular-nums [@media(hover:hover)]:group-hover:hidden group-has-[[data-state=open]]:hidden">
@@ -12,7 +12,7 @@ import {
import type * as TypesGen from "api/typesGenerated";
import { Alert, AlertDescription, AlertTitle } from "components/Alert/Alert";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Loader2Icon } from "lucide-react";
import { Spinner } from "components/Spinner/Spinner";
import { type FC, useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { cn } from "utils/cn";
@@ -301,7 +301,7 @@ export const ChatModelAdminPanel: FC<ChatModelAdminPanelProps> = ({
<div className={cn("flex min-h-full flex-col space-y-3", className)}>
{isLoading && (
<div className="flex items-center gap-1.5 text-xs text-content-secondary">
<Loader2Icon className="h-4 w-4 animate-spin" />
<Spinner className="h-4 w-4" loading />
Loading
</div>
)}
@@ -9,12 +9,12 @@ import {
SelectTrigger,
SelectValue,
} from "components/Select/Select";
import { Spinner } from "components/Spinner/Spinner";
import { useFormik } from "formik";
import {
ChevronDownIcon,
ChevronLeftIcon,
ChevronRightIcon,
Loader2Icon,
} from "lucide-react";
import { type FC, useMemo, useState } from "react";
import { cn } from "utils/cn";
@@ -487,10 +487,8 @@ export const ModelForm: FC<ModelFormProps> = ({
disabled={isDeleting}
onClick={() => void onDeleteModel(editingModel.id)}
>
{isDeleting && (
<Loader2Icon className="h-4 w-4 animate-spin" />
)}
Delete model
{isDeleting && <Spinner className="h-4 w-4" loading />}
Delete model{" "}
</Button>
</div>
</div>
@@ -522,7 +520,7 @@ export const ModelForm: FC<ModelFormProps> = ({
type="submit"
disabled={isSaving || !form.isValid || hasFieldErrors}
>
{isSaving && <Loader2Icon className="h-4 w-4 animate-spin" />}
{isSaving && <Spinner className="h-4 w-4" loading />}{" "}
{isEditing ? "Save" : "Add model"}{" "}
</Button>
</div>
@@ -2,12 +2,13 @@ import type * as TypesGen from "api/typesGenerated";
import { Alert, AlertDescription, AlertTitle } from "components/Alert/Alert";
import { Button } from "components/Button/Button";
import { Input } from "components/Input/Input";
import { Spinner } from "components/Spinner/Spinner";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { ChevronLeftIcon, InfoIcon, Loader2Icon } from "lucide-react";
import { ChevronLeftIcon, InfoIcon } from "lucide-react";
import { type FC, type FormEvent, useId, useState } from "react";
import { formatProviderLabel } from "../modelOptions";
import type { ProviderState } from "./ChatModelAdminPanel";
@@ -275,9 +276,9 @@ export const ProviderForm: FC<ProviderFormProps> = ({
onClick={() => void onDeleteProvider(providerConfig.id)}
>
{isProviderMutationPending && (
<Loader2Icon className="h-4 w-4 animate-spin" />
<Spinner className="h-4 w-4" loading />
)}
Delete provider
Delete provider{" "}
</Button>
</div>
</div>
@@ -299,9 +300,11 @@ export const ProviderForm: FC<ProviderFormProps> = ({
)}
<Button size="lg" type="submit" disabled={!canSave}>
{isProviderMutationPending && (
<Loader2Icon className="h-4 w-4 animate-spin" />
<Spinner className="h-4 w-4" loading />
)}
{providerConfig ? "Save changes" : "Create provider config"}
{providerConfig
? "Save changes"
: "Create provider config"}{" "}
</Button>
</div>
)}
@@ -1,5 +1,6 @@
import type { ChatQueuedMessage } from "api/typesGenerated";
import { Button } from "components/Button/Button";
import { Spinner } from "components/Spinner/Spinner";
import {
Tooltip,
TooltipContent,
@@ -8,7 +9,6 @@ import {
import {
ArrowUpIcon,
CornerDownLeftIcon,
Loader2Icon,
PencilIcon,
Trash2Icon,
} from "lucide-react";
@@ -288,7 +288,7 @@ export const QueuedMessagesList: FC<QueuedMessagesListProps> = ({
className="size-6 rounded text-content-secondary hover:bg-surface-tertiary hover:text-content-primary"
>
{isItemBusy && busyItem.action === "promote" ? (
<Loader2Icon className="h-3.5 w-3.5 animate-spin" />
<Spinner className="h-3.5 w-3.5" loading />
) : (
<ArrowUpIcon className="h-3.5 w-3.5" />
)}
@@ -307,7 +307,7 @@ export const QueuedMessagesList: FC<QueuedMessagesListProps> = ({
className="size-6 rounded text-content-secondary hover:bg-surface-tertiary hover:text-content-destructive"
>
{isItemBusy && busyItem.action === "delete" ? (
<Loader2Icon className="h-3.5 w-3.5 animate-spin" />
<Spinner className="h-3.5 w-3.5" loading />
) : (
<Trash2Icon className="h-3.5 w-3.5" />
)}
+3 -2
View File
@@ -1,12 +1,13 @@
import { getErrorMessage } from "api/errors";
import { Button } from "components/Button/Button";
import { Spinner } from "components/Spinner/Spinner";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import { useWebpushNotifications } from "contexts/useWebpushNotifications";
import { BellIcon, BellOffIcon, Loader2Icon } from "lucide-react";
import { BellIcon, BellOffIcon } from "lucide-react";
import type { FC } from "react";
import { toast } from "sonner";
@@ -51,7 +52,7 @@ export const WebPushButton: FC = () => {
className="h-7 w-7 text-content-secondary hover:text-content-primary"
>
{webPush.loading ? (
<Loader2Icon className="animate-spin" />
<Spinner size="sm" loading />
) : webPush.subscribed ? (
<BellIcon className="text-content-success" />
) : (