Open tobiassern opened 8 months ago
https://github.com/huntabyte/vaul-svelte/assets/34103045/c08fb610-d3f0-43e1-bb01-035606ed0075
I can confirm same bug on Android Chrome.
As shown in the video, this is caused by some bug that resets style
attribute, when user enters value to input field that has bind:value
.
If users click out of the input field, styling is set to back to correct value.
Note: This can't be debugged or reproduced on browser dev tools. Must be done in real or virtual device. In the video I am using chrome "inspect remote devices" feature.
About severity: I agree with @tobiassern. This bug makes vaul-svelte totally unusable in any practical application where forms are used in the drawer/vaul.
System info:
Android: 13
Chrome: 124.0.6367.82
I tried to debug and fix this but couldn't even find out what might cause the bug. Feels like that I might not even be caused by this codebase but maybe something else like, svelte itself?
Only thing was able to identify is that everytime there is keydown event on input field with bind:value
set, the height property of drawer content
component is deleted/set to null/0px.
I am more than happy to try to fix this and make PR as debugging this with real device is kinda slow and painful.
So other people don't have to hassle with the debugging setup as I already have it done.
@huntabyte Any insight or idea about this? Where should I pay attention?
I think I found the solution. Could someone confirm if this fixes issue on your device?
Sidenote: I still get some styling issues and drawer jumping around but I think those bugs are not related to this. I have to do more debugging on those and probably open new issue.
The problem is caused by svelte reactivity. Everytime the binded variable bind:value
is updated by user input, it causes drawer to rerender, which then causes styling of the content
component to be resetted to its original state: position: fixed; bottom: 0px; left: 0px; right: 0px;
. This then hides the drawer behind the keyboard.
Wrap everything inside <Drawer.Content>
to new component. (Or atleast wrap <input>
element to its own component)
This prevents rerender from happening in the <Drawer>
. Rerender will still happen but only in the newly create component.
Example:
// hero.svelte
<Drawer.Root direction="bottom">
<Drawer.Trigger>Open Drawer 2</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay style="position: fixed; background: #00000040; inset: 0;" />
<Drawer.Content style="position: fixed; bottom: 0px; left: 0px; right: 0px; max-height: 96%;">
<div style="display: flex; flex-direction: column; gap: 10px; overflow: auto; padding: 1rem; background: #fff;">
<label> Without binded value
<input style="border: 1px green solid;" />
</label>
<label> With binded value
<input bind:value={value01} type="text" style="border: 2px red solid;" />
</label>
<!-- Here is the new component-->
<IsolatedInput />
</div>
</Drawer.Content>
<Drawer.Overlay />
</Drawer.Portal>
</Drawer.Root>
// isolated-input.svelte
<script lang="ts">
let value = "";
</script>
<label>
With isolated input component
<input bind:value={value} style="border: 1px solid gray;"/>
</label>
Describe the bug
Drawer disappear on Safari on iPhone when having an input inside the drawer with a bind:value. I have added a minimal reproduction for this.
The same issue appears when using shadcn-svelte and the drawer component.
Video showing the reproduction of this bug
https://github.com/huntabyte/vaul-svelte/assets/7224143/fcd1c668-3982-4925-9a5a-a9bd77401e73
Reproduction
Logs
No response
System Info
Severity
blocking all usage of vaul-svelte