New Loading Spinner Component #1694
Replies: 14 comments 27 replies
-
Agreed, this seems to be something missing! |
Beta Was this translation helpful? Give feedback.
-
Agreed! |
Beta Was this translation helpful? Give feedback.
-
export const LoadingSpinner = ({className}) => {
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={cn("animate-spin", className)}
>
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
</svg>
} |
Beta Was this translation helpful? Give feedback.
-
@benjick is shared a good example. I improved a bit and add type-safety and flexibility. export interface ISVGProps extends React.SVGProps<SVGSVGElement> {
size?: number;
className?: string;
}
export const LoadingSpinner = ({
size = 24,
className,
...props
}: ISVGProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
{...props}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className={cn("animate-spin", className)}
>
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
</svg>
);
}; |
Beta Was this translation helpful? Give feedback.
-
how can i use this loadingspinner |
Beta Was this translation helpful? Give feedback.
-
take a look at lucide-react package. it is as simple as: import { LoaderIcon } from "lucide-react"
<LoaderIcon className="animate-spin" /> |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
created it here |
Beta Was this translation helpful? Give feedback.
-
To anybody who came here for the common loading spinner, you see on a lot of websites, here it is:
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
const spinnerVariants =
"w-16 h-16 border-4 border-t-4 border-gray-200 border-t-gray-600 rounded-full animate-spin";
const LoadingSpinner = React.forwardRef((props, ref) => {
const { className, ...rest } = props;
return <div ref={ref} className={cn(spinnerVariants, className)} {...rest} />;
});
LoadingSpinner.displayName = "LoadingSpinner";
export { LoadingSpinner }; The code is consistent with the other Shadcn UI components.
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
const spinnerVariants =
"w-16 h-16 border-4 border-t-4 border-gray-200 border-t-gray-600 rounded-full animate-spin";
interface LoadingSpinnerProps extends React.HTMLAttributes<HTMLDivElement> {
className?: string;
}
const LoadingSpinner = React.forwardRef<HTMLDivElement, LoadingSpinnerProps>((props, ref) => {
const { className, ...rest } = props;
return <div ref={ref} className={cn(spinnerVariants, className)} {...rest} />;
});
LoadingSpinner.displayName = "LoadingSpinner";
export { LoadingSpinner }; You can use it anywhere in your app like this: <LoadingSpinner /> |
Beta Was this translation helpful? Give feedback.
-
And here goes the variant that works and combines lucide icons with Shadcn code conventions: import * as React from "react";
import { cn } from "@/lib/utils";
import { LoaderIcon } from "lucide-react";
const spinnerVariants = "w-16 h-16 rounded-full animate-spin";
interface LoadingSpinnerProps extends React.HTMLAttributes<SVGSVGElement> {
className?: string;
}
const LoadingSpinner = React.forwardRef<SVGSVGElement, LoadingSpinnerProps>(
(props, ref) => {
const { className, ...rest } = props;
return (
<LoaderIcon
ref={ref}
className={cn(spinnerVariants, className)}
{...rest}
/>
);
},
);
LoadingSpinner.displayName = "LoadingSpinner";
export { LoadingSpinner }; |
Beta Was this translation helpful? Give feedback.
-
Based on @mazewinther code published here.
'use client'
import * as React from 'react'
import { cn } from '@/lib/utils'
// Define the spinner styles as a constant for better readability and maintainability
const spinnerStyles = 'border-4 border-t-4 rounded-full animate-spin'
// Define the default colors for the spinner
const defaultSpinnerColors = {
border: 'gray-200',
borderTop: 'gray-900',
size: 'w-16 h-16',
}
interface LoadingSpinnerProps extends React.HTMLAttributes<HTMLDivElement> {
className?: string
borderColor?: string
borderTopColor?: string
size?: number | string
}
/**
* A simple loading spinner component.
*
* @param props - The props for the component.
* @returns The loading spinner element.
*/
const LoadingSpinner = React.forwardRef<HTMLDivElement, LoadingSpinnerProps>(
(props, ref) => {
const { className, borderColor, borderTopColor, size, ...rest } = props
const borderStyle = cn(
`${spinnerStyles} border-${borderColor || defaultSpinnerColors.border} border-t-${
borderTopColor || defaultSpinnerColors.borderTop
}`,
)
const sizeStyle = size ? `h-${size} w-${size}` : defaultSpinnerColors.size
return (
<div className={cn(sizeStyle, className)} ref={ref} {...rest}>
<div className={cn(borderStyle, sizeStyle)} />
</div>
)
},
)
LoadingSpinner.displayName = 'LoadingSpinner'
export { LoadingSpinner } You can use it anywhere in your app like this: <LoadingSpinner borderColor="gray-200" borderTopColor="gray-600" size={4}/> |
Beta Was this translation helpful? Give feedback.
-
I like using the combo tailwind + vector icons with Usage: <Spinner className="w-4 h-4 mr-2" type="circle-bars" />
<Spinner className="w-4 h-4 mr-2" type="shaft-long-rounded" />
<Spinner className="w-4 h-4 mr-2" type="shaft-short-rounded" /> |
Beta Was this translation helpful? Give feedback.
-
I've created one similar to the example shared by @henriemategui in the initial discussion. ![]() ![]() components/spinner.tsx/**
* A loading spinner component that supports multiple variants and sizes.
* @example
* ```tsx
* <Spinner variant="primary" size="lg" />
* <Spinner size={32} />
* ```
*/
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const spinnerVariants = cva(
'relative inline-block aspect-square transform-gpu',
{
variants: {
variant: {
default: '[&>div]:bg-foreground',
primary: '[&>div]:bg-primary',
secondary: '[&>div]:bg-secondary',
destructive: '[&>div]:bg-destructive',
muted: '[&>div]:bg-muted-foreground',
},
size: {
sm: 'size-4',
default: 'size-5',
lg: 'size-8',
},
},
defaultVariants: { variant: 'default', size: 'default' },
},
);
export interface SpinnerProps
extends React.HTMLAttributes<HTMLDivElement>,
Omit<VariantProps<typeof spinnerVariants>, 'size'> {
className?: string;
size?: VariantProps<typeof spinnerVariants>['size'] | number;
}
const Spinner = ({ className, variant, size = 'default' }: SpinnerProps) => (
<div
role="status"
aria-label="Loading"
className={cn(
typeof size === 'string'
? spinnerVariants({ variant, size })
: spinnerVariants({ variant }),
className,
)}
style={typeof size === 'number' ? { width: size, height: size } : undefined}
>
{Array.from({ length: 12 }).map((_, i) => (
<div
key={i}
className="animate-spinner absolute left-[46.5%] top-[4.4%] h-[24%] w-[7%]
origin-[center_190%] rounded-full opacity-[0.1] will-change-transform"
style={{
transform: `rotate(${i * 30}deg)`,
animationDelay: `${(i * 0.083).toFixed(3)}s`,
}}
aria-hidden="true"
/>
))}
<span className="sr-only">Loading...</span>
</div>
);
export { Spinner, spinnerVariants }; globals.css (For Tailwind CSS 4.0 or newer)@theme {
--animate-spinner: spinner 1s linear infinite;
@keyframes spinner {
0% {
opacity: 1;
}
10% {
opacity: 0.7;
}
20% {
opacity: 0.3;
}
35% {
opacity: 0.2;
}
50% {
opacity: 0.1;
}
75% {
opacity: 0.05;
}
100% {
opacity: 0;
}
}
} tailwind.config.ts (For previous version of Tailwind CSS)module.exports = {
extend: {
animation: {
spinner: 'spinner 1s linear infinite',
},
keyframes: {
spinner: {
'0%': { opacity: '1' },
'10%': { opacity: '0.7' },
'20%': { opacity: '0.3' },
'35%': { opacity: '0.2' },
'50%': { opacity: '0.1' },
'75%': { opacity: '0.05' },
'100%': { opacity: '0' },
},
},
},
} Usage<Spinner variant="primary" size="lg" /> or <Spinner size={32} /> |
Beta Was this translation helpful? Give feedback.
-
I'm looking to have spinner with messages like we have in AI chatbots... e.g when we submit a query, we got few messeges under Model's message bubble like: How can we achieve that in react? i'm new to React. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
A component that indicates interface loading would be interesting, I know Skeleton already exists, but that's not what I'm talking about. It's something like a spinner.
I know this isn't a big deal and it doesn't take much work for me to do myself, but I like shadcn/ui's design patterns and I would love it to have that.
An example:
Beta Was this translation helpful? Give feedback.
All reactions