Hello. I'm creating a component with Preact, the idea is making a progressive enhancement of an accordion. My idea was to show it as a card when JS is not loaded and change it to the accordion view once it loads.
My approach here was to use a state, let it be false by default, and then change it to true with an useEffect. This is how the code looks
import { useState, useEffect } from "preact/hooks";
export default function Accordion({ title, children }) {
const [expanded, setExpanded] = useState(false);
const [loadedJs, setLoadedJs] = useState(false);
useEffect(() => {
setLoadedJs(true);
}, []);
return (
<>
{loadedJs ? (
<>
<h3>
<button
aria-expanded={expanded}
onClick={() => setExpanded(!expanded)}
>
{title}
</button>
</h3>
<div {...{ hidden: !expanded }}>{children}</div>
</>
) : (
<article>
<h3>{title}</h3>
<div>{children}</div>
</article>
)}
</>
);
}
And this is how I have it on my index.astro
<Accordion title="Accessibility fundamentals" client:load>
<p>Paragraph test to check if the elements renders as expected</p>
</Accordion>
The problem is that the change between views is evident and it'll cause a layout shift. Is there a better way to create a progressively enhanced component using Preact? Maybe turning it into a Web Component with 'preact-custom-element'?
I tried to use the noscript tag but for some odd reason, children is not being rendered once JS loads. That'd be a great solution because it doesn't create a layout shift, but it's not working lol
I'd like to know your experience creating this kind of components. Thanks! 🙂