A scroll-triggered wavy text animation component that creates flowing motion effects.
pnpm dlx shadcn@latest add @gammaui/wavy-text-block
import { WavyBlock, WavyBlockItem } from "@/components/gammaui/wavy-block"
export default function Example() {
return (
<WavyBlock className="space-y-4">
<WavyBlockItem index={0}>
<h2>First Line</h2>
</WavyBlockItem>
<WavyBlockItem index={1}>
<h2>Second Line</h2>
</WavyBlockItem>
<WavyBlockItem index={2}>
<h2>Third Line</h2>
</WavyBlockItem>
</WavyBlock>
)
}The container component that provides scroll context to child items.
| Prop | Type | Default | Description |
|---|---|---|---|
| offset | [string, string] | ['start end', 'end start'] | Scroll offset range for animation trigger |
| ...props | HTMLDivElement props | - | All standard div props are supported |
Individual animated items within the WavyBlock.
| Prop | Type | Default | Description |
|---|---|---|---|
| index | number | - | Required. Index for wave phase calculation |
| config | WavyTextsConfig | See below | Configuration object for wave animation |
| style | React.CSSProperties | - | Additional inline styles |
| ...props | motion.div props | - | All Framer Motion div props are supported |
The config prop accepts a WavyTextsConfig object with the following properties:
interface WavyTextsConfig {
baseOffsetFactor: number // Base horizontal offset multiplier (default: 0.1)
baseExtra: number // Additional base offset (default: 0)
baseAmplitude: number // Wave amplitude (default: 160)
lengthEffect: number // Text length impact on amplitude (default: 0.6)
frequency: number // Wave frequency (default: 35)
progressScale: number // Scroll progress multiplier (default: 6)
phaseShiftDeg: number // Phase shift in degrees (default: -180)
spring: SpringOptions // Spring animation config
}const defaultConfig = {
baseOffsetFactor: 0.1,
baseExtra: 0,
baseAmplitude: 160,
lengthEffect: 0.6,
frequency: 35,
progressScale: 6,
phaseShiftDeg: -180,
spring: { damping: 22, stiffness: 300 },
}<WavyBlock className="space-y-4">
<WavyBlockItem
index={0}
config={{
baseOffsetFactor: 0.15,
baseAmplitude: 200,
frequency: 45,
progressScale: 8,
phaseShiftDeg: -90,
spring: { damping: 30, stiffness: 400 },
}}
>
<h2>Custom Wave</h2>
</WavyBlockItem>
</WavyBlock><WavyBlock className="space-y-6" offset={["start center", "end center"]}>
{["Create", "Amazing", "Animations"].map((text, i) => (
<WavyBlockItem key={i} index={i}>
<h1 className="text-6xl font-bold">{text}</h1>
</WavyBlockItem>
))}
</WavyBlock>frequency to control spacing between wave peaksbaseAmplitude to increase or decrease horizontal movementphaseShiftDeg to shift the wave pattern left or rightoffset prop to control when the animation starts and ends during scroll