This component no longer exists. It was in blaze-motion’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-06 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.
Mask Text Reveal
blaze-motion/mask-text-revealRemovedComponent
Masked text reveal — words rise out from behind a clip mask, token by token.
Install it
npx shadcn@latest add https://motion.asmitsah.dev/r/mask-text-reveal.jsonSource
1"use client";23import * as m from "motion/react-m";4import {5 type CSSProperties,6 Fragment,7 isValidElement,8 type ReactElement,9 type ReactNode,10} from "react";11import { feel, maskTextItem, textRevealContainer, viewportOnce } from "@/lib/motion";1213const TAGS = {14 span: m.span,15 div: m.div,16 p: m.p,17 h1: m.h1,18 h2: m.h2,19 h3: m.h3,20 h4: m.h4,21 h5: m.h5,22 h6: m.h6,23} as const;2425type Tag = keyof typeof TAGS;26type HostProps = { className?: string; style?: CSSProperties; children?: ReactNode };2728type MaskTextRevealProps = {29 /** A single host element (h1–h6 / p / span / div) whose own children is a30 * plain string. MaskTextReveal reconstructs THAT element as the animated one —31 * its tag, className + style win; no extra DOM wrapper is added. */32 children: ReactNode;33 delay?: number;34 by?: "word" | "line";35 trigger?: "inView" | "mount";36};3738/** Text slides up out of a hard mask — no fade, crisp editorial. Per token an39 * overflow-hidden wrapper clips an inner span that rises from below (110% → 0). */40export function MaskTextReveal({41 children,42 delay = 0,43 by = "word",44 trigger = "inView",45}: MaskTextRevealProps) {46 const play =47 trigger === "mount"48 ? ({ animate: "animate" } as const)49 : ({ whileInView: "animate", viewport: viewportOnce } as const);5051 // Read the wrapped element's tag + props + string text so we can re-render it52 // as the matching m[tag] carrying the stagger — the caller's tag/className win.53 const child = isValidElement(children) ? (children as ReactElement<HostProps>) : null;54 const tag = child && typeof child.type === "string" ? child.type : null;55 const text = child && typeof child.props.children === "string" ? child.props.children : null;5657 // Fail soft: if the child isn't a single host element wrapping a plain string,58 // render it untouched (unanimated) rather than crash.59 if (!child || !tag || !(tag in TAGS) || text === null) {60 return <>{children}</>;61 }6263 const Container = TAGS[tag as Tag] as typeof m.span;64 const { className, style } = child.props;65 const step = by === "line" ? feel.lineStagger : feel.textStagger;66 // Headings permit an accessible name; generic tags (span/div/p) don't — so an67 // aria-label there is prohibited. role="img" lets the label name the composite68 // while the per-token masks stay aria-hidden.69 const isHeading = tag.length === 2 && tag.startsWith("h");70 const tokens =71 by === "line"72 ? text73 .split("\n")74// … truncated
What it pulls in
npm packages
Other registry items
