I created a simple tabs component using tailwind and svelte, like the following one:
you can see it working on this repl
I'd like to animate the transition from one option to the other
Similar to what happens in this page: https://www.shadcn-svelte.com/examples/dashboard
How could I achieve such animation, either using tailwind classes or svelte directives?
One approach is to draw an element under the tabs and move that around, the movement then can be animated using a transition.
E.g.
let buttons = [];
$: ({ left, top, width, height } = (() => {
const button = buttons[options.findIndex(o => o == value)];
if (button == null)
return { }; // Not mounted yet
return button.getBoundingClientRect();
})())
<div class="... isolate"> <!-- Prevent z-index leakage -->
<div
class="absolute bg-white rounded-md transition-all"
style="
left: {left}px;
top: {top}px;
width: {width}px;
height: {height}px;
"></div>
{#each options as option, i}
<button
bind:this={buttons[i]}
on:click={() => (value = option)}
class="z-10 ..."
>{option}</button
>
{/each}
</div>
The shadcn-svelte site uses a Svelte crossfade transition:
import { cubicInOut } from "svelte/easing";
import { crossfade } from "svelte/transition";
const [send, receive] = crossfade({
duration: 250,
easing: cubicInOut,
});
{#if isActive}
<div
class="bg-muted absolute inset-0 rounded-full"
in:send={{ key: "activetab" }}
out:receive={{ key: "activetab" }}
/>
{/if}
Crossfades have issues with transparency (overlaying two partially transparent elements does not yield a fully opaque area), but even then it probably would not be very visible for small elements like this.