snapcn
23 components
DocsComponentsTemplatesVideo EditorShowcaseMarketplaceRoadmapChangelog

Getting started

IntroductionInstallationAgent skill
GitHub

Star snapcn

Free, open-source components.

Production-ready Remotion animations, transitions and backgrounds — you own the code.

Star on GitHubXFollow

MIT licensed · own your code.

© 2026 snapcn

DocsComponentsTemplatesVideo EditorShowcaseMarketplaceRoadmapChangelog
Getting startedIntroductionInstallationAgent skill

Block Wordmark

A wordmark that builds itself out of solid blocks — a deck shuffles, collapses, splits one block per letter, and each block flashes and cuts to its real letterform

Installation

pnpm
$ pnpm dlx shadcn@latest add @snapcn/block-wordmark

Component code

The exact file shadcn add copies into your project.

Usage

A wordmark build in six beats:

  1. Seed — a single rounded square scales up off the baseline (growDuration).
  2. Shuffle — coloured cards fan out from behind it and wind back in, one full turn each about a shared pivot on the baseline. The fan is one S-curve sampled at cardStagger offsets, so it opens and closes exactly once (cards, spinTurns, spinDuration, liftRatio).
  3. Collapse — the deck lands back on the seed square and dips once, which is the only frame in the piece where the ink is a single block.
  4. Split — the square stretches horizontally and splits into one block per letter, outermost blocks leading and the inner ones lagging by splitStagger. Any letter whose ink rises above the x-height grows a tab on the correct side — the "b" of base sprouts a left stem, a "d" a right one, an "A" an apex.
  5. Hold — the block row sits and scales up slowly for holdDuration frames. This is the beat that reads as a logo rather than as an animation.
  6. Resolve — each block flashes a colour from colors, returns to ink, and is hard-cut to its letterform flashToSwap frames later. The first letter goes last, so the word finishes where it started.

Nothing crossfades and nothing morphs. At each swap frame the block is already within a few pixels of the settled letter, so the cut is invisible — and a spring or a crossfade "to improve it" is the one change that breaks the effect.

// src/Root.tsx
import { Composition } from "remotion";
import { BlockWordmark } from "@/components/snap-cn/block-wordmark";

const Sting = () => (
  <BlockWordmark text="snapcn" color="#0000FF" fontSize={160} />
);

export const RemotionRoot = () => (
  <Composition
    id="BlockWordmark"
    component={Sting}
    durationInFrames={150}
    fps={30}
    width={1280}
    height={720}
  />
);

Any word, not just this one

Nothing about the geometry is hardcoded to a four-letter lowercase word. Every glyph's advance width, x-height and ink top are measured at runtime behind delayRender(), so the blocks are sized to the letters they become and the ascender tabs are found by measurement rather than a letter list. Emoji survive (the text is split by code point) and spaces get a gap, not a block.

Two knobs decide how literal the morph is:

  • blockSizing="square" (default) makes every block a square the height of the x-height, so the row reads as an even rhythm and each block visibly changes into its letter.
  • blockSizing="glyph" sizes each block to its letter's advance width, which makes the resolve nearly in-place.

Long words outrun the 150-frame default: the last letter resolves at roughly 94 + flashStagger × letters. Drop flashStagger to 2 or raise durationInFrames.

Colour

The deck and the flash colours are a prop with our defaults — the first card follows your primary token, the rest are a decorative set.

The ink defaults to your foreground, so an installed copy paints in whatever palette it lands in. The preview above passes color="#0000FF" because that is snapcn's own mark; yours is one prop away.

A full brand look — ink, deck, and a display face's heavier ascender — is one line. base rather than snapcn here because the ascender props only show on a word that has one:

<BlockWordmark
  text="base"
  color="#0000FF"
  colors="#ABF25B,#FA361A,#FCCA28,#337DFE,#F99BCA"
  ascenderRatio={0.4}
  ascenderStemRatio={0.415}
/>

ascenderRatio and ascenderStemRatio are the two places a display face differs most from Inter: leave them out and they are measured per glyph, set them and you get the chunky flag a geometric sans draws.

Props

PropTypeDefaultDescription
text
string"base"The word to build. Split by code point, so emoji stay whole; spaces get a gap, not a block
fontSize
number160Size the finished wordmark is set at, in px
fontFamily
stringInterLoaded through @remotion/google-fonts, so the Player and the render agree
fontWeight
number | string700Weight of the finished letterforms and of the probe they are measured from
color
stringtheme.foregroundThe wordmark's ink, and the colour of the lead card in the deck
colors
string[] | stringtheme.primary + four accentsThe deck's cards and the flash colours, in order. Accepts an array or a comma-separated string
background
stringtheme.backgroundStage behind the build
blockGap
number0.093Gap between blocks, as a fraction of a block's side
cornerRadius
number0.07Corner radius of a block, as a fraction of its side
ascenderRatio
numbermeasuredTab height ÷ block height. Omitted, it is measured per glyph — how far that letter actually rises above the x-height
ascenderStemRatio
numbermeasuredTab width ÷ block width. Omitted, measured too: the stem of a "b", the whole width of a "B"
blockSizing
"square" | "glyph""square"Uniform squares (an even rhythm), or each block sized to the letter it becomes (a near in-place morph)
maxWidth
number0.92Fraction of the frame width the row may occupy before it is scaled to fit
cards
number6Cards in the deck, including the lead one
cardStagger
number2Frames between one card's turn starting and the next card's
spinTurns
number1Full turns the deck makes while it fans and winds back in
liftRatio
number0.665How far the deck lifts off the baseline as it fans, as a fraction of a block's side
growDuration
number9Frames the first square takes to scale in
spinDuration
number33Frames the deck's turn lasts
splitDuration
number5Frames a block takes to travel from the collapsed square to its slot
splitStagger
number1Frames the inner blocks lag the outer ones by — the split runs outside-in
ascenderDuration
number12Frames an ascender's tab takes to grow
holdDuration
number54Frames the finished block row holds before the letters resolve
flashStagger
number4Frames between one letter's flash and the next. Lower it for long words
flashDuration
number3Frames a block stays lit in its flash colour
flashToSwap
number5Frames from a block lighting up to it being hard-cut to its letterform
speed
number1Global playback multiplier applied to the whole sequence
className
string—Optional className passed to the outer wrapper
theme
Partial<SnapCnTheme>—Design-system token overrides. Anything you leave out falls back to the shadcn defaults
mode
"light" | "dark"—Which end of the design system to resolve tokens against