UI Components
The /components/ui directory contains shadcn/ui components and custom visual effects. These components provide the base layer for styling and animations used throughout the application.
Overview
shadcn/ui Radix UI-based accessible components with Tailwind styling
Custom Effects Animation and visual effect components
shadcn/ui Components
These components follow the shadcn/ui pattern: copy-paste components built on Radix UI primitives with Tailwind CSS.
Accordion
Collapsible content sections with smooth animations.
Subcomponents:
Accordion - Root container
AccordionItem - Individual collapsible item
AccordionTrigger - Clickable header
AccordionContent - Collapsible content area
Usage:
components/ui/accordion.tsx
import {
Accordion ,
AccordionContent ,
AccordionItem ,
AccordionTrigger ,
} from '@/components/ui/accordion'
< Accordion type = "single" collapsible >
< AccordionItem value = "item-1" >
< AccordionTrigger > What is NJ Rajat Mahotsav? </ AccordionTrigger >
< AccordionContent >
A grand celebration organized by Shree Swaminarayan Temple Secaucus
commemorating 25 years of spiritual service.
</ AccordionContent >
</ AccordionItem >
< AccordionItem value = "item-2" >
< AccordionTrigger > When is the event? </ AccordionTrigger >
< AccordionContent >
July 29 - August 2, 2026
</ AccordionContent >
</ AccordionItem >
< AccordionItem value = "item-3" >
< AccordionTrigger > How do I register? </ AccordionTrigger >
< AccordionContent >
Visit the registration page and fill out the form with your details.
</ AccordionContent >
</ AccordionItem >
</ Accordion >
Features:
Animated chevron icon rotation
Smooth expand/collapse transitions
Single or multiple items open
Keyboard navigation support
ARIA attributes for accessibility
Props:
// Accordion
type : "single" | "multiple"
collapsible ?: boolean // For single type
defaultValue ?: string // Initial open item(s)
// AccordionItem
value : string // Unique identifier
disabled ?: boolean
// AccordionTrigger & AccordionContent
className ?: string
Versatile button component with multiple variants - also available in /components/atoms.
Usage:
import { Button } from '@/components/ui/button'
< Button variant = "default" size = "default" >
Click Me
</ Button >
< Button variant = "destructive" size = "lg" >
Delete
</ Button >
< Button variant = "outline" size = "sm" >
Cancel
</ Button >
< Button variant = "ghost" size = "icon" >
< Icon />
</ Button >
Variants:
default - Primary button with solid background
destructive - Red button for dangerous actions
outline - Button with border, no fill
secondary - Secondary button style
ghost - Transparent button with hover effect
link - Text link style
Sizes:
default - h-10 px-4 py-2
sm - h-9 px-3
lg - h-11 px-8
icon - h-10 w-10 (square)
Custom Effect Components
These components provide advanced visual effects and animations.
InfiniteSlider
Infinite scrolling content slider with configurable direction and speed.
Props Interface:
components/ui/infinite-slider.tsx
type InfiniteSliderProps = {
children : React . ReactNode
gap ?: number // Default: 16px
duration ?: number // Default: 25s
durationOnHover ?: number // Optional hover speed
direction ?: 'horizontal' | 'vertical' // Default: 'horizontal'
reverse ?: boolean // Default: false
className ?: string
}
Usage:
import { InfiniteSlider } from '@/components/ui/infinite-slider'
< InfiniteSlider
gap = { 24 }
duration = { 30 }
durationOnHover = { 60 }
direction = "horizontal"
className = "my-8"
>
{ logos . map (( logo , index ) => (
< div key = { index } className = "flex-shrink-0" >
< img src = { logo . src } alt = { logo . alt } className = "h-12" />
</ div >
)) }
</ InfiniteSlider >
Features:
Infinite loop animation
Horizontal or vertical scrolling
Reversible direction
Hover to slow down (optional)
Content duplication for seamless loop
Uses Framer Motion for smooth animations
Implementation Details:
components/ui/infinite-slider.tsx
const translation = useMotionValue ( 0 )
const [ ref , { width , height }] = useMeasure ()
useEffect (() => {
const size = direction === 'horizontal' ? width : height
const contentSize = size + gap
const from = reverse ? - contentSize / 2 : 0
const to = reverse ? 0 : - contentSize / 2
const controls = animate ( translation , [ from , to ], {
ease: 'linear' ,
duration: currentDuration ,
repeat: Infinity ,
repeatType: 'loop'
})
return controls ?. stop
}, [ width , height , gap , currentDuration ])
FloatingParticles
Animated floating particle background effect.
Props Interface:
components/ui/floating-particles.tsx
interface FloatingParticlesProps {
count ?: number // Default: 50
speed ?: number // Default: 1
particleSize ?: number // Default: 4
className ?: string
colors ?: string [] // Default: ['#fff']
}
Usage:
import { FloatingParticles } from '@/components/ui/floating-particles'
< div className = "relative h-screen" >
< FloatingParticles
count = { 100 }
speed = { 0.5 }
particleSize = { 6 }
colors = { [ '#FFD700' , '#FFA500' , '#FF6347' ] }
/>
< div className = "relative z-10" >
{ /* Content above particles */ }
</ div >
</ div >
Features:
Random particle positioning
Floating animation with varying speeds
Customizable colors and sizes
Performance-optimized rendering
Non-interactive background layer
GradientMeshBackground
Animated gradient mesh background with smooth color transitions.
Props Interface:
components/ui/gradient-mesh-background.tsx
interface GradientMeshBackgroundProps {
colors ?: string [] // Default: preset colors
speed ?: number // Default: 20s
className ?: string
children ?: React . ReactNode
}
Usage:
import { GradientMeshBackground } from '@/components/ui/gradient-mesh-background'
< GradientMeshBackground
colors = { [
'#0D132D' , // Navy
'#B50000' , // Red
'#FFD700' , // Gold
'#FF6347' // Orange
] }
speed = { 15 }
className = "min-h-screen"
>
< div className = "relative z-10 container mx-auto" >
{ /* Page content */ }
</ div >
</ GradientMeshBackground >
Features:
Smooth animated gradients
Multiple color stops
CSS-based animation (no JS overhead)
Works as container or background
Customizable animation speed
ImageGridBackground
Mosaic-style image grid background with parallax effect.
Props Interface:
components/ui/image-grid-background.tsx
interface ImageGridBackgroundProps {
images : string [] // Array of image URLs
columns ?: number // Default: 6
gap ?: number // Default: 4
opacity ?: number // Default: 0.3
parallax ?: boolean // Default: true
className ?: string
}
Usage:
import { ImageGridBackground } from '@/components/ui/image-grid-background'
const backgroundImages = [
'/gallery/event1.jpg' ,
'/gallery/event2.jpg' ,
'/gallery/event3.jpg' ,
// ... more images
]
< ImageGridBackground
images = { backgroundImages }
columns = { 8 }
gap = { 2 }
opacity = { 0.2 }
parallax = { true }
className = "fixed inset-0 z-0"
/>
Features:
Responsive grid layout
Parallax scroll effect
Adjustable opacity
Random image distribution
Optimized for large image arrays
LightRaysEffect
Divine light rays emanating from center.
Props Interface:
components/ui/light-rays-effect.tsx
interface LightRaysEffectProps {
rayCount ?: number // Default: 12
color ?: string // Default: '#FFD700'
opacity ?: number // Default: 0.1
duration ?: number // Default: 30s
className ?: string
}
Usage:
import { LightRaysEffect } from '@/components/ui/light-rays-effect'
< div className = "relative h-screen bg-gradient-to-b from-blue-900 to-purple-900" >
< LightRaysEffect
rayCount = { 16 }
color = "#FFD700"
opacity = { 0.15 }
duration = { 40 }
/>
< div className = "relative z-10" >
{ /* Content */ }
</ div >
</ div >
Features:
Radial gradient rays
Rotating animation
Customizable ray count and color
Blend mode effects
Fixed positioning for backgrounds
shadcn/ui Registries
The project includes custom registries for specialized components:
Background Paths
Animated SVG background paths.
Location: /components/ui/shadcn-io/background-paths/
Usage:
import { BackgroundPaths } from '@/components/ui/shadcn-io/background-paths'
< BackgroundPaths className = "opacity-20" />
Dropzone
File upload dropzone component.
Location: /components/ui/shadcn-io/dropzone/
Usage:
import { Dropzone } from '@/components/ui/shadcn-io/dropzone'
< Dropzone
onDrop = { handleFiles }
accept = { { 'image/*' : [ '.png' , '.jpg' , '.jpeg' ] } }
maxSize = { 5 * 1024 * 1024 } // 5MB
>
< div className = "text-center" >
< p > Drag & drop images here </ p >
< p className = "text-sm text-gray-500" > or click to browse </ p >
</ div >
</ Dropzone >
Integration with Component Libraries
The project supports additional component registries:
MagicUI
Registry: https://magicui.design
Specialized animation and effect components.
Aceternity UI
Registry: https://ui.aceternity.com
Modern UI components with advanced effects (e.g., 3D Pin used in molecules).
Skiper UI
Registry: https://skiper-ui.com
Additional utility components.
Installation:
# Example: Add a component from MagicUI
npx shadcn-ui@latest add https://magicui.design/r/animated-beam
Styling Conventions
Tailwind CSS v4
All UI components use Tailwind CSS v4 with custom configuration:
@import "tailwindcss" ;
/* Custom color palette */
:root {
--preset-deep-navy : #0D132D ;
--preset-navy-accent : #1E1F3C ;
--preset-zodiac-blue : #0F2847 ;
--preset-red : #B50000 ;
--preset-light-gray : #EEF0F2 ;
--preset-stone : #F1EFE8 ;
--preset-pale-gray : #F8F8F0 ;
--preset-bluish-gray : #E0E7EF ;
}
/* Custom spacing */
:root {
--page-header-spacing : 4 rem ;
--page-title-description-spacing : 1.5 rem ;
--page-bottom-spacing : 4 rem ;
}
Class Variance Authority (CVA)
Button and other variant-based components use CVA:
import { cva , type VariantProps } from "class-variance-authority"
const buttonVariants = cva (
"base-classes" ,
{
variants: {
variant: {
default: "bg-primary text-primary-foreground" ,
destructive: "bg-destructive text-white" ,
// ...
},
size: {
default: "h-10 px-4" ,
sm: "h-9 px-3" ,
// ...
}
},
defaultVariants: {
variant: "default" ,
size: "default"
}
}
)
Utility Function
Class name merging utility:
import { clsx , type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn ( ... inputs : ClassValue []) {
return twMerge ( clsx ( inputs ))
}
Usage:
import { cn } from '@/lib/utils'
< div className = { cn (
"base-classes" ,
isActive && "active-classes" ,
className // Allow prop override
) } >
{ /* Content */ }
</ div >
Animation Patterns
Framer Motion Integration
Many UI components use Framer Motion for animations:
import { motion , AnimatePresence } from 'framer-motion'
< AnimatePresence mode = "wait" >
< motion.div
initial = { { opacity: 0 , y: 20 } }
animate = { { opacity: 1 , y: 0 } }
exit = { { opacity: 0 , y: - 20 } }
transition = { { duration: 0.3 } }
>
{ content }
</ motion.div >
</ AnimatePresence >
CSS Animations
Tailwind animation utilities:
< div className = "animate-spin" >
< LoaderIcon />
</ div >
< div className = "animate-pulse" >
Loading...
</ div >
< div className = "animate-bounce" >
< ArrowDown />
</ div >
Custom Keyframes
export default {
theme : {
extend: {
keyframes: {
'accordion-down' : {
from: { height: '0' },
to: { height : 'var(--radix-accordion-content-height)' }
},
' accordion-up ': {
from : { height: 'var(--radix-accordion-content-height)' },
to: { height : '0' }
}
},
animation: {
' accordion-down ': 'accordion-down 0.2s ease-out' ,
'accordion-up' : 'accordion-up 0.2s ease-out'
}
}
}
}
Accessibility
All UI components follow accessibility best practices:
Tab navigation support
Enter/Space for activation
Arrow keys for lists/dropdowns
Escape to close modals/dropdowns
aria-label for icon buttons
aria-expanded for collapsible content
aria-hidden for decorative elements
role attributes for semantic meaning
Visible focus indicators
Focus trap in modals
Restore focus on close
Skip links for navigation
Semantic HTML elements
Descriptive labels
Live region announcements
Alternative text for images
Best Practices
When using UI components:
Always import from the correct path (@/components/ui)
Use the cn() utility for class name merging
Maintain accessibility attributes
Follow the shadcn/ui update pattern
Test animations for performance
Provide fallbacks for effects
Use semantic HTML elements
Component Updates
To update shadcn/ui components:
# Update a specific component
npx shadcn-ui@latest add button
# Update all components
npx shadcn-ui@latest add --all --overwrite
The /components/ui directory is maintained separately to allow easy updates from shadcn/ui without affecting custom components.
Next Steps
Atoms See how atoms use these UI primitives
Overview Return to component architecture overview