@entrancekit/react
Turn an intro animation you already have — a video, a Lottie file, or your own React
component — into a correct app entrance, without writing the lifecycle yourself.
The animation is the easy part. The flow around it is not: playing it on load without
blocking the app, honoring reduced motion, falling back on slow or failed loads, exiting by
the model you chose, and tearing down cleanly. EntranceKit owns that flow. You keep owning
the animation.
- Non-blocking — the overlay never gates your app; it stays interactive underneath.
- Reduced-motion aware —
prefers-reduced-motion is honored by default (no flash).
- Graceful — skips on error, falls back on timeout, never traps the user.
- Self-removing — deterministic teardown on every exit path, with an optional outro.
- Bring your own — MP4/WebM, Lottie JSON, or any custom React/Motion/GSAP/Canvas/SVG
component. Client-only, single package, zero runtime dependencies, SSR-safe.
Install
npm install @entrancekit/react
npm install @lottiefiles/dotlottie-react
Drop in a video
import { EntranceVideo } from '@entrancekit/react';
export default function Root() {
return (
<>
<App /> {/* renders and stays interactive the whole time */}
<EntranceVideo
id="launch"
sources={[
{ src: '/intro.webm', type: 'video/webm' },
{ src: '/intro.mp4', type: 'video/mp4' },
]}
poster="/intro-poster.png"
fallbackAfter={2500}
/>
</>
);
}
Bring your own component (the core)
import { EntranceController } from '@entrancekit/react';
<EntranceController id="launch">
{({ shouldAnimate, complete, skip }) => (
<MyIntro
play={shouldAnimate} // start when told
onComplete={complete} // its OWN done-signal — the preferred path
onError={skip} // never trap the user
/>
)}
</EntranceController>;
The lifecycle
EntranceKit owns one canonical state machine:
idle → preload → play → resolve → done
Every way an entrance can end — the animation's own done-signal, a user skip, a timeout, an
error, or a reduced-motion suppression — funnels through a single resolve carrying a
reason, so teardown is deterministic on every path. Wire your animation's native end event
to complete(); fallbackAfter is only a safety net for a hung or slow load, never a cap on
a correctly-signalling animation.
API at a glance
EntranceController | Render-prop for a bring-your-own animation. The core. |
EntranceVideo | MP4/WebM convenience entry point (prefers native ended). |
EntranceLottie | Lottie JSON entry point (optional, lazy-loaded player). |
useEntrance | The same engine, headless, for a fully custom overlay. |
Shared props: id (required), fallbackAfter (default 4000), reducedMotion
('skip' | 'play', default 'skip'), skipControl (true | render-fn | false),
outro (number | { durationMs, render }), container, and
onResolve / onError / onStateChange.
There is no mode, no persistence, and no show-policy in v0.1.0 — an entrance is a
transient overlay that plays and leaves, not a once-per-user gate.
Demo
A live Playground (every source, every scenario, every exit model) is at
terminalis.github.io/entrancekit (deployed by
CI from examples/demo). Run it locally:
npm install && npm run build
npm --prefix examples/demo install
npm --prefix examples/demo run dev
License
MIT