Components / Shiny Wrap
Shiny Wrap
A simple shimmering highlight wrapper that adds a moving light streak over any content. Great for featured cards, album covers, or hero images.
Preview
The shine effect animates across the cards in a loop. You can also enable hover-only mode.



Usage
tsx
import ShinyWrapper from "@/components/shiny-wrap/shiny-wrapper"
export function Example() {
return (
<div className="flex gap-4">
<ShinyWrapper className="rounded-xl">
<figure className="h-[320px] w-[220px] overflow-hidden rounded-xl">
<img
src="/images/photo1.jpg"
alt="Shiny wrapper"
className="w-full h-full object-cover"
/>
</figure>
</ShinyWrapper>
</div>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | required | Content to wrap with the shine effect |
| animationSpeed | number | 1500 | Duration of the shine animation in milliseconds |
| loop | boolean | true | Whether the shine animation should loop |
| loopDelay | number | 200 | Delay between shine loops (ms) when looping |
| hoverOnly | boolean | false | Only animate when hovered |
| shinyStyle | 'gradient' | 'solid' | 'gradient' | Style of the shine bar (gradient vs solid) |
| shinyWidth | string | '30%' | Width of the shine bar (CSS value) |
| className | string | "" | Additional classes for the wrapper |
Source Code
tsx
'use client'
import { useState, ReactNode } from 'react'
interface ShinyWrapperProps {
children: ReactNode
animationSpeed?: number
loop?: boolean
loopDelay?: number
hoverOnly?: boolean
shinyStyle?: 'gradient' | 'solid'
className?: string
shinyWidth?: string
}
const ShinyWrapper = ({
children,
animationSpeed = 1500,
loop = true,
loopDelay = 200,
hoverOnly = false,
shinyStyle = 'gradient',
className = '',
shinyWidth = '30%'
}: ShinyWrapperProps) => {
const [isHovered, setIsHovered] = useState(false)
const totalDuration = loop ? animationSpeed + loopDelay : animationSpeed
const shouldAnimate = hoverOnly ? isHovered : true
const animationStyle = {
animation: shouldAnimate
? `shine ${totalDuration}ms linear ${loop ? 'infinite' : '1'}`
: 'none'
}
const shinyClass = {
gradient: 'bg-gradient-to-r from-transparent via-white/10 to-transparent',
solid: 'bg-white/10'
}
return (
<div
className={`relative overflow-hidden ${className}`}
onMouseEnter={hoverOnly ? () => setIsHovered(true) : undefined}
onMouseLeave={hoverOnly ? () => setIsHovered(false) : undefined}
>
<div
className={`absolute z-1 top-0 -left-1/2 h-full -skew-x-14 ${shinyClass[shinyStyle]}`}
style={{ ...animationStyle, width: shinyWidth }}
/>
<div className='relative'>{children}</div>
</div>
)
}
export default ShinyWrapper