Bauhaus Build
Flat shapes tumble corner over corner into a Bauhaus frieze, then rebuild around an open band that hands off to a title
$ pnpm dlx shadcn@latest add @remocn/bauhaus-buildUsage
BauhausBuild assembles an abstract Bauhaus poster from nine flat pieces: a
large circle, two quarter circles, a semicircle, two squares, two bars and a
small circle. They arrive one at a time on a six-frame beat and build a frieze
across the middle of an invisible square grid. After a short hold the frieze
splits. Every piece makes one more quarter turn, and together they settle
above and below an empty center band. That band is the handoff field for your
title.
Pieces never slide or fade into place. Each one travels by tumbling over its corners like a hinged tile. It makes a chain of quarter turns, each about the grid corner on its leading edge, and rolls cell by cell until it lands exactly in its slot. A new piece unfolds out of its first hinge point, which can lie outside the poster, so some pieces roll in from the margins. The last quarter turn overshoots by 4.5° and settles back.
The component draws no background, text, or fonts. Put a Backdrop in the
paper color behind it, with no padding, so the grid centers on the whole
frame.
import { Backdrop } from "@/components/remocn/backdrop";
import { BauhausBuild } from "@/components/remocn/bauhaus-build";
export const Opener = () => (
<Backdrop
fill={{ type: "color", value: "#f1eee7" }}
padding={0}
radius={0}
shadow=""
>
<BauhausBuild />
</Backdrop>
);Title handoff
getBauhausBuildField returns the open band in composition pixels. The band
spans the full frame width and the middle third of the poster, and it stays
vertically centered at every aspect ratio. Pass it the same scale as the
component. The band is clear from bauhausBuildTimeline.clear (frame 116 at
30 fps) and stays clear while the handoff holds.
import { Sequence, useVideoConfig } from "remotion";
import { Backdrop } from "@/components/remocn/backdrop";
import {
BauhausBuild,
bauhausBuildTimeline,
getBauhausBuildField,
} from "@/components/remocn/bauhaus-build";
export const Opener = () => {
const { width, height } = useVideoConfig();
const field = getBauhausBuildField({ width, height });
return (
<Backdrop
fill={{ type: "color", value: "#f1eee7" }}
padding={0}
radius={0}
shadow=""
>
<BauhausBuild />
<Sequence from={bauhausBuildTimeline.clear}>
<div
style={{
position: "absolute",
left: field.x,
top: field.y,
width: field.width,
height: field.height,
display: "flex",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
color: "#1c1a17",
fontFamily: "Helvetica, Arial, sans-serif",
fontSize: field.unit * 1.25,
fontWeight: 700,
lineHeight: 1.1,
}}
>
Form follows function
</div>
</Sequence>
</Backdrop>
);
};Timing
At 30 fps and speed={1}:
| Frames | Motion |
|---|---|
| 0–22 | The first pieces unfold out of grid points and start tumbling toward their slots |
| 22–75 | Nine landings, one every six frames, each with a 4.5° overshoot that settles |
| 75–90 | Hold on the frieze |
| 90–125 | The frieze splits in a three-frame cascade. Paired pieces swing apart about shared corners, and the bars tip into rules above and below the band |
| 125–150 | Hold on the handoff. The band has been clear since frame 116 |
bauhausBuildLengthis 125, the frame where the last piece settles.getBauhausBuildDuration({ speed, loop })returns the preview length, including the final hold: 150 frames atspeed={1}, or 300 withloop.- At another speed or frame rate, divide these frames by
speedand multiply byfps / 30. loopplays the whole sequence forward, then backward. The pieces tumble back out and fold into their hinge points, so the cycle repeats without a cut. Played backward, each landing overshoot becomes a small anticipation.
Palette and variants
Each piece has a color role. The default is one warm accent and three neutrals on a paper backdrop. Set the roles to red, yellow and blue for the classic Bauhaus look:
<Backdrop
fill={{ type: "color", value: "#efe9dc" }}
padding={0}
radius={0}
shadow=""
>
<BauhausBuild
inkColor="#161616"
accentColor="#d7362b"
secondaryColor="#f2b930"
tertiaryColor="#1f4f9e"
/>
</Backdrop>seedmirrors the composition: 1 is the authored layout, 2 mirrors it horizontally, 3 vertically, 4 both ways, and then the cycle repeats. Every seed also reshuffles the arrival order. The band stays in the middle for every seed, sogetBauhausBuildFielddoes not need one.scalesets the size of the square poster. At 1 it fills 80% of the shorter side, and the range is 0.5–1.25. The composition keeps its proportions at 16:9, 1:1 and 9:16.getBauhausBuildState(time, options)returns every piece's pose in grid modules (position, rotation, hinge and scale), the poster'soriginX,originYandunitin pixels, and the seed'sflipXandflipY, so other layers can follow the same grid.timecounts frames at 30 fps andspeed={1}.
| Prop | Type | Default | Description |
|---|---|---|---|
scale | number | 1 | Poster size; 1 fills 80% of the shorter side, clamped to 0.5–1.25 |
seed | number | 1 | Mirror variant, cycling every four seeds, and arrival order |
inkColor | string | "#1c1a17" | Large quarter circle, pillar bar and small circle |
accentColor | string | "#e4572e" | Large circle and small square |
secondaryColor | string | "#cbbc9f" | Semicircle and small quarter circle |
tertiaryColor | string | "#7e776b" | Post bar and square block |
speed | number | 1 | Playback multiplier; 0 freezes the empty first frame |
loop | boolean | false | Plays the sequence forward and back so it repeats seamlessly every 300 frames |
className | string | — | Optional class name on the full-frame root |