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.
Line Reveal
blaze-motion/line-revealRemovedComponent
Per-line rise + fade, staggered and calm — for body copy / multiline blocks; each line clips inside its own mask.
Install it
npx shadcn@latest add https://motion.asmitsah.dev/r/line-reveal.jsonSource
1"use client";23import * as m from "motion/react-m";4import { type CSSProperties, isValidElement, type ReactElement, type ReactNode } from "react";5import { lineRevealContainer, lineRevealItem, viewportOnce } from "@/lib/motion";67const TAGS = {8 span: m.span,9 div: m.div,10 p: m.p,11 h1: m.h1,12 h2: m.h2,13 h3: m.h3,14 h4: m.h4,15 h5: m.h5,16 h6: m.h6,17} as const;1819type Tag = keyof typeof TAGS;20type HostProps = { className?: string; style?: CSSProperties; children?: ReactNode };2122type LineRevealProps = {23 /** A single host element (h1–h6 / p / span / div) whose own children is a24 * plain string (split on "\n"). LineReveal reconstructs THAT element as the25 * animated one — its tag, className + style win; no extra DOM wrapper. */26 children: ReactNode;27 delay?: number;28 trigger?: "inView" | "mount";29};3031/** Per-line rise + fade, staggered and calm — for body copy / multiline blocks.32 * Splits the wrapped element's string on "\n"; each line clips inside its own33 * overflow-hidden wrapper so the rise reads as an emerge, not a slide.34 * Transform-only (provider handles reduced motion). aria-label carries the whole35 * text so SR reads it as one passage. */36export function LineReveal({ children, delay = 0, trigger = "inView" }: LineRevealProps) {37 const play =38 trigger === "mount"39 ? ({ animate: "animate" } as const)40 : ({ whileInView: "animate", viewport: viewportOnce } as const);4142 // Read the wrapped element's tag + props + string text so we can re-render it43 // as the matching m[tag] carrying the stagger — the caller's tag/className win.44 const child = isValidElement(children) ? (children as ReactElement<HostProps>) : null;45 const tag = child && typeof child.type === "string" ? child.type : null;46 const text = child && typeof child.props.children === "string" ? child.props.children : null;4748 // Fail soft: if the child isn't a single host element wrapping a plain string,49 // render it untouched (unanimated) rather than crash.50 if (!child || !tag || !(tag in TAGS) || text === null) {51 return <>{children}</>;52 }5354 const Container = TAGS[tag as Tag] as typeof m.div;55 const { className, style } = child.props;56 const lines = text57 .split("\n")58 .map((line) => line.trim())59 .filter((line) => line.length > 0);60 // Headings permit an accessible name; generic tags (span/div/p) don't — so an61 // aria-label there is prohibited. role="img" lets the label name the composite62// … truncated
What it pulls in
npm packages
Other registry items
