Docs
Particle Background

Particle Background

A dynamic background with animated particles that adapts to light and dark themes

"Are we the prey? No, we are the hunters... of bugs in our code!"

- Eren Yeager, debugging the Titan problem

Installation

Copy and paste the following code into your project.

"use client"
 
import React, { useEffect, useRef } from "react"
import { useTheme } from "next-themes"
 
interface Particle {
  x: number
  y: number
  vx: number
  vy: number
  radius: number
  color: string
}
 
interface ParticleBackgroundProps {
  particleCount?: number
  lightModeColors?: string[]
  darkModeColors?: string[]
}
 
const ParticleBackground: React.FC<ParticleBackgroundProps> = ({
  particleCount = 100,
  lightModeColors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFA07A", "#98D8C8"],
  darkModeColors = ["#FFD700", "#FF69B4", "#00CED1", "#FF6347", "#32CD32"],
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const particlesRef = useRef<Particle[]>([])
  const { theme } = useTheme()
 
  useEffect(() => {
    const canvas = canvasRef.current
    if (!canvas) return
 
    const ctx = canvas.getContext("2d")
    if (!ctx) return
 
    const createParticles = () => {
      const particles: Particle[] = []
      const colors = theme === "dark" ? darkModeColors : lightModeColors
      for (let i = 0; i < particleCount; i++) {
        particles.push({
          x: Math.random() * canvas.width,
          y: Math.random() * canvas.height,
          vx: (Math.random() - 0.5) * 0.2,
          vy: (Math.random() - 0.5) * 0.2,
          radius: Math.random() * 2 + 1,
          color: colors[Math.floor(Math.random() * colors.length)],
        })
      }
      return particles
    }
 
    particlesRef.current = createParticles()
 
    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height)
 
      particlesRef.current.forEach((particle) => {
        particle.x += particle.vx
        particle.y += particle.vy
 
        if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1
        if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1
 
        ctx.beginPath()
        ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2)
        ctx.fillStyle = particle.color
        ctx.fill()
      })
 
      requestAnimationFrame(animate)
    }
 
    animate()
 
    const handleResize = () => {
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight
      particlesRef.current = createParticles()
    }
 
    handleResize()
    window.addEventListener("resize", handleResize)
 
    return () => {
      window.removeEventListener("resize", handleResize)
    }
  }, [particleCount, lightModeColors, darkModeColors, theme])
 
  return (
    <canvas
      ref={canvasRef}
      className="absolute inset-0 w-full h-full"
      style={{ mixBlendMode: theme === "dark" ? "screen" : "multiply" }}
    />
  )
}
 
export ParticleBackground

Update the import paths to match your project setup.

Usage

import ParticleBackground from "@/components/ui/particle-background"
export default function ParticleBackgroundDemo() {
  return (
    <ParticleBackground />
      {/* Your content goes here */}
      <h1>Glass UI</h1>
  )
}

Props

The ParticleBackground component accepts the following props:

  • children (React.ReactNode): The content to be displayed on top of the particle background.
  • particleCount (number, optional): The number of particles to render. Default is 100.
  • lightModeColors (string[], optional): An array of colors for particles in light mode. Default is ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFA07A", "#98D8C8"].
  • darkModeColors (string[], optional): An array of colors for particles in dark mode. Default is ["#FFD700", "#FF69B4", "#00CED1", "#FF6347", "#32CD32"].

Customization

You can customize the appearance of the Particle Background by adjusting the props:

<ParticleBackground 
  particleCount={150}
  lightModeColors={["#FF0000", "#00FF00", "#0000FF"]}
  darkModeColors={["#800000", "#008000", "#000080"]}
/>
  {/* Your content */}

This example increases the particle count to 150 and uses custom colors for light and dark modes.