Text Build
snap-cn/text-buildFreeComponent
Words enter one at a time while already-placed words physically reflow to stay centered — a growing line on the x axis or a growing stack on the y axis.
Install it
npx shadcn@latest add https://snapcn.dev/r/text-build.jsonSource
1"use client";23import { useEffect, useMemo, useState } from "react";4import { Easing, interpolate, useCurrentFrame } from "remotion";5import { type SnapCnTheme, useSnapCnTheme } from "@/lib/snap-cn-ui";67export type TextBuildAxis = "x" | "y";89export interface TextBuildProps {10 text: string;11 /** Build direction: "x" pushes the line sideways, "y" stacks rows. */12 axis?: TextBuildAxis;13 /** Distance a new word travels in from (px). Defaults: 88 on x, 28 on y. */14 entryOffset?: number;15 /** Space between words (px on x) or between rows (px on y, default 12). */16 gap?: number;17 /** Frames the first word takes to settle. */18 firstDuration?: number;19 /** Frames each subsequent enter/push/reflow step takes. */20 pushDuration?: number;21 /** Scale a word enters at before settling to 1. */22 entryScale?: number;23 /** Blur (px) a word enters with. Defaults: 3.5 on x, 2.4 on y. */24 entryBlur?: number;25 /** Peak blur (px) on already-placed words while they reflow. */26 reflowBlur?: number;27 /** Cubic-bezier easing for every move. */28 easing?: [number, number, number, number];29 fontSize?: number;30 /** Overrides the design system's `foreground`. */31 color?: string;32 fontWeight?: number;33 speed?: number;34 className?: string;35 /** Design-system token overrides. */36 theme?: Partial<SnapCnTheme>;37 mode?: "light" | "dark";38}3940const FONT_FAMILY =41 "var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif";4243const MEASURE_FONT =44 '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';4546/** Per-axis defaults harvested from the two legacy looks. */47const AXIS_DEFAULTS: Record<48 TextBuildAxis,49 {50 entryOffset: number;51 gap: number;52 entryBlur: number;53 /** Subtle drift the very first word settles from, on the cross axis (x)54 * or the primary axis (y). */55 firstDrift: number;56 }57> = {58 x: { entryOffset: 88, gap: 10, entryBlur: 3.5, firstDrift: 6 },59 y: { entryOffset: 28, gap: 12, entryBlur: 2.4, firstDrift: -14 },60};6162/**63 * Size of each word along the build axis. On "x" this is the measured text64 * width (canvas measureText, with a `length * fontSize * 0.55` SSR fallback);65 * on "y" every row is one `fontSize` tall.66 */67function fallbackWordSizes(68 words: string[],69 axis: TextBuildAxis,70 fontSize: number,71): number[] {72 if (axis === "y") return words.map(() => fontSize);73 return words.map((w) => w.length * fontSize * 0.55);74}7576export function measureWordSizes(77 words: string[],78// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from snap-cn
All 24 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Answer Streamanswer-stream | snap-cn | Components | Free | 2 deps | |
| UI Caretcaret | snap-cn | Components | Free | 1 dep | |
| Follower Rushfollower-rush | snap-cn | Components | Free | 2 deps | |
| Product Herohero-launch | snap-cn | Components | Free | 2 deps | |
| UI Inputinput | snap-cn | Components | Free | 2 deps · 2 files | |
| Karaoke Captionskaraoke-captions | snap-cn | Components | Free | 2 deps | |
| Laptop Framelaptop-frame | snap-cn | Components | Free | 1 dep | |
| Logo Assemblelogo-assemble | snap-cn | Components | Free | 1 dep |
