snapcn
32 components
DocsComponentsTemplatesVideo EditorNewShowcaseMarketplaceRoadmapChangelog

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

Loading
snapcn
32 components
DocsComponentsTemplatesVideo EditorNewShowcaseMarketplaceRoadmapChangelog

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 EditorNewShowcaseMarketplaceRoadmapChangelog
Getting startedIntroductionInstallationAgent skill

Answer Highlight

A question, an answer that writes itself, and then a selection dragged across the one sentence that matters — and settled onto one word inside it

Installation

pnpm
$ pnpm dlx shadcn@latest add @snapcn/answer-highlight

Needs an existing Remotion project and a components.json. Two-minute setup if this is your first snapcn component.

Component code

The exact file shadcn add copies into your project.

Usage

Four beats. The question lands in a pill. The answer writes itself a word at a time. A caret appears mid-sentence and a selection band drags across one statement, wrapping onto the next line the way a real one does. Then the band settles onto one word inside it, and that word takes the accent.

The point of the shot is the third beat. The typing is the setup — it is what makes the highlight land on something the viewer has just read rather than on a paragraph that was always there.

// src/Root.tsx
import { Composition } from "remotion";
import { AnswerHighlight } from "@/components/snap-cn/answer-highlight";

const Ask = () => (
  <AnswerHighlight
    question="How should we structure the demo video?"
    answer="Build one composition per scene and keep the timeline declarative, so the same props always render the same frames."
    statement="keep the timeline declarative"
    word="declarative"
  />
);

export const RemotionRoot = () => (
  <Composition
    id="AnswerHighlight"
    component={Ask}
    durationInFrames={190}
    fps={30}
    width={1280}
    height={720}
  />
);

You name the sentence, not its coordinates

statement and word are strings, matched against the answer — not indices, not offsets, not a markup syntax inside the copy. Edit the answer and the highlight follows it; edit it so far that the sentence is gone and nothing highlights, which is the signal that the two have drifted apart rather than a band drawn over the wrong words.

Punctuation does not have to line up. statement="keep the timeline declarative" finds the answer's declarative, — writing the comma into the prop to make the match land is the kind of thing nobody remembers and everybody debugs twice. word only counts if it falls inside statement; the same word appearing earlier in the answer is not the one you meant.

The band is a background, not a rectangle

Every word of the answer is its own inline span, and the selection is a background on the spans the drag has passed. That is the whole trick, and it is what buys:

  • Real wrapping. A selection that runs over a line break breaks square at the line end and picks up at the start of the next one — because the browser is doing the wrapping, not a measured rectangle trying to imitate it.
  • No DOM measurement. No refs, no delayRender, no getBoundingClientRect that reports device pixels and has to be divided back out by the current scale. Put any copy you like in it.

The word gap is padding, not margin, so the band is drawn behind the spaces too — otherwise a selection over four words comes out as four chips with holes where the spaces were.

Why the drag has a caret

Because a selection without one is a highlight animating in, and a highlight animating in reads as decoration. The leading edge is drawn as a hard stop inside a gradient, with a sliver of the accent just past it — one background doing the band, its edge, and the caret at once. The stop moves through the word it is crossing rather than jumping over it: at 30fps a per-word step advances three whole words a second and the whole thing turns into four chips appearing in sequence.

dragStep is seconds per word, default 0.11 — four words in a little under half a second, which is what a hand actually does.

The selection is a tint, never the accent

accentColor at 16% over the page for the statement, 30% for the picked word, and the picked word's ink mixed toward the accent. Primary at full strength behind body type puts white-on-blue in the middle of a paragraph and the line stops being readable — which is exactly why a browser's own selection is pale until the window loses focus.

The tint is composited as alpha, not mixOklch. Mixing the warm off-white page toward a blue in oklch takes the short way round the hue wheel and passes through green: the first cut of this scene highlighted the answer in pale mint.

Proportions

The question pill is the one measured object here — its height, radius, padding and entrance are the numbers Agent Steps carries, fitted off the same recording. Everything below it is chosen for this scene, and the constants in the file say what each one is for.

value
answer type0.0385 of frame height
answer measure0.6 of frame width — three or four lines of a real answer
line height1.64, looser than a paragraph wants, so the band on one line does not sit against the type on the next
band inset0.18em above and below the type
caret0.06em wide

Props

PropTypeDefaultDescription
question
string"How should we structure the demo video?"The prompt, in the pill at the top
answer
string—The answer. It writes itself a word at a time; line breaks are the browser's, so write a paragraph and let the measure set the rag
statement
string"keep the timeline declarative"The run inside answer that gets selected. Matched word for word, ignoring outer punctuation; a run that is not found simply never highlights
word
string"declarative"The one word inside statement that takes the second, stronger band and the accent ink. Ignored if it falls outside the statement
questionHold
number0.6Seconds the question holds alone before the answer starts
wordStep
number0.055Seconds between two words of the answer arriving. Each word takes 0.22s to land, so four or five are always mid-arrival — which is what stops it looking like a ticker
beforeDrag
number0.45Seconds between the answer finishing and the drag starting
dragStep
number0.11Seconds the drag spends on each word of the statement. The edge moves through a word, not over it
beforeWord
number0.6Seconds the selected statement holds before the word is picked out
paperColor
string—Page behind the scene. Defaults to theme.background
pillColor
string—Question pill fill. Defaults to theme.card
questionColor
string—Question ink. Defaults to theme.mutedForeground
answerColor
string—Answer ink. Defaults to theme.foreground
accentColor
string—The selection, the caret and the picked word. Defaults to theme.primary
centerY
number0.5Where the lockup sits, as a fraction of frame height
fontFamily
string—Overrides Inter
theme
Partial<SnapCnTheme>—Design-system token overrides — the same shape every snap-cn-ui component takes
mode
"light" | "dark""light"Which default token set to resolve against
speed
number1Global playback multiplier applied to the whole sequence

More in this category

  • Search TypingA search field wider than the shot — it comes forward, types across its left half, then pages to its right half
  • Prompt SendA composer that unrolls from a hairline, writes a brief while the camera cuts in and rides the caret, then cuts back out as a pointer arrives and sends it — with typing that eases in and out instead of ticking
  • Prompt ZoomAn assistant landing screen that offers its suggestions, then cuts hard into the caret — a measured 2.547× push anchored on the text insertion point — where the prompt types itself
  • Answer StreamThe beat after send — a macro shot on the button cuts hard to the answer building itself, while the camera pulls back about a focal point above the frame to keep up with it
  • Agent StepsAn agent narrating its own work — a log that writes itself one line at a time, always on the centre line, then swells and clears until only the answer is left