Installation
Usage
import { ArcRevealHero } from "@/components/ruixen/arc-reveal-hero";
export default function Page() {
return (
<ArcRevealHero
greetings={[
{ text: "Hello", lang: "en" },
{ text: "你好", lang: "zh" },
{ text: "Bonjour", lang: "fr" },
{ text: "やあ", lang: "ja" },
{ text: "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ ਜੀ", lang: "pa" },
]}
storageKey="home-intro"
>
<YourLandingPage />
</ArcRevealHero>
);
}Pass any landing content as children — it sits on the dark surface that the
curtain reveals. The intro plays once per session when storageKey is set;
omit the prop to replay on every mount (handy in dev or for component pages).
Props
| Prop | Type | Default | Description |
|---|---|---|---|
greetings | ArcRevealGreeting[] | 8 mood words | Words cycled before the reveal — single declarative beats by default. |
greetingHold | number | 620 | Time (ms) each greeting is held on screen. |
revealDuration | number | 1500 | Duration (ms) of the curved curtain rise. |
storageKey | string | - | When set, the intro plays only once per sessionStorage lifetime. |
className | string | - | Extra classes on the outer <section> (the post-reveal surface). |
introClassName | string | - | Extra classes on the intro overlay (the pre-reveal surface). |
greetingClassName | string | - | Extra classes on the cycled greeting <span>. |
revealClassName | string | - | Extra classes on the wrapper around children. |
Types
type ArcRevealGreeting = {
text: string;
lang?: string;
};Features
- Single continuous arc — one quadratic Bézier with a constant concavity translates upward across the viewport, so the top edge of the curtain stays a smooth curve from the first frame to the last. No flat slide, no segmented stages.
- Driven entirely by motion values — the SVG
dattribute updates viauseTransformon a single progress value, so the curve runs off React's render loop for genuine 60 fps motion. - Mood-word cycle — defaults ship with eight short declarative beats (Quiet · Sharp · Calm · Crafted · Considered · Composed · Honest · Ready) to set tone before the reveal. Each fades and lifts with an
[0.22, 1, 0.36, 1]ease that's snappy without feeling abrupt. Pass your owngreetings(with optionallang) to script anything — brand words, multilingual hellos, a countdown. - Considered easing — the curtain rises with
[0.85, 0, 0.15, 1](strong ease-in-out): a deliberate anticipation at the start, a quick cover, and a soft settle as it locks into place. - Accessibility-aware — respects
prefers-reduced-motion(skips straight to the revealed surface), and usesaria-hiddenon the curtain so screen readers jump straight to the landing content. - Plays once per session — pass
storageKeyto suppress replays inside the samesessionStoragelifetime; omit it to replay on every mount (the default for component pages). - Self-contained overlay — the intro lives inside the section's own bounding box (
position: absolute, one viewport tall,overflow: hidden), so it never covers a parent layout's nav or sidebar and never locks page scroll. Drop it at the top of any page and the rest of the page keeps scrolling normally.

