React AnimeJS
Components/Tabs25 / 25

Tabs

uiBeginnerRead the docs

Code

1// Measure the active tab's offset + width so the underline hugs each
2// label exactly (no fixed-width box, no hardcoded offset math).
3const [indicator, setIndicator] = useState({ x: 0, w: 0 });
4
5useLayoutEffect(() => {
6 const el = tabRefs.current[active];
7 if (el) setIndicator({ x: el.offsetLeft, w: el.offsetWidth });
8}, [active]);
9
10// <Anime> slides AND resizes the underline to the active tab.
11// `autoplay` is required: hooks default to autoplay={false}, so deps
12// alone would recreate the tween without ever playing it.
13<Anime
14 translateX={indicator.x}
15 width={indicator.w}
16 duration={300}
17 ease="outExpo"
18 autoplay
19 deps={[indicator.x, indicator.w]}
20>
21 <span className="underline" />
22</Anime>
23
24// Active panel mounts/unmounts as `active` changes. <AnimePresence>
25// drives the cross-fade; mode="wait" gives a clean out-then-in swap.
26<AnimePresence mode="wait" initial={false}>
27 <AnimePresenceChild
28 key={panels[active].label}
29 enter={{ opacity: [0, 1], translateY: [6, 0] }}
30 exit={{ opacity: [1, 0], translateY: [0, -6] }}
31 duration={220}
32 ease="outQuad"
33 >
34 <div className="panel">{panels[active].body}</div>
35 </AnimePresenceChild>
36</AnimePresence>

Animated underline indicator with cross-fading content panels.

Live preview
TabsClick a tab to switch

A hooks-first React wrapper for anime.js v4. Declarative components where they help.

Props
NameTypeDefaultDescription
translateXnumber-Indicator slide to active tab offset
widthnumber-Indicator width matching active tab
autoplaybooleanfalsePlays the (re)created tween — required with deps
depsunknown[][]Re-runs the animation when values change
mode'wait''wait'Exit completes before next panel enters
enterUseAnimeOptions-Panel enter keyframes
exitUseAnimeOptions-Panel exit keyframes
durationnumber220Transition ms

Related components