shadcn-svelte
shadcn-svelte copied to clipboard
Dialog/Drawer issues with controlled state
Describe the bug
If using a store in melt to control open, then clickoutside still works. In Drawer/Dialog it doesn't. https://shadcdn-drawer.vercel.app/
Reproduction
https://github.com/hartwm/shadcdn-drawer
Logs
No response
System Info
System:
OS: macOS 13.5.1
CPU: (10) x64 Apple M1 Pro
Memory: 29.54 MB / 32.00 GB
Shell: 5.1.4 - /usr/local/bin/bash
Binaries:
Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 10.2.4 - /usr/local/bin/npm
pnpm: 8.12.1 - ~/Library/pnpm/pnpm
Browsers:
Brave Browser: 120.1.61.109
Chrome: 120.0.6099.199
Safari: 16.6
npmPackages:
@sveltejs/kit: ^2.0.0 => 2.1.2
bits-ui: ^0.13.6 => 0.13.6
svelte: ^4.2.7 => 4.2.8
vaul-svelte: ^0.0.6 => 0.0.6
Severity
annoyance
I can reproduce the Drawer, but if I apply bind:open={$dialogOpen} to the Dialog then it works. In theory, both should work without bind, so I will investigate this further.
Similar issue happens when Drawer is invoked from within the Dialog. Then closing the Drawer also closes the background/parent dialog. Including weird case when clicking within the Drawer closes both Drawer and parent Dialog.
https://github.com/huntabyte/shadcn-svelte/assets/4096154/a0deaf9c-9ccd-4f9a-b3ea-c9e2d832596e
There is a similar issue when creating a toast when a Drawer or Dialog is open. Closing/dragging to close the toast also closes the Drawer or Dialog.
If a Drawer has a form in the <Drawer.Content></Drawer.Content>t , it won't drag to close itself, only if you click/interact with the form first.
https://github.com/huntabyte/shadcn-svelte/assets/97332554/6bcf62f9-b08f-4e66-81d5-4f90950f46db
https://github.com/huntabyte/shadcn-svelte/assets/97332554/d06295af-ec45-4bf0-8a74-15a1f385072c
There is a similar issue when creating a toast when a
DrawerorDialogis open. Closing/dragging to close the toast also closes theDrawerorDialog. If aDrawerhas a form in the<Drawer.Content></Drawer.Content>t, it won't drag to close itself, only if you click/interact with the form first.Dialog.mp4 drawer.mp4
I got the drawer drag work when first opened by wrapping the form in a div and giving it a height of 1/2
There is a similar issue when creating a toast when a
DrawerorDialogis open. Closing/dragging to close the toast also closes theDrawerorDialog.
This is because it considers the toast to be an "outside click" event, and closes the drawer on those events. You can use the onOutsideClick prop on the Dialog.Root to ignore certain conditions.
For example, if all of your toasts had a common data- attribute, you could prevent that behavior from occurring by doing something like this:
<script lang="ts">
// let's say all of our toasts have a `data-toast` attribute
function onOutsideClick(event: PointerEvent) {
if (event.target && event.target.hasAttribute("data-toast") {
event.preventDefault()
}
};
</script>
<Drawer.Root {onOutsideClick}>
<!-- ... -->
</Drawer.Root>
By calling preventDefault() on the event, it tells bits-ui to ignore that event altogether and not do what it normally would, which in this situation is closing the drawer.
Will make a note to document this a bit better!
My case was fixed with:
bits-ui ^0.15.1 → ^0.16.0
vaul-svelte ^0.1.0 → ^0.2.1
Thank you.
My case was fixed with:
bits-ui ^0.15.1 → ^0.16.0 vaul-svelte ^0.1.0 → ^0.2.1Thank you.
Issue is back again with:
bits-ui ^0.16.0 → ^0.17.0
:)
Similar issue here. The selection of a Select in Drawer makes the drawer close.
Update: I use this to fix it:
onOutsideClick={(e) => {
if (e.target && e.target instanceof HTMLElement && e.target.hasAttribute('data-select-item')) {
e.preventDefault();
}
}}
Reproduction: https://stackblitz.com/edit/github-6lpr3i?file=src%2Froutes%2F%2Bpage.svelte or
<script lang="ts">
import * as Drawer from "$lib/components/ui/drawer";
import * as Select from "$lib/components/ui/select";
let fix = false // true to fix
</script>
<Drawer.Root onOutsideClick={(e) => {
if (!fix) return
if (e.target && e.target instanceof HTMLElement && e.target.hasAttribute('data-select-item')) {
e.preventDefault();
}
}}>
<Drawer.Trigger>Open</Drawer.Trigger>
<Drawer.Content class='h-[500px]'>
<Select.Root>
<Select.Trigger class="w-[180px]">
<Select.Value placeholder="Theme" />
</Select.Trigger>
<Select.Content>
<Select.Item value="light">Light</Select.Item>
<Select.Item value="dark">Dark</Select.Item>
<Select.Item value="system">System</Select.Item>
</Select.Content>
</Select.Root>
</Drawer.Content>
</Drawer.Root>
In my case <Drawer.Root closeOnOutsideClick={false}> does not help. I unfortunately had no time to dig into this issue.
Dialog doesn't work in a controlled way at all. When I close it, the open variable is still in a true state. It's a deal-breaker because I need to open dialogs from a different place. Is there a workaround?