Best practice on creating a reusable Modal component in Svelte?

Viewed 370

I've been having trouble understanding the best way to create a reusable Modal component in Svelte. I want to have the Modal component where I can pass in other components easily, and in a scalable way. When I click the background, it should destroy the modal and the content inside.

I've created a REPL here with working version but would like to know if this is a convoluted way to achieve this: https://svelte.dev/repl/9180dd40e7304fc78d175cf4535a6423?version=3.38.2

This method works but I don't know if this is a suggested way (I'm new to both Svelte and component libraries).

App.js

<script>
    import Modal from './Modal.svelte'
    import Component1 from './Component1.svelte'
    import Component2 from './Component2.svelte'
    import {showModal} from './store.js'
    
    let showC1, showC2 = false;
    
    function toggleModal() {
        $showModal = !$showModal;
    }
    
    function toggleC1() {
        toggleModal();
        showC1 = !showC1;
    }
    
    function toggleC2() {
        toggleModal();
        showC2 = !showC2;}
</script>

<button on:click={toggleC1}>
    Toggle Component 1
</button>
<button on:click={toggleC2}>
    Toggle Component 2
</button>

<Component1 {showC1} on:click={toggleC1}  />
<Component2 {showC2} on:click={toggleC2} />

Modal.svelte

<script>
    import {showModal} from './store.js'
</script>

{#if $showModal}
<div on:click|self class='modal'>
    <div class='content'>
        <slot />
    </div>
</div>
{/if}

<style>
    .modal {
        background-color: rgba(0, 0, 0, 0.589);
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0.7;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .content {
        background-color: white;
        width: 20em;
        height: 20em;
    }
</style>

Component1.svelte

<script>
    import Modal from './Modal.svelte'
    export let showC1;
</script>

{#if showC1}
    <Modal on:click>
        <div>
            This is some content...
        </div>
        <button on:click>
            close
        </button>
    </Modal>
{/if}

Component2.svelte

<script>
    import Modal from './Modal.svelte'
    export let showC2;
</script>

{#if showC2}
    <Modal on:click>
        <div>
            ...And some more content
        </div>
        <button on:click>
            close
        </button>
    </Modal>
{/if}

store.js

import { writable } from "svelte/store";
export const showModal = writable(false);
1 Answers
Related