From fb30bb3dcd3eac2206317896236d2f1e718086fc Mon Sep 17 00:00:00 2001 From: Vasco Singh Date: Tue, 5 Aug 2025 00:00:25 -0400 Subject: [PATCH 1/2] New loader --- src/components/ui/loader.tsx | 132 ++++++++++++++++++ src/styles/globals.css | 19 +++ .../toolkits/image/tools/generate/client.tsx | 15 +- .../toolkits/video/tools/generate/client.tsx | 15 +- 4 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 src/components/ui/loader.tsx diff --git a/src/components/ui/loader.tsx b/src/components/ui/loader.tsx new file mode 100644 index 00000000..15144b3d --- /dev/null +++ b/src/components/ui/loader.tsx @@ -0,0 +1,132 @@ +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const loaderVariants = cva( + "inline-block animate-spin rounded-full border-2 border-solid border-current border-r-transparent motion-reduce:animate-[spin_1.5s_linear_infinite]", + { + variants: { + size: { + sm: "h-4 w-4", + default: "h-6 w-6", + lg: "h-8 w-8", + xl: "h-12 w-12", + }, + }, + defaultVariants: { + size: "default", + }, + }, +); + +const wrenchLoaderVariants = cva( + "inline-block motion-reduce:animate-[wrench-spin_2s_ease-in-out_infinite]", + { + variants: { + size: { + sm: "h-4 w-4", + default: "h-6 w-6", + lg: "h-8 w-8", + xl: "h-12 w-12", + }, + }, + defaultVariants: { + size: "default", + }, + }, +); + +interface LoaderProps + extends React.HTMLAttributes, + VariantProps { + text?: string; + variant?: "spinner" | "wrench"; +} + +function Loader({ className, size, text, variant = "spinner", ...props }: LoaderProps) { + const WrenchIcon = () => ( + + {/* Wrench - moved down and left to get into bolt */} + + + + + {/* Hex bolt - moved up and right more and made 5% smaller */} + + {/* Regular hexagon (radius 40) */} + + + + {/* Circular hole */} + + + + + + ); + + return ( +
+ {variant === "wrench" ? ( + + ) : ( +
+ )} + {text && ( + {text} + )} +
+ ); +} + +export { Loader, loaderVariants }; \ No newline at end of file diff --git a/src/styles/globals.css b/src/styles/globals.css index 9cf9b70f..f7707b06 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -119,6 +119,25 @@ transform: translateZ(0) rotate(360deg); } } + @keyframes wrench-spin { + 9% { + transform: translateX(0) translateY(0) rotate(0deg); + } + 13% { + transform: translateX(0) translateY(0) rotate(0deg); + } + 25% { + transform: translateX(-15px) translateY(0) rotate(120deg); + } + 28% { + transform: translateX(-15px) translateY(0) rotate(120deg); + } + 79% { + transform: translateX(0) translateY(0) rotate(0deg); + } + } + + --animate-shiny-text: shiny-text 8s infinite; @keyframes shiny-text { 0%, diff --git a/src/toolkits/toolkits/image/tools/generate/client.tsx b/src/toolkits/toolkits/image/tools/generate/client.tsx index 7325a6b5..af7c37af 100644 --- a/src/toolkits/toolkits/image/tools/generate/client.tsx +++ b/src/toolkits/toolkits/image/tools/generate/client.tsx @@ -2,6 +2,7 @@ import React from "react"; import Image from "next/image"; +import { Loader } from "@/components/ui/loader"; import type { baseGenerateTool } from "./base"; import type { ClientToolConfig } from "@/toolkits/types"; @@ -10,8 +11,18 @@ export const generateToolConfigClient: ClientToolConfig< typeof baseGenerateTool.inputSchema.shape, typeof baseGenerateTool.outputSchema.shape > = { - CallComponent: ({ args }) => { - return {args.prompt}; + CallComponent: ({ args, isPartial }) => { + return ( +
+ + + Generating your image... + + + "{args.prompt}" + +
+ ); }, ResultComponent: ({ result }) => { return ( diff --git a/src/toolkits/toolkits/video/tools/generate/client.tsx b/src/toolkits/toolkits/video/tools/generate/client.tsx index 9c9bcf1c..1be9e0ee 100644 --- a/src/toolkits/toolkits/video/tools/generate/client.tsx +++ b/src/toolkits/toolkits/video/tools/generate/client.tsx @@ -1,5 +1,6 @@ import React from "react"; +import { Loader } from "@/components/ui/loader"; import type { baseGenerateTool } from "./base"; import type { ClientToolConfig } from "@/toolkits/types"; @@ -8,8 +9,18 @@ export const generateToolConfigClient: ClientToolConfig< typeof baseGenerateTool.inputSchema.shape, typeof baseGenerateTool.outputSchema.shape > = { - CallComponent: ({ args }) => { - return {args.prompt}; + CallComponent: ({ args, isPartial }) => { + return ( +
+ + + Generating your video... + + + "{args.prompt}" + +
+ ); }, ResultComponent: ({ result }) => { return
); } -export { Loader, loaderVariants }; \ No newline at end of file +export { Loader, loaderVariants }; diff --git a/src/toolkits/toolkits/image/tools/generate/client.tsx b/src/toolkits/toolkits/image/tools/generate/client.tsx index af7c37af..6e23d0a6 100644 --- a/src/toolkits/toolkits/image/tools/generate/client.tsx +++ b/src/toolkits/toolkits/image/tools/generate/client.tsx @@ -15,10 +15,10 @@ export const generateToolConfigClient: ClientToolConfig< return (
- + Generating your image... - + "{args.prompt}"
diff --git a/src/toolkits/toolkits/video/tools/generate/client.tsx b/src/toolkits/toolkits/video/tools/generate/client.tsx index 1be9e0ee..e77474c1 100644 --- a/src/toolkits/toolkits/video/tools/generate/client.tsx +++ b/src/toolkits/toolkits/video/tools/generate/client.tsx @@ -13,10 +13,10 @@ export const generateToolConfigClient: ClientToolConfig< return (
- + Generating your video... - + "{args.prompt}"