[Drawer] It isn't as expected in mobile with SvelteKit

Author: candidosalesCreated Mar 14, 2025Updated Jul 19, 2026
Labelstriage

Describe the bug

The drawer is not working as expected; I can't scroll inside, and the drawer is closing unpredictably. I don't know why. Do you have any assumptions?

My package.json

json
"devDependencies": {
		"@beyonk/svelte-google-analytics": "^2.6.4",
		"@playwright/test": "1.49.0",
		"@svelte-put/intersect": "^4.0.0",
		"@sveltejs/adapter-auto": "4.0.0",
		"@sveltejs/adapter-vercel": "5.6.3",
		"@sveltejs/kit": "2.19.0",
		"@sveltejs/vite-plugin-svelte": "^5.0.3",
		"@tailwindcss/typography": "^0.5.16",
		"@types/gtag.js": "^0.0.20",
		"@types/qs": "6.9.17",
		"@typescript-eslint/eslint-plugin": "8.25.0",
		"@typescript-eslint/parser": "8.25.0",
		"autoprefixer": "^10.4.20",
		"bits-ui": "1.3.11",
		"clsx": "^2.1.1",
		"eslint": "9.21.0",
		"eslint-config-prettier": "^10.1.1",
		"eslint-plugin-svelte": "^3.0.3",
		"lucide-svelte": "0.479.0",
		"postcss": "8.5.3",
		"prettier": "^3.5.3",
		"prettier-plugin-svelte": "3.3.3",
		"prettier-plugin-tailwindcss": "0.6.11",
		"sass": "1.83.0",
		"svelte": "5.23.0",
		"svelte-check": "4.1.5",
		"svelte-google-materialdesign-icons": "^1.0.5",
		"tailwind-merge": "^2.6.0",
		"tailwind-variants": "^0.3.0",
		"tailwindcss": "3.4.17",
		"tailwindcss-animate": "^1.0.7",
		"tslib": "^2.8.1",
		"typescript": "5.7.2",
		"vaul-svelte": "1.0.0-next.6",
		"vite": "6.2.1",
		"vitest": "3.0.6"
	},
	"type": "module",
	"dependencies": {
		"@candidosales/svelte-google-translate": "^0.0.15",
		"@fontsource/albert-sans": "5.2.5",
		"@googlemaps/js-api-loader": "^1.16.8",
		"@sentry/cli": "2.42.1",
		"@sentry/node": "9.5.0",
		"@sentry/svelte": "9.5.0",
		"@sentry/sveltekit": "9.5.0",
		"@sentry/tracing": "^7.120.3",
		"@types/google.maps": "3.58.1",
		"@vercel/speed-insights": "^1.2.0",
		"meilisearch": "0.49.0",
		"prettier-plugin-tailwindcss": "0.6.11",
		"qs": "^6.13.1",
		"svelte-french-toast": "^1.2.0",
		"svelte-local-storage-store": "^0.6.4",
		"svelte-markdown": "^0.4.1",
		"svelte-meta-tags": "^4.2.0",
		"svelte-skeleton": "^1.3.1",
		"tailwind-scrollbar-hide": "2.0.0"
	}

The implementation in +page.svelte.

svelte
<script lang="ts">
import Breadcrumb from '$lib/components/base/Breadcrumb.svelte';
import BannerCity from '$lib/components/BannerCity.svelte';
import MetaTagsSeo from '$lib/components/MetaTagsSeo.svelte';
import Link from '$lib/renderers/Link.svelte';
import SvelteMarkdown from 'svelte-markdown';
import CityContent from '$lib/components/CityContent.svelte';
import AdvertisingsPlace from '$lib/components/AdvertisingsPlace.svelte';
import { AdvertisingPlaceType } from '$lib/constants/advertising-places.js';
import { GoogleTranslate } from '@candidosales/svelte-google-translate';
import { GOOGLE_TRANSLATE_LANGUAGES } from '$lib/constants/locale.js';
import ModalGeolocation from '$lib/components/modals/ModalGeolocation.svelte';
import MenuNavigation from '$lib/components/base/MenuNavigation.svelte';
import * as Drawer from '$lib/components/ui/drawer';
import { ImageSize } from '$lib/constants/image-sizes.js';

const { data } = $props();
const renderers = {
	link: Link
};

let breadcrumbItems: Array<App.Breadcrumb> = $derived.by(() => {
	if (data.city) {
		return [
			{
				url: '/cidades',
				name: 'Cidades'
			},
			{
				url: '',
				name: data.city.name
			}
		];
	}
	return [];
});

let openDrawer = $state(false);

$effect(() => {
	if (!openDrawer) {
		setTimeout(() => {
			cleanBodyStyle();
		}, 1000);
	}

	return () => {
		cleanBodyStyle();
	};
});

const cleanBodyStyle = () => {
	document.body.style = '';
};
</script>

<Drawer.Root bind:open={openDrawer}>
	<main class="mx-auto mb-24 max-w-2xl bg-white px-4 py-4 lg:max-w-7xl lg:px-8">
		{#if data.city}
			<MetaTagsSeo
				title={data.city.name ?? ''}
				description={data.city.description ?? ''}
				images={data.city.images}
			/>
			<div class="mb-8">
				<Breadcrumb items={breadcrumbItems} />
			</div>
			<h1
				data-testid="page-title"
				class="page-title mb-4 text-2xl font-bold"
				style:--title="title-{data.city.slug}"
			>
				{data.city.name ?? ''}
			</h1>
			<div class="mb-8 grid grid-cols-12 gap-4">
				<div class="col-span-12 md:col-span-6">
					<BannerCity
						city={data.city}
						showTitle={false}
						showOverlay={false}
						imageSize={ImageSize.cityBanner}
					/>
				</div>
				<div class="col-span-12 md:col-span-6">
					<div class="prose-base mb-4 h-48 overflow-hidden">
						<SvelteMarkdown source={data?.city?.description ?? ''} renderers={renderers} />
					</div>
					<Drawer.Trigger
						class="w-full rounded-full border bg-white px-5 py-3 text-base font-bold text-emerald-700 transition-all duration-300 ease-in-out hover:bg-emerald-100 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 md:w-fit"
						>Leia mais</Drawer.Trigger
					>
					<Drawer.Content
						class="fixed bottom-0 left-0 right-0 mt-24 flex h-[96%] flex-col rounded-t-[10px] bg-white"
					>
						<button
							class="absolute right-4 top-4 rounded-full border bg-white p-2 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none"
							id="bits-166"
							data-dialog-close=""
							data-state="open"
							onclick={() => openDrawer = false}
							><!----><svg
								xmlns="http://www.w3.org/2000/svg"
								width="24"
								height="24"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
								stroke-linecap="round"
								stroke-linejoin="round"
								class="lucide-icon lucide lucide-x size-6"
								><!----><path d="M18 6 6 18"></path><!----><path d="m6 6 12 12"
								></path><!----><!----><!----></svg
							><!----> <span class="sr-only">Close</span><!---->
						</button>
						<div
							id="google-translate-element"
							class="prose mx-auto flex w-full max-w-lg flex-col overflow-auto rounded-t-[10px] px-8 py-8 lg:prose-lg md:px-0"
						>
							<Drawer.Title class="text-3xl">{data?.city?.name}</Drawer.Title>
							<SvelteMarkdown source={data?.city?.description ?? ''} renderers={renderers} />
							<GoogleTranslate options={{ includedLanguages: GOOGLE_TRANSLATE_LANGUAGES }} />

							<Drawer.Footer>
								<Drawer.Close
									class="w-full rounded-full border bg-white px-3 py-2 text-[0.875rem] font-bold text-emerald-700 transition-all duration-300 ease-in-out hover:bg-emerald-100 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2"
									>Fechar</Drawer.Close
								>
							</Drawer.Footer>
						</div>
					</Drawer.Content>
				</div>
			</div>
			{#if data.advertisings && data.advertisings.length > 0}
				<AdvertisingsPlace
					items={data.advertisings}
					place={AdvertisingPlaceType.homeAfterSubmenu}
				/>
			{/if}
			<CityContent data={data} />
			<ModalGeolocation />
			<MenuNavigation />
		{/if}
	</main>
</Drawer.Root>

Reproduction

You can check here: https://www.turismopiaui.com/cidades/joaquim-pires

Evidence

https://github.com/user-attachments/assets/548616ac-a682-4d71-8001-c50c4dc71d1d

Logs

bash

System Info

bash
System:
    OS: macOS 15.3.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 88.34 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.14.0 - ~/.nvm/versions/node/v22.14.0/bin/node
    Yarn: 4.3.1 - /opt/homebrew/bin/yarn
    npm: 10.9.2 - ~/.nvm/versions/node/v22.14.0/bin/npm
    pnpm: 10.2.1 - /opt/homebrew/bin/pnpm
    bun: 1.2.5 - ~/.bun/bin/bun
    Watchman: 2024.12.02.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 134.0.6998.89
    Safari: 18.3
  npmPackages:
    @sveltejs/kit: 2.19.0 => 2.19.0 
    bits-ui: 1.3.11 => 1.3.11 
    lucide-svelte: 0.479.0 => 0.479.0 
    svelte: 5.23.0 => 5.23.0 
    tailwindcss: 3.4.17 => 3.4.17 
    vaul-svelte: 1.0.0-next.6 => 1.0.0-next.6

Severity

annoyance