Use node animation to animate the open/close of accordion, attach this animation to the svelte component, and create passed props like duration.

This commit is contained in:
Bradley Shellnut 2021-07-27 11:40:56 -07:00
parent bad22ed422
commit 6a68fd734b
2 changed files with 36 additions and 5 deletions

View file

@ -8,11 +8,20 @@
<span class:isOpen></span>
{buttonText}</button
>
<div class="accordion-content" use:slide={isOpen}>
<slot />
<div
class="accordion-content"
use:slide={{ isOpen, duration: 200 }}
on:animationEnd={() => console.log('Animation ended')}
>
<div class="wrapper">
<slot />
</div>
</div>
<style>
.wrapper {
padding: 20px;
}
button {
display: block;
border: 0;

View file

@ -1,12 +1,34 @@
export function slide(node, isOpen) {
export function slide(node, { isOpen, duration = 500 }) {
// Initialize
let initialHeight = node.offsetHeight;
node.style.height = isOpen ? 'auto' : 0;
node.style.overflow = "hidden";
let animation = node.animate([
{
height: 0,
}, {
height: `${initialHeight}px`,
}
], {
duration,
fill: 'both',
direction: isOpen ? 'reverse' : 'normal',
});
animation.pause();
animation.onfinish = ({ currentTime }) => {
if(!currentTime) {
animation.reverse();
animation.pause();
}
node.dispatchEvent(new CustomEvent('animationEnd'));
}
return {
update: (isOpen) => {
node.style.height = isOpen ? 'auto' : 0;
update: () => {
animation.currentTime ? animation.reverse() : animation.play();
}
}
}