nsarrazin's picture
nsarrazin HF Staff
feat: improved nav consistency on mobile (#1726)
e584c54 unverified
<script lang="ts">
import { createEventDispatcher, onDestroy, onMount } from "svelte";
import { cubicOut } from "svelte/easing";
import { fade, fly } from "svelte/transition";
import Portal from "./Portal.svelte";
import { browser } from "$app/environment";
import CarbonClose from "~icons/carbon/close";
interface Props {
width?: string;
closeButton?: boolean;
children?: import("svelte").Snippet;
}
let { width = "max-w-sm", children, closeButton = false }: Props = $props();
let backdropEl: HTMLDivElement | undefined = $state();
let modalEl: HTMLDivElement | undefined = $state();
const dispatch = createEventDispatcher<{ close: void }>();
function handleKeydown(event: KeyboardEvent) {
// close on ESC
if (event.key === "Escape") {
event.preventDefault();
dispatch("close");
}
}
function handleBackdropClick(event: MouseEvent) {
if (window?.getSelection()?.toString()) {
return;
}
if (event.target === backdropEl) {
dispatch("close");
}
}
onMount(() => {
document.getElementById("app")?.setAttribute("inert", "true");
modalEl?.focus();
});
onDestroy(() => {
if (!browser) return;
document.getElementById("app")?.removeAttribute("inert");
});
</script>
<Portal>
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<div
role="presentation"
tabindex="-1"
bind:this={backdropEl}
onclick={(e) => {
e.stopPropagation();
handleBackdropClick(e);
}}
transition:fade|local={{ easing: cubicOut, duration: 300 }}
class="fixed inset-0 z-40 flex items-center justify-center bg-black/80 backdrop-blur-sm dark:bg-black/50"
>
<div
role="dialog"
tabindex="-1"
bind:this={modalEl}
onkeydown={handleKeydown}
in:fly={{ y: 100 }}
class={[
"relative mx-auto max-h-[95dvh] max-w-[90dvw] overflow-y-auto overflow-x-hidden rounded-2xl bg-white shadow-2xl outline-none",
width,
]}
>
{#if closeButton}
<button class="absolute right-4 top-4 z-50" onclick={() => dispatch("close")}>
<CarbonClose class="size-6 text-gray-700" />
</button>
{/if}
{@render children?.()}
</div>
</div>
</Portal>