Preanimate
Per-component skeleton swap. Renders a placeholder until ready flips, then mounts the real content — so its entrance animations (SplitReveal, Stagger, etc.) fire exactly when the skeleton disappears, not while it's still on screen.
Usage
import { PreanimateProvider, Preanimate, Skeleton, SplitReveal } from '@bwo-ui/react';
<PreanimateProvider duration={900}>
<Preanimate skeleton={<Skeleton height={48} style={{ width: 320 }} />}>
<SplitReveal as="h1" type="words" stagger={0.04}>
Real title that animates in
</SplitReveal>
</Preanimate>
</PreanimateProvider>Pair multiple Preanimate swaps under a single PreanimateProvider so they share one ready signal and flip in sync.
PreanimateProvider props
| Prop | Type | Default | Description |
|---|---|---|---|
duration | number | 1000 | Auto-flip ready=true after this many ms. |
ready | boolean | — | External control. When set, `duration` is ignored. |
Preanimate props
| Prop | Type | Default | Description |
|---|---|---|---|
skeleton | ReactNode | — | Rendered while not ready. Should occupy the same dimensions as the real content. |
children | ReactNode | — | Real content. Not mounted until ready — entrance animations fire on swap. |
delay | number | — | Extra ms to wait *after* the provider's base ready flips before mounting children. Use to cascade entrances (e.g. cards waiting for the hero typewriter to finish). |
Cascading entrances
Each Preanimate under one provider can stage its own ready time with delay. Total wait per section is provider.duration + delay.
<PreanimateProvider duration={900}>
{/* mounts at 900ms — hero starts typing */}
<Preanimate skeleton={<TitleSkeleton />}>
<Typewriter lines={[...]} />
</Preanimate>
{/* mounts at 900 + 1500 = 2400ms — by then the typewriter is well into reveal */}
<Preanimate skeleton={<ShowcaseSkeleton />} delay={1500}>
<Stagger>...cards...</Stagger>
</Preanimate>
</PreanimateProvider>usePreanimate()
Drop-in hook returning the shared ready boolean. Useful when you need to conditionally swap parts of a single component:
function Card() {
const ready = usePreanimate();
return ready ? <RealCard /> : <CardSkeleton />;
}