This component no longer exists. It was in remotionui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-11 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
quote-card
remotionui/quote-cardRemovedBlock
Pull quote read aloud: the mark draws, the quote rises line by line, a marker sweeps the phrase, the attribution lands last
Live preview
live · rendered by the registry
Rendered by remotionui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://remotionui.com/r/quote-card.jsonSource
1import { loadFont } from "@remotion/google-fonts/Inter";2import { interpolate, useCurrentFrame, useVideoConfig } from "remotion";3import { CODE_THEMES } from "@/remotion/lib/code-syntax";4import { getSafeAreaPadding } from "@/remotion/lib/layout";5import { EASING } from "@/remotion/lib/motion-tokens";6import { markEmphasis, markerEdges } from "@/remotion/lib/text-emphasis";78const { fontFamily } = loadFont("normal", {9 weights: ["400", "500", "600", "700"],10 subsets: ["latin"],11});1213export type QuoteCardProps = {14 quote: string;15 /**16 * Phrase inside the quote swept with a marker, word by word. Matched17 * case-insensitively over the whole quote, so it may span a line break.18 */19 emphasis?: string;20 author?: string;21 /** Second attribution line — role, company, handle. */22 role?: string;23 /** Initials in the attribution disc. Falls back to the author's initials. */24 initials?: string;25 /** Characters per line the quote is balanced to. */26 charsPerLine?: number;27 backgroundColor?: string;28 accentColor?: string;29 theme?: "dark" | "light";30 /** Animation speed multiplier. */31 speed?: number;32};3334/** Beat plan in seconds. */35const T = {36 mark: 0,37 quote: 0.3,38 lineStagger: 0.11,39 /** Marker starts once the quote is standing. */40 sweep: 0.34,41 sweepStagger: 0.11,42 attribution: 0.5,43} as const;4445const clamp = {46 extrapolateLeft: "clamp",47 extrapolateRight: "clamp",48} as const;4950const WORD_GAP = "0.28em";5152/** Greedy wrap that keeps the last line from being a runt. */53function balanceLines(text: string, target: number): string[] {54 const words = text.split(/\s+/).filter(Boolean);55 const lines: string[] = [];56 let line = "";5758 for (const word of words) {59 const candidate = line ? `${line} ${word}` : word;60 if (candidate.length > target && line) {61 lines.push(line);62 line = word;63 } else {64 line = candidate;65 }66 }67 if (line) {68 lines.push(line);69 }70 return lines;71}7273/**74 * A pull quote read aloud rather than pasted in: the quote mark draws, the75 * quote rises line by line out of its own masks, a marker sweeps the phrase the76 * speaker leant on, and the attribution arrives last.77 */78export const QuoteCard: React.FC<QuoteCardProps> = ({79 quote,80 emphasis,81 author,82 role,83 initials,84 charsPerLine = 30,85 backgroundColor,86 accentColor = "#F472B6",87 theme = "dark",88 speed = 1,89}) => {90 const frame = useCurrentFrame();91 const { fps, width, height } = useVideoConfig();92// … truncated
