Balatro
balatroRenders a pixelated swirling multicolor oil-paint shader background.
Usage
Basic usage
Put it into the relative container and it will be filled. The three colors will be chart token adaptive light and dark by default.
Balatro
Spiral oil paint WebGL background
<div className="relative h-64 overflow-hidden rounded-xl"
style={{ background: "oklch(0.12 0.02 270)" }}>
<Balatro />
<div className="relative z-10">Content</div>
</div>Continuous rotation
isRotate lets the vortex continue to rotate over time, and spinSpeed controls the turbulence speed.
isRotate
<Balatro isRotate spinSpeed={4} />Retro Mosaic
Turn down pixelFilter to make the pixel blocks larger, creating a low-resolution mosaic texture.
pixelFilter = 120
<Balatro pixelFilter={120} contrast={4} />Custom color matching
color1/2/3 can transfer any CSS color to create exclusive oil paint vortex.
Warm orange oil paint
<Balatro
color1="oklch(0.72 0.2 40)"
color2="oklch(0.6 0.18 25)"
color3="oklch(0.18 0.04 30)"
spinSpeed={5}
lighting={0.6}
/>When to Use
Use it for a full-bleed backdrop with dense painted color and a swirling flow, such as a sign-in page, hero, or card background. Use DotPattern or GridPattern for regular geometry, and Spotlight for a lightweight single-color glow. Balatro is a GPU-heavy focal effect, not a small decorative accent.
Import
import { Balatro } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| spinRotation | number | -2.0 | Static vortex rotation when isRotate=false; the sign determines direction |
| spinSpeed | number | 7.0 | Internal paint-flow speed; higher values produce more vigorous motion |
| offset | [number, number] | [0, 0] | Vortex-center offset from the viewport midpoint as [x, y] |
| color1 | string | --color-chart-1 | Main color for the vortex's bright band; accepts any CSS color and defaults to a theme-aware token |
| color2 | string | --color-chart-2 | Secondary color for the middle of the vortex; accepts any CSS color |
| color3 | string | --color-chart-5 | Background color for shadows and gaps in the swirl; accepts any CSS color |
| contrast | number | 3.5 | Separation between the three colors; higher values create sharper boundaries |
| lighting | number | 0.4 | Highlight intensity on vortex peaks; 0 disables the additional highlights |
| spinAmount | number | 0.25 | Radial twist strength; higher values make the spiral tails more pronounced |
| pixelFilter | number | 745 | Pixelation factor; higher values produce smaller, finer pixels, while lower values create a coarser retro mosaic |
| spinEase | number | 1.0 | Rotation easing coefficient used to fine-tune the overall twist and speed |
| isRotate | boolean | false | Continuously rotate over time; when enabled, spinRotation influences rotation speed |
| mouseInteraction | boolean | true | Enable pointer interaction; disabling it makes the effect pointer-transparent |
| className | string | — | Additional class name for the root container or fallback div |
Slots
| Slot | Type | Description |
|---|---|---|
| fallback | ReactNode | Static non-WebGL content for reduced motion or unavailable WebGL; defaults to a conic-gradient swirl |
Usage Guidelines
- WebGL client rendering: the component depends on OGL and WebGL and must mount on the client. SSR renders the conic-gradient
fallback; do not import the realtime implementation directly at the top of a Next.js server-component tree. - Token colors require the `--color-` prefix: pass CSS variables such as
var(--color-chart-1). Bare names such asvar(--chart-1)do not resolve and can make the vortex render black. See [[hulian-token-color-var-needs-color-prefix]]. - Give the parent
position: relativeandoverflow: hiddenso the absolutely positioned effect fills the intended bounds without overflowing. - Continuous rotation and high
lightingvalues increase GPU cost. Avoid stacking multiple instances in long lists, especially on lower-end devices.
Related
DotPattern · GridPattern · StripedPattern · Spotlight · RetroGrid · Ripple
Playground
Balatro · Spiral oil paint background
<div className="relative h-64 overflow-hidden rounded-xl"
style={{ background: "oklch(0.12 0.02 270)" }}>
<Balatro
spinSpeed={7}
contrast={3.5}
lighting={0.4}
pixelFilter={745}
spinAmount={0.25}
isRotate={false}
mouseInteraction={true}
/>
<div className="relative z-10">Content</div>
</div>