How to set up animations when using 'forceMount' on Accordion? #1481
-
Hey Radix Team, I'm currently struggling with the I've tried playing around with height and visibility, but it just messed up my animations... Can anybody show me an example on how to achieve this? Codesandbox link with |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 2 replies
-
Hi @PhilBookst, The purpose of It's on our radar to provide additional mount options for cases like this but at the moment it’s not something we support via |
Beta Was this translation helpful? Give feedback.
-
I found an ugly little workaround in case anybody else has the same problem: export const MyAccordionItem = ( ) => {
const contentRef = useRef<HTMLDivElement | null>(null);
let removedStyle = false;
useEffect(() => {
const { current: elem } = contentRef;
if (!elem) return;
if (elem.dataset["state"] === "closed") {
elem.style.height = "0px";
}
}, []);
const showElement = useCallback(() => {
const { current: elem } = contentRef;
if (!elem) return;
if (removedStyle) return;
elem.style.height = "unset";
removedStyle = true;
}, []);
return (
<AccordionItem value="value">
<Accordion.Header asChild>
<Accordion.Trigger onClick={showElement}>
trigger
</Accordion.Trigger>
</Accordion.Header>
<AccordionContent forceMount ref={contentRef}>
hello there
</AccordionItem>
);
}; |
Beta Was this translation helpful? Give feedback.
-
Kinda works with <Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1" className="group border-0">
<AccordionTrigger>{title}</AccordionTrigger>
<AccordionContent
forceMount
className="group-data-[state=closed]:hidden"
>
{children}
</AccordionContent>
</AccordionItem>
</Accordion> |
Beta Was this translation helpful? Give feedback.
-
For me previous answers were blocking and breaking animations. export const AccordionContent = ({
children,
}) => {
const ref = useRef(null);
const contentRef = useRef(null);
// Radix Accordion doesnt update height when children updates.
// We need to manualy add a resize observer on children of the Content component
// to update the css variable height of the content.
useEffect(() => {
const content = contentRef.current;
if (!ref.current || !content) return;
const resizeObserver = new ResizeObserver(() => {
const currentHeight = ref.current.clientHeight;
content.style.cssText = `--radix-accordion-content-height: ${currentHeight}px;`;
});
resizeObserver.observe(ref.current);
return () => resizeObserver.disconnect(); // clean up
}, []);
return (
<Content ref={contentRef} forceMount>
<div ref={ref}>{children}</div>
</Content>
);
}; |
Beta Was this translation helpful? Give feedback.
-
I found a solution with pure css, you can check my comment here #1155 (comment) |
Beta Was this translation helpful? Give feedback.
-
Shadcn as base using ResizeObserver and react-merge-refs
|
Beta Was this translation helpful? Give feedback.
Hi @PhilBookst,
The purpose of
forceMount
is to hand over lifecycle to javascript animation libraries and so our built in animation handling doesn’t support this type of use.It's on our radar to provide additional mount options for cases like this but at the moment it’s not something we support via
forceMount
i'm afraid.