Getting Started
Scroll Animations
Text Animations
Hover & Cursor
Sliders & Carousels
Galleries & Grids
Menus & Navigation
Preloaders & Intros
Page Transitions
3D & WebGL
import { FluidPortraitHero } from "@/registry/tween/fluid-portrait-hero"
export function FluidPortraitHeroDemo() {
return <FluidPortraitHero />
}
import { FluidPortraitHero } from "@/components/ui/fluid-portrait-hero"<FluidPortraitHero
topImage="https://example.com/portrait-mono.jpg"
bottomImage="https://example.com/portrait-colour.jpg"
keyColor="#040d14"
brandLine1="KAGEMORI"
ghostWord="KAGEMORI"
/>A full-bleed orthographic plane is rendered through two shader passes. The first pass simulates a trail: each frame decays the previous frame by decay and adds intensity along the segment between the cursor’s last and current position, ping-ponging between two render targets so the trail accumulates and fades. The second pass samples that trail and uses it as a smoothstep mask to mix between the topImage (shown at rest) and the bottomImage (revealed wherever you have moved), with a cover-fit UV so each portrait fills the frame at any aspect. Pointer input is scoped to the hero element and the renderer is sized to it via a ResizeObserver, so it behaves inside the docs preview and at full screen. When prefers-reduced-motion: reduce is set, a single static frame of the top portrait is rendered with no simulation loop.
| Prop | Type | Default | Description |
|---|---|---|---|
topImage | string | monochrome portrait | Portrait shown at rest; the trail wipes it away. |
bottomImage | string | colour portrait | Portrait revealed wherever the cursor has moved. |
brandLine1 | React.ReactNode | "KAGEMORI" | First brand line (white). |
brandLine2 | React.ReactNode | "" | Optional second brand line (accent red); hidden when empty. |
brandMeta | React.ReactNode | "Colour Studio · K.26" | Small kicker under the brand. |
ringPhrases | string[] | default | Phrases that orbit the portrait on the curved ring. |
tapeText | React.ReactNode | "KAGEMORI" | Repeating text on the diagonal banner. |
ghostWord | string | "KAGEMORI" | Huge ghosted wordmark behind the figure (split on space). |
rightLabelTop | React.ReactNode | default | Rotated label on the right edge, upper. |
rightLabelBottom | React.ReactNode | default | Rotated label on the right edge, lower. |
sectionLabel | React.ReactNode | "Reel" | Active section label in the left rail. |
sideTabTitle | React.ReactNode | "K." | Title on the left edge tab. |
sideTabCaption | React.ReactNode | "Awards" | Caption on the left edge tab. |
background | string | "#05090d" | Surface color. |
accent | string | "#c8142c" | Accent red used across chrome and the reveal glow. |
keyColor | string | "#040d14" | Knock out a solid photo backdrop by color; "" disables it. |
keyThreshold | number | 0.08 | Color distance from keyColor that counts as background. |
keySoftness | number | 0.08 | Softness of the knockout edge. |
decay | number | 0.985 | Trail persistence per frame (0–1). |
lineWidth | number | 0.13 | Trail thickness in simulation UV space. |
className | string | — | Extra classes on the outer section. |