Skip to main content
Glama
spinner.tsx3.38 kB
import type { SVGProps } from 'react'; import { cn } from '../../utils/cn'; /** * Props for the Spinner component */ type SpinnerProps = SVGProps<SVGSVGElement> & { /** Stroke width for the spinner animation circles. Defaults to 4 */ strokeWidth?: number; }; /** * Spinner Component * * An animated SVG spinner that displays two expanding and fading circles * to indicate loading or processing states. Uses smooth CSS animations * with spline curves for natural motion. * * @component * @example * Basic usage: * ```tsx * <Spinner /> * ``` * * @example * Custom stroke width: * ```tsx * <Spinner strokeWidth={6} className="text-blue-500" /> * ``` * * @example * Custom size: * ```tsx * <Spinner className="size-8 text-red-500" strokeWidth={2} /> * ``` * * Features: * - Smooth expanding circle animation * - Customizable stroke width * - Inherits text color from parent (currentColor) * - Responsive sizing through className * - Infinite loop animation * - Two-phase animation with offset timing * - Optimized SVG with minimal DOM impact * * Animation Details: * - Duration: 1.8 seconds per cycle * - Two circles with 0.9s offset * - Radius expands from 1 to 20 * - Opacity fades from 1 to 0 * - Spline easing for natural motion * * @param props - SVG props with custom spinner options * @param props.className - CSS classes for styling and sizing * @param props.strokeWidth - Line thickness for the animated circles * @param props.color - SVG color (use className with text-color for easier styling) * @param props.width - SVG width (defaults to 44, use className for responsive sizing) * @param props.height - SVG height (defaults to 44, use className for responsive sizing) * @param props...rest - All other standard SVG element attributes * * @returns An animated SVG spinner element */ export const Spinner = ({ className, strokeWidth = 4 }: SpinnerProps) => ( <svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 44 44" stroke="currentColor" role="img" aria-label="Spinner" className={cn('size-full', className)} > <g fill="none" fillRule="evenodd" strokeWidth={strokeWidth}> <circle cx="22" cy="22" r="1"> <animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /> <animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /> </circle> <circle cx="22" cy="22" r="1"> <animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite" /> <animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite" /> </circle> </g> </svg> );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aymericzip/intlayer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server