feat: add Modal component with open/close functionality and body overflow management

This commit is contained in:
Norbert Maciaszek
2025-11-17 21:17:28 +01:00
parent 06a129a560
commit c8a8b8df1b
2 changed files with 67 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import { fade, fly } from 'svelte/transition';
type Props = {
title: string;
children: Snippet;
isOpen: boolean;
footer?: Snippet;
onClose: () => void;
};
let { title, children, footer, onClose, isOpen }: Props = $props();
$effect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'auto';
}
return () => {
document.body.style.overflow = 'auto';
};
});
</script>
{#if isOpen}
<div
transition:fade={{ duration: 200 }}
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
>
<div
in:fly={{ y: 100 }}
class="max-h-[90vh] w-full max-w-2xl overflow-y-auto rounded-2xl bg-white text-gray-700 shadow-xl"
onclick={(e) => e.stopPropagation()}
>
<div
class="sticky top-0 flex items-center justify-between rounded-t-2xl border-b border-gray-200 bg-white px-6 py-4"
>
<h2 class="text-2xl font-semibold text-gray-800">{title}</h2>
<button
onclick={onClose}
class="text-2xl leading-none text-gray-400 transition-colors hover:text-gray-600"
>
×
</button>
</div>
<div class="p-6">{@render children()}</div>
{#if footer}
<div class="sticky bottom-0 rounded-b-2xl border-t border-gray-200 bg-white px-6 py-4">
{@render footer()}
</div>
{/if}
</div>
</div>
{/if}

View File

@@ -12,6 +12,16 @@ const config = {
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter()
},
compilerOptions: {
warningFilter: (warning) => {
const ignoreCodes = [
'a11y_no_static_element_interactions',
'a11y_click_events_have_key_events'
];
return !ignoreCodes.includes(warning.code);
}
}
};