I am attempting to code a Sidebar in Svelte and have run into issue related to how Svelte transitions work with dynamic classes.
Sidebar is supposed to fly into view when a button is clicked. I am using the transition:fly
for it. There is also a Dimmer component covering the entire screen, which fades into view during Sidebar’s fly animation. To close the Sidebar user must click the Dimmer. Sidebar then flies out of view, and Dimmer fades out. And here is my problem.
Where the Dimmer is in its fade out animation, the page underneath cannot be interacted with. Clicking anywhere registers on the dimmer itself, Sidebar stops its fly out animation and jumps back into view.
I tried to solve it by appending isFading
class to the Dimmer when the outro animation starts – the class would add pointer-events: none
to the Dimmer when it fades out. But the class is appended with a delay and this solution simply does not work.
My code looks as follows:
<script lang="ts">
import { fade } from 'svelte/transition'
import { isSidebarOpen, toggleSidebar } from '../state'
let isOpen: boolean = false
let isFading: boolean = false
isSidebarOpen.subscribe((value) => (isOpen = value))
</script>
<div class="sidebar">
{#if isOpen}
<div
class="sidebar__dimmer"
class:isFading
on:click={toggleSidebar}
on:outrostart={() => (isFading = true)}
on:introstart={() => (isFading = false)}
transition:fade={{ duration: 500 }}
/>
{/if}
<div>Lorem opsum dolor sit amet</div>
</div>
<style lang="scss" scoped>
.sidebar {
z-index: 9999;
position: fixed;
inset: 0;
display: flex;
overflow: hidden;
pointer-events: none;
&__dimmer {
position: absolute;
inset: 0;
pointer-events: all;
}
&__dimmer.isFading {
pointer-events: none;
}
}
</style>
My question is: how do I append the isFading
class to the component instantly when the outro animation starts?
2
Answers
In Svelte 4 you should not need this in browsers supporting
inert
, as that will be added automatically.You could apply the class directly using the DOM via the event:
(Might have to use
target?.
,currentTarget
or extract logic to functions if you run into TypeScript errors.)Since the class is applied in a way that makes it invisible to the compiler, you will have to change the selector accordingly:
By using the start and end transition callbacks, the isFading class will be applied instantly when the outro animation starts, and it will be removed when the outro animation ends. This should help you achieve the desired behavior where the Dimmer doesn’t interfere with interactions while fading out.