Need help debugging animations
I had a brilliant idea for implementing an animated responsive tab bar component, but I need help debugging animations.
Explanation
The idea is as follows: instead of making the indicator reside in the tab bar element, move it inside the currently active tab. This way if the tab changes its width the indicator will resize as well. To animate it, we need to calculate offsets (
left
and right
) of the previous tab relative to the current tab. If there are multiple ongoing animations we need to readjust each single one (create a new animation relative to the current tab and set its currentTime
to the time of the animation we are adjusting).
The problem
If I have 2 simulatenous animations, everything works as expected, but with 3 or more the indicator starts shifting. (see attachment)
I'm not that good at doing maths in coordinate space, so I must have miscalculated something. I hope someone can point me in the right direction.
Minimal, reproducible example
To observe the problem, quickly click through 3 or more different tabs (the animation will break)
Here's the link to a MRE (heavily simplified):
https://codesandbox.io/p/devbox/tab-bar-36kj3623 Replies
My advice would be to just use Kobalte's tabs which can handle the animation for you 😅
https://kobalte.dev/docs/core/components/tabs
It breaks...
I haven't seen a perfect tabs implementation yet
i'm probably gonna fix that at some point, it's a problem in my app too
but at least i don't have to write animation code lol
will be fixed soon, go ahead and use it
https://github.com/kobaltedev/kobalte/pull/458
GitHub
Recalculate tab indicator styles on resize by Brendonovich · Pull R...
The tab indicator currently doesn't resize if the tab trigger changes size. Adding a resize observer on the selected tab seems to be an easy fix.
Screen.Recording.2024-08...
Screen.Recording.2024-08...
That's nice
But resize observer seems like a big performance issue
do you know a better way?
That's what I was trying to achieve
¯\_(ツ)_/¯
My way only has some calculations which are only done whenever tab index changes
wouldn't yours need a resize observer too for if the tab size changes?
kobalte's implemention pretty much only runs the calculations when the selected tab element changes too
No
In my case the indicator is inside the active tab element
so
left: 0
and right: 0
provide auto resize
In my case it can be resized even while animatingare you basically reparenting the indicator when the animation finishes?
When it starts*
Is that compatible with css transitions?
I think it's not, but I'm not making an unstyled component
also WAAPI is hardware accelerated as well
Yeah if you’re not using css transitions that’s fair
I just realized I also wanted to make the indicator to have this stretching effect so I have to rewrite all of that logic to have separate animations for left and right edges
https://firebasestorage.googleapis.com/v0/b/design-spec/o/projects%2Fm3%2Fimages%2Flasu1iqx-3P%20-%20Behavior-%20Fixed%20tabs%20Hero.mp4?alt=media&token=51db9a01-3477-4b3a-9224-09400eaea124
Also WAAPI is compatible with controlled animations (e.g dragging the content area could control the indicator animation)
I like your idea. I tried implementing it a bit simpler here https://playground.solidjs.com/anonymous/0633f857-6c75-432b-aa8c-e167155fb7f4
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
This example makes the duration depend on
sqrt(distance)
traveled https://playground.solidjs.com/anonymous/51f8765f-cc7c-4e28-a820-4fbfdb589918Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
That's nice! Though I would consider not using CSS variables and sqrt since it has pour support
CSS props should be supported since 2016? Not sure about sqrt, but you can do it in js easily
I mean, css props can have name conflicts