Velocity UI
Loading…
Menu

Loader

Loader component with smooth animations and modern UI.

Installation

Add this component to your project using the CLI:

terminal
npx vui-registry-cli-v1 add loader

Source Code

loader.tsx
'use client'

import React from 'react'
import { motion } from 'framer-motion'
import { cn } from '@/lib/utils'

export interface LoaderProps extends React.HTMLAttributes<HTMLDivElement> {
  /**
   * Additional CSS classes to apply to the loader
   */
  className?: string
  /**
   * Size of the loader
   */
  size?: 'sm' | 'md' | 'lg'
  /**
   * Color of the loader
   */
  color?: string
}

/**
 * Base Loader Component
 *
 * A foundational loader component that serves as the base for all loader variants.
 * This component provides a simple spinning loader with consistent styling.
 *
 * @example
 * ```tsx
 * <Loader />
 * <Loader size="lg" />
 * <Loader className="text-blue-500" />
 * ```
 */
export const Loader = React.forwardRef<HTMLDivElement, LoaderProps>(
  ({ className, size = 'md', color, ...props }, ref) => {
    const sizeClasses = {
      sm: 'w-4 h-4 border-2',
      md: 'w-8 h-8 border-2',
      lg: 'w-12 h-12 border-3',
    }

    return (
      <div
        ref={ref}
        className={cn('inline-flex items-center justify-center', className)}
        {...props}
      >
        <motion.div
          className={cn(
            'rounded-full border-solid border-t-transparent',
            sizeClasses[size],
            color || 'border-current',
          )}
          animate={{ rotate: 360 }}
          transition={{
            duration: 1,
            repeat: Infinity,
            ease: 'linear',
          }}
        />
      </div>
    )
  },
)

Loader.displayName = 'Loader'

// Demo Component
export default function LoaderDemo() {
  return (
    <div className="flex flex-col items-center justify-center min-h-[400px] w-full bg-white dark:bg-zinc-950 p-8">
      <div className="w-full max-w-md space-y-8">
        <div className="text-center space-y-2 mb-8">
          <h2 className="text-2xl font-bold tracking-tight">Base Loader Component</h2>
          <p className="text-zinc-500 text-sm">Foundation for all loader variants</p>
        </div>

        <div className="space-y-8">
          <div className="space-y-4">
            <h3 className="text-sm font-medium">Sizes</h3>
            <div className="flex items-center gap-8 justify-center">
              <div className="flex flex-col items-center gap-2">
                <Loader size="sm" />
                <span className="text-xs text-zinc-500">Small</span>
              </div>
              <div className="flex flex-col items-center gap-2">
                <Loader size="md" />
                <span className="text-xs text-zinc-500">Medium</span>
              </div>
              <div className="flex flex-col items-center gap-2">
                <Loader size="lg" />
                <span className="text-xs text-zinc-500">Large</span>
              </div>
            </div>
          </div>

          <div className="space-y-4">
            <h3 className="text-sm font-medium">Colors</h3>
            <div className="flex items-center gap-8 justify-center">
              <div className="flex flex-col items-center gap-2">
                <Loader className="text-blue-500" />
                <span className="text-xs text-zinc-500">Blue</span>
              </div>
              <div className="flex flex-col items-center gap-2">
                <Loader className="text-green-500" />
                <span className="text-xs text-zinc-500">Green</span>
              </div>
              <div className="flex flex-col items-center gap-2">
                <Loader className="text-red-500" />
                <span className="text-xs text-zinc-500">Red</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}