Open ciaoben opened 7 months ago
I've spent the past couple of hours trying to come up with a clean solution for this with no luck so far.
The tricky part is we have a few different pieces at play here, one being the underlying Dialog
's open state, our true "isOpen" state (which changes once the animation completes), and then also the user's bind:open
to the Drawer.Root
.
I plan to keep experimenting with a way to work around this but if anyone else wants to take a look I'm open to ideas!
If this is something you all desperately need, in the meantime I can expose the closeDrawer()
function as a prop so you could do something like:
<script lang="ts">
let closeDrawer: CloseDrawer;
</script>
<Drawer.Root bind:closeDrawer>
</Drawer.Root>
<button on:click={() => closeDrawer()>Programatic close</button>
Let me know if this would work. I feel I'm getting close to a solution though.
Thanks for looking into this. The mentioned workaround is not working for me on the latest Drawer update.
ModalBottomDrawer.svelte:66 Uncaught TypeError: $.get(...) is not a function
at HTMLButtonElement.click (ModalBottomDrawer.svelte:66:36)
at HTMLButtonElement.bubble_event (chunk-6IUIVARJ.js?v=ff411993:1472:8)
at HTMLButtonElement.click (button.svelte:20:17)
at HTMLButtonElement.bubble_event (chunk-6IUIVARJ.js?v=ff411993:1472:8)
at HTMLButtonElement.<anonymous> (bits-ui.js?v=ff411993:13667:24)
at HTMLButtonElement.target_handler (chunk-H4AWZ5LT.js?v=ff411993:1847:22)
I'm also struggling with that
If this is something you all desperately need, in the meantime I can expose the
closeDrawer()
function as a prop so you could do something like:<script lang="ts"> let closeDrawer: CloseDrawer; </script> <Drawer.Root bind:closeDrawer> </Drawer.Root> <button on:click={() => closeDrawer()>Programatic close</button>
Let me know if this would work. I feel I'm getting close to a solution though.
I'd need that too
I've spent the past couple of hours trying to come up with a clean solution for this with no luck so far.
The tricky part is we have a few different pieces at play here, one being the underlying
Dialog
's open state, our true "isOpen" state (which changes once the animation completes), and then also the user'sbind:open
to theDrawer.Root
.I plan to keep experimenting with a way to work around this but if anyone else wants to take a look I'm open to ideas!
Would it not work to replace bind:open
with open={$isOpen}
in root.svelte
?
That way the underlying bits-ui Dialog only responds to isOpen
changes, our true open/close state.
And we still have open
exposed as a prop, which already triggers openDrawer
& closeDrawer
.
Trying this worked for me... mostly:
style={$getContentStyle(style)}
from content.svelte
.Just some findings that I hope can help.
Any update on this?
I was running into this from shadcdn-svelte, and I couldn't get that workaround to work because I believe the closeDrawer prop isn't exposed there.
Instead I found the following workaround:
<script>
let dialogTrigger;
</script>
<button on:click={() => {dialogTrigger.click()}}>close</button
<Drawer.Root bind:open={dialogOpen}>
<Drawer.Close>
<div bind:this={dialogTrigger}></div>
</Drawer.Close>
</Drawer.Root>
@huntabyte Great work porting this all to Svelte. Keep carrying the Svelte torch man. I had to get back to making money and stop making videos on my Consulting Ninja channel. Super busy with work now, but a quick fix for anyone that just needs this to look like there isn't a bug....
<script lang="ts">
let expanded: boolean = false;
let delayClose: boolean = false;
// Reactive Statement to actually set the drawer closed
$: {
if (delayClose) {
setTimeout(() => {
expanded = false;
delayClose = false;
}, 300); // <--- Adjust this also as needed. I feel like this looks good. The overlay disappears just as it is reach bottom
}
}
</script>
<button on:click={() => expanded = !expanded}>Open Drawer</button>
<Drawer.Root bind:open={expanded}>
<!-- I like my drawers to close a bit faster than they open so I purposely set duration shorter here -->
<Drawer.Content class="transition-all duration-200 ease-in-out {delayClose ? '!transform translate-y-full' : ''}">
<!-- I am performing an api call when a user chooses something inside of a scroll area in the drawer , but you can put this anywhere on the page you need to initiate the the close -->
<button
on:click={() => {
// Inline for simplicity, but this or in other button click functions works of course
loading = true;
// Whatever else you need to do wrapped in error handling
delayClose = true;
}}
>
I am an option in giant list of options for the user
</button>
</Drawer.Content>
</Drawer.Root>
My workaround is to add fade
to Drawer.Content
:
<script>
import { fade } from 'svelte/transition';
export let drawerOpen = false;
</script>
<button type="button" on:click={() => { drawerOpen = !drawerOpen;}}>Toggle</button>
<Drawer.Root bind:open={drawerOpen} direction="right">
<Drawer.Overlay />
<Drawer.Content transition={fade}>
...
My blind idea was that it could force transition when we close drawer. And it works for me.
On the other hand, your workaround is better @Krulknul 🙏
How to make it work in react?
Describe the bug
I noticed that close animation is broken when using the
bind:open
prop.Reproduction
https://stackblitz.com/edit/vaul-svelte-scaled-z2k92v?file=src%2Froutes%2F%2Bpage.svelte
Logs
No response
System Info
Severity
annoyance