Skip to content

Commit

Permalink
Fix dom structure
Browse files Browse the repository at this point in the history
  • Loading branch information
atjn committed Dec 14, 2023
1 parent 32aa319 commit 3f5c798
Showing 1 changed file with 38 additions and 31 deletions.
69 changes: 38 additions & 31 deletions src/lib/components/modal/Modal.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,44 @@
<script lang="ts">
let dialogContainer: HTMLDialogElement | undefined;
export let modalCloseOnBackdrop: boolean = false;
let dialog: HTMLDialogElement | undefined;
/**
* Will allows the user to close the modal by clicking outside it.
*/
export let closeOnBackdrop: boolean = false;
/**
* Whether or not the modal is open or closed.
*/
export let show: boolean = false;
/**
* Ensures that the real DOM element is opened or closed when the svelte value changes.
*/
$: if (dialogContainer && show) {
dialogContainer.showModal();
$: if (dialog && show) {
dialog.showModal();
} else {
dialogContainer?.close();
dialog?.close();
}
/**
* Function for closing the current modal when the backdrop is clicked if
* ModalCloseOnBackdrop is true
* Closes the modal if the user clicks outside it
* Only works if ModalCloseOnBackdrop is true
*/
function closeModalOnBackdropClick() {
if (modalCloseOnBackdrop) {
function closeOnBackdropClick(event: MouseEvent) {
if (!closeOnBackdrop) return;
if (!dialog) {
throw new TypeError("Dialog should always be defined on mount");
}
/**
* TODO: Is there really no better way to check if the user clicked outside?
*/
const rect = dialog.getBoundingClientRect();
const clickIsOnDialog =
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width;
if (!clickIsOnDialog) {
show = false;
}
}
Expand All @@ -26,33 +47,19 @@
<!--TODO: Remove this when supported by Svelte-->
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
<dialog
bind:this={dialogContainer}
on:click|self={() => {
closeModalOnBackdropClick();
bind:this={dialog}
on:click|self={(event) => {
closeOnBackdropClick(event);
}}
>
<div class="box">
<slot />
</div>
<slot />
</dialog>

<style>
.box {
max-width: 100vw;
display: block;
position: fixed;
background-color: var(--modal-background-color);
z-index: 100;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
}
dialog {
max-width: 100vw;
width: 100vw;
max-height: 100vh;
height: 100vh;
background-color: rgba(0, 0, 0, 0.2);
background-color: var(--background-color);
}
dialog::backdrop {
background-color: var(--modal-background-color);
}
</style>

0 comments on commit 3f5c798

Please sign in to comment.