6 tab bar animations. Copy any short prompt for free, and open full prompt 1 to see how detailed they are. Full prompts 2–6 are in the pack.
Basics: stage 470×222px, background #13131C, all coordinates in px from the stage's top-left, everything clipped to the stage. The animation is a seamless 4s loop that plays by itself (u = loop time 0–4 s). A tap lands every 1.0s, at u = 0, 1, 2 and 3, selecting the tabs SEL = [3, 1, 2, 0] in that order (tab 0 is the leftmost), so the moves are 0→3, 3→1, 1→2, 2→0. Treat the taps as an endless cycle: for any u, lastTap = {k = floor(u), to = SEL[k], from = SEL[(k+3) mod 4], dt = u − k} and nextTap = {to = SEL[(k+1) mod 4], dt = k + 1 − u}; whatever the previous tap started keeps running (the 0s tap's "from" is tab 0, the one the 3s tap selected). In a 12s video, u = (T + 0.25) mod 4 (T = video time), so the first frame is 0.25s after a tap and the taps fall at T = 0.75, 1.75 … 11.75. Bar barRect: 410×92px, corner radius 30, centered at (235, 148) (x 30–440, y 102–194), fill #1B1A28 with a shadow rgba(0,0,0,0.45) blur 18, offset y 6; then a 2px border rgba(255,255,255,0.08) on rr(31, 103, 408, 90, 29). Tab centers tx(i) = 30 + 102.5·(i + 0.5) = 81.25, 183.75, 286.25, 388.75; the bar's vertical center is y = 148. Tabs 0–3 are Home, Search, Likes (heart), Profile. Icons icon(i, x, y, s, color, fill = 0, fillColor, lw) are hand-drawn paths in units where 1 = s px (s = 17 unless stated): translate to (x, y), scale by s, line width lw/s (so it stays lw px; lw = 2.8 unless stated), round caps and joins. Home: closed polygon (−0.72, 0.78) (−0.72, −0.12) (0, −0.78) (0.72, −0.12) (0.72, 0.78), plus a door, an open line (−0.2, 0.78)→(−0.2, 0.28)→(0.2, 0.28)→(0.2, 0.78). Search: circle at (−0.12, −0.12), radius 0.56, plus a handle line (0.29, 0.29)→(0.78, 0.78). Heart: M(0, 0.78) C(−0.35, 0.5)(−0.92, 0.12)(−0.88, −0.3) C(−0.84, −0.74)(−0.24, −0.86)(0, −0.42) C(0.24, −0.86)(0.84, −0.74)(0.88, −0.3) C(0.92, 0.12)(0.35, 0.5)(0, 0.78) Z. Profile: head circle at (0, −0.4), radius 0.34, plus body M(−0.78, 0.8) C(−0.78, 0.08)(0.78, 0.08)(0.78, 0.8) Z. If fill > 0: clip to the closed shape (polygon / circle / heart / head+body) and fill a circle of radius 1.3·fill at (0, 0.05) with fillColor; then stroke the outline in color; the door is stroked in color and, when fill > 0.3, again in #1B1A28 at opacity clamp((fill − 0.3)/0.4); the search handle is stroked as a line. Inactive icons are gray #8C8AA8. Colors: violet #6E5BFF, cyan #38C6FF, gray #8C8AA8. "violet→cyan" = a linear gradient from the shape's left edge (violet) to its right edge (cyan) unless end points are given; grad(x0, y0, x1, y1, stops) = linear gradient with evenly spaced stops. mix(A, B, k) = per-channel linear RGB blend, k clamped to 0–1. clamp(x) = x clamped to 0–1; lerp(a, b, k) = a + (b − a)·k; seg(x, a, b) = clamp((x − a)/(b − a)); ease(k) = 1 − (1 − k)³; easeIO(k) = 4k³ for k < 0.5, else 1 − (−2k + 2)³/2 (k clamped first). Spring springF(ω₀, ζ)(t) = 0 for t ≤ 0, else 1 − e^(−ζω₀t)·(cos ω_d t + (ζω₀/ω_d)·sin ω_d t), ω_d = ω₀√(1 − ζ²). posAt(u, f) = from + (to − from)·f(dt) (a tab position in tabs, fractional; tx() of a fractional position interpolates linearly). hash(n) = fract(sin(127.1n + 311.7)·43758.5453). rr(x, y, w, h, r) = rounded rect with top-left (x, y). Tap indicator tapMark (drawn last, on top of everything; at (tx(i), 148) over the tab that is about to be tapped, unless a prompt moves it): a = time relative to that tap (negative before); visible for −0.42 ≤ a < 0.4 (before the tap it shows the next tap, after it the last one). Circle radius 23, fill rgba(215,215,230,0.38) with a shadow black 35% blur 10 (fill only), then a 3.5px border rgba(255,255,255,0.92) (the border scales with the circle). Scale: a < −0.1: lerp(1.25, 1, ease((a + 0.42)/0.32)); −0.1 ≤ a < 0: lerp(1, 0.8, (a + 0.1)/0.1); a ≥ 0: lerp(0.8, 1, ease(a/0.2)). Opacity: clamp((a + 0.42)/0.18) before the tap, clamp(1 − (a − 0.12)/0.25) after. Ripple (under the circle, not scaled, 0 ≤ a < 0.4): a 3px white ring of radius 23·(1 + 3.2a), opacity 0.7·(1 − a/0.4). The indicator stays where the tap happened.
Each icon sits on a small tile; the tapped tile flips around its vertical axis with real perspective to a violet→cyan back with a white icon, and the old one flips on to its plain front again.
- Bar: the Basics bar.
- Two faces per tab, each drawn once on a 68×68 canvas (at 2× resolution) with a 64×64 tile at (2, 2), radius 18:
- front: fill rgba(255,255,255,0.05), a 1.5px border rgba(255,255,255,0.12) on rr(2.75, 2.75, 62.5, 62.5, 17.25), and the gray icon (s = 17, lw 2.8) at the center (34, 34).
- back: fill with a gradient from (2, 2) violet to (66, 66) cyan, a 1.5px border rgba(255,255,255,0.3) on the same inset rect, a sheen = the top half rr(2, 2, 64, 32) with radii [18, 18, 0, 0] filled with a vertical gradient y 2 → 34 from rgba(255,255,255,0.22) to transparent, and the icon in #FFFFFF (s = 17, lw 2.8) at the center.
- Angle θ per tab: the tapped tab θ = π·springF(12, 0.5)(dt) (it overshoots past π and settles); the tab that loses the selection θ = π·(1 + springF(14, 0.62)(dt)) (continues the same way round to 2π = front); every other tab θ = 0.
- Perspective flip (eye distance d = 150px): cut the face into 34 vertical strips. For a strip covering local x from xa to xb (x measured from the face center, −34…34; for the back face use x = −(column − 34) so it is not mirrored), its screen x edges are x·cosθ·d/(d − x·sinθ), and its height is 68·d/(d − x_mid·sinθ), centered vertically on the tile center; draw the strip image there (0.6px extra width to hide seams). Show the front while cosθ ≥ 0, the back while cosθ < 0.
- Around each tile center (tx(i), 148): first a glow when b = max(0, −cosθ) > 0.01: a radial gradient radius 4 → 52, rgba(110,91,255,0.55) → rgba(56,198,255,0), filling a 104×104 square, opacity b. Then the tile, scaled by 1 + 0.14·|sinθ| around its center and drawn at opacity 1 − 0.3·|sinθ|.
- Draw order: bar, then for each tab glow and tile, then the tap indicator.