Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawer disappear on iOS when using an input with bind:value #68

Open
tobiassern opened this issue Mar 17, 2024 · 3 comments
Open

Drawer disappear on iOS when using an input with bind:value #68

tobiassern opened this issue Mar 17, 2024 · 3 comments

Comments

@tobiassern
Copy link

tobiassern commented Mar 17, 2024

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

RPReplay_Final1710677900.MP4

Reproduction

  • Start a new Svelte kit Project
  • Install vaul -> npm install vaul svelte
  • Copy paste the snippet below into root +page.svelte
  • Run npm run dev --host and use the Network address to open the site on your iPhone
<script>
	import { Drawer } from 'vaul-svelte';

	let value = '';
</script>

<div data-vaul-drawer-wrapper style="background: #fff; height: 100dvh;">
	<h1>Welcome to SvelteKit</h1>
	<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

	<Drawer.Root shouldScaleBackground>
		<Drawer.Trigger>Open Drawer</Drawer.Trigger>
		<Drawer.Portal>
			<Drawer.Overlay style="position: fixed; background: #00000040; inset: 0;" />
			<Drawer.Content style="position: fixed; bottom: 0px; left: 0px; right: 0px;">
				<div style="border-radius: 25px 25px 0 0; background: #fff; padding: 12px;">
					<p>Content</p>
					<label>
                        Without binded value
						<input style="font-size: 16px;" />
					</label>
					<label>
						With binded value
						<input style="font-size: 16px;" bind:value />
					</label>
				</div>
			</Drawer.Content>
			<Drawer.Overlay />
		</Drawer.Portal>
	</Drawer.Root>
</div>

Logs

No response

System Info

iPhone 12 Pro
iOS: 17.3.1

Severity

blocking all usage of vaul-svelte

@devjume
Copy link

devjume commented Apr 30, 2024

2024-04-30.17-12-08.mp4

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

@devjume
Copy link

devjume commented Apr 30, 2024

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.

Screenshot from 2024-04-30 20-51-19

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?

@devjume
Copy link

devjume commented May 3, 2024

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.

Cause:

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.

Fix:

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>

Suggestion

  • I think this could be somehow prevented in the vault-svelte code, but I don't know wheter it's worth it as the following solution is quite simple.
  • Maybe example that showcases how to prevent this issue could be added to examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants