Line Boil
A hand-drawn outline draws itself, boils on threes like a cel animation, and fills with color while it keeps boiling
$ pnpm dlx shadcn@latest add @remocn/line-boilUsage
LineBoil is a full-frame scene. It draws a closed outline with a pen that
tapers in and out and varies its pressure along the stroke, then fills the
shape with color. The line never sits still. Like a cel animation shot "on
threes", the whole drawing is retraced every few frames with a slightly
different wobble, cycling through a small set of drawings.
import { LineBoil } from "@/components/remocn/line-boil";
export const Star = () => <LineBoil />;Pass path to draw your own shape. It takes SVG path data in any coordinate
space. The outline is sampled at 160 points along its length, scaled so its
longer side is size of the frame's short side, and centered. Use one closed
outline: separate subpaths and holes are joined into one continuous stroke.
import { LineBoil } from "@/components/remocn/line-boil";
const heart =
"M 50 88 C 20 66 4 48 4 30 C 4 14 16 4 30 4 C 40 4 47 10 50 18 C 53 10 60 4 70 4 C 84 4 96 14 96 30 C 96 48 80 66 50 88 Z";
export const Heart = () => (
<LineBoil
path={heart}
line="#1C1A17"
fill="#FF8FB1"
background="#FFF6E9"
boilEvery={2}
/>
);The fill boils with its own seed and a stronger wobble than the line, so the color slips a little past the outline the way a cel fill does.
Timing
At 30 fps and speed={1}:
| Frames | Motion |
|---|---|
| 0–22 | The pen draws the outline along the path on an ease-in-out, with tapered ends |
| 28–40 | The fill grows from the shape's center with a small overshoot |
| 40+ | The finished drawing keeps boiling |
lineBoilLength is 40, the frame the fill lands. The boil runs from frame 0
and never stops: a new drawing every boilEvery frames, cycling through
drawings variations. speed scales the draw, the fill and the boil rate
together.
Props11
| Prop | Type | Default |
|---|---|---|
| path | string5-point star Closed outline as SVG path data in any coordinate space, fitted to the frame | |
| boilEvery | number3 Frames each drawing holds before the next one | |
| drawings | number3 Number of distinct drawings the boil cycles through | |
| amplitude | number1 Wobble strength; 1 is a gentle hand-drawn boil, 0 is a steady line | |
| strokeWidth | number9 Base line weight in px at 720p; pen pressure varies it along the stroke | |
| size | number0.66 Size of the shape's longer side as a fraction of the frame's short side | |
| line | string"#111111" Outline color. Overrides colors.line when set | |
| fill | string"#E5322D" Shape fill. Overrides colors.fill when set | |
| background | string"#FFFFFF" Background color. Overrides colors.background when set | |
| colors | { line?: string; fill?: string; background?: string }{ line: "#111111", fill: "#E5322D", background: "#FFFFFF" } The same colors as one object; the flat props above take precedence, missing keys keep their defaults | |
| speed | number1 Playback multiplier | |
- pathstring
Closed outline as SVG path data in any coordinate space, fitted to the frame
Default
5-point star - boilEverynumber
Frames each drawing holds before the next one
Default
3 - drawingsnumber
Number of distinct drawings the boil cycles through
Default
3 - amplitudenumber
Wobble strength; 1 is a gentle hand-drawn boil, 0 is a steady line
Default
1 - strokeWidthnumber
Base line weight in px at 720p; pen pressure varies it along the stroke
Default
9 - sizenumber
Size of the shape's longer side as a fraction of the frame's short side
Default
0.66 - linestring
Outline color. Overrides colors.line when set
Default
"#111111" - fillstring
Shape fill. Overrides colors.fill when set
Default
"#E5322D" - backgroundstring
Background color. Overrides colors.background when set
Default
"#FFFFFF" - colors{ line?: string; fill?: string; background?: string }
The same colors as one object; the flat props above take precedence, missing keys keep their defaults
Default
{ line: "#111111", fill: "#E5322D", background: "#FFFFFF" } - speednumber
Playback multiplier
Default
1