[tabs] How does it work with Motion?
So I tried to use it similar way as Radix, but it's doesn't work
"use client"
import * as React from "react"
import { useState } from "react"
import { Tabs } from "@base-ui-components/react/tabs"
import { AnimatePresence, motion } from "motion/react"
export function NewTabsDemo() {
const [active, setActive] = useState("one")
return (
<Tabs.Root value={active} onValueChange={setActive} defaultValue="one">
<Tabs.List>
<Tabs.Tab value="one">One</Tabs.Tab>
<Tabs.Tab value="two">Two</Tabs.Tab>
<Tabs.Tab value="three">Three</Tabs.Tab>
</Tabs.List>
<AnimatePresence mode="popLayout">
{active === "one" && (
<Tabs.Panel
className="bg-red-500 p-12"
value="one"
keepMounted
render={
<motion.div
initial={{
opacity: 0,
y: -100,
}}
animate={{
opacity: 1,
y: 0,
}}
exit={{
opacity: 0,
y: 100,
}}
/>
}
>
one
</Tabs.Panel>
)}
{active === "two" && (
<Tabs.Panel
keepMounted
className="bg-green-500 p-12"
value="two"
render={
<motion.div
initial={{
opacity: 0,
y: -100,
}}
animate={{
opacity: 1,
y: 0,
}}
exit={{
opacity: 0,
y: 100,
}}
/>
}
>
two
</Tabs.Panel>
)}
{active === "three" && (
<Tabs.Panel
keepMounted
className="bg-yellow-500 p-12"
value="three"
render={
<motion.div
initial={{
opacity: 0,
y: -100,
}}
animate={{
opacity: 1,
y: 0,
}}
exit={{
opacity: 0,
y: 100,
}}
/>
}
>
three
</Tabs.Panel>
)}
</AnimatePresence>
</Tabs.Root>
)
}
I haven't found a single examples of usage with Motion.
Hi @subproject22, in our next release the docs will be updated with some Motion examples but this mainly pertains to popup-related components, not ones like Tabs.
You can read the updated docs here - we can investigate Motion animations with Tabs soon though
hey @atomiks thanks for response. As for my example with Tabs, adding key helps, but still can't make exit animation work.
Related to https://github.com/mui/base-ui/issues/1486
@subproject22 Just wondering if you've gotten Radix Tabs working well with motion, and if so are you able to share a sandbox or demo 🙏
adding
keyhelps, but still can't make exit animation work
I found that this is when the active state changes, the exiting panel is gone immediately despite keepMounted because they are rendered like: {value === 'one' && (<Panel />)}
Also realized Panel uses the hidden attribute when not active, so Tailwind 4's reset could interfere with exit animations, since it applies:
[hidden]:where(:not([hidden='until-found'])) {
display: none !important;
}
@mj12albert – Is Tailwind 4's reset so weird? Seems like a good way to ensure that author CSS cannot accidentally unhide a hidden element with a high specificity selector. IMO the problem is that Motion should also use !important in its inline styles to ensure it beats any non-runtime styles.
Is Tailwind 4's reset so weird?
I think it's a sensible default for this, it's just annoying because it seems the only way to opt-out of one thing is to fork the whole file 🙈