Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Zoppatorsk
Zoppatorsk

Posted on

     

Simple, reusable Svelte Modal

Intro

So I noticedthis post about make a React Modal so i thought I would post my take on a Svelte Modal but with more features and more reusable.

So this for this Modal you can display it and change text and title by just setting the values of a store.

You will also be able to close the modal by clicking outside the modal-box, pressing Escape key or pressing the OK-button.

This is a small variation of a component I created for my submission to the redis hackathon where it was used to display error messages.

Step by step

Start with open a terminal/console

Go to the directory you want the project

Run

npm create vite@latest
Enter fullscreen modeExit fullscreen mode

Type a project name, in my case svelte-modal
Choose svelte as framework
Choose regular svelte
cmd

As instruction says, got to directory and run

npminstall
Enter fullscreen modeExit fullscreen mode

I am lazy and don't like writing a lot of CSS so for this I will usepicocss
So now run

npminstall @picocss/pico
Enter fullscreen modeExit fullscreen mode

Start up the dev server with

npm run dev
Enter fullscreen modeExit fullscreen mode

You should now see this in the browser.
starterpage

Let's get to code!
Go to the App.svelte file in the src folder. It contains the boilerplate for the page you just open in the browser.
Let's delete it all and replace with:

<script></script><main><button>Showmodal</button></main>
Enter fullscreen modeExit fullscreen mode

Let's go toapp.css and just delete all the contents as it's not needed.

Now, lets import pico.css
gotomain.jsand add this

import'@picocss/pico/css/pico.min.css';
Enter fullscreen modeExit fullscreen mode

in the top of the file.
Should now look like this:

import'@picocss/pico/css/pico.min.css';import'./app.css';importAppfrom'./App.svelte';constapp=newApp({target:document.getElementById('app'),});exportdefaultapp;
Enter fullscreen modeExit fullscreen mode

This modal will make use of a Svelte store. This store will hold the modals message, title and open/close state. By using a store means we will be able to trigger the showing of the modal from both Svelte components and regular Javascript code.

Let's create a new folder namedstores inside thesrc/lib folder. Create a new file in thestoresfolder namedindex.js

Put below code in there. If you want can set a default title and message to anything you want.

import{writable}from'svelte/store';exportconstmodal=writable({open:false,title:'Default title',message:'Default message'});
Enter fullscreen modeExit fullscreen mode

Store is now done and ready to be used.
Let's create the actual modal component. I usually create a components folder but for this example we will just put the file in the 'src/lib' folder.

Create a file namedModal.svelte

We put below code in the file, I will explain what it does a bit later.

<script>import{modal}from'../lib/stores/';constclose=()=>($modal.open=false);consthandle_keydown=(e)=>{if(e.key==='Escape')returnclose();};</script><svelte:windowon:keydown|once={handle_keydown}/><dialogopenon:click|self|preventDefault={close}><article><h3>{$modal.title}</h3><p>{$modal.message}</p><footer><buttonon:click|once={close}>OK</button></footer></article></dialog>
Enter fullscreen modeExit fullscreen mode

Let's go back toApp.svelte and wire things up so can try things out.

<script>importModalfrom'./lib/Modal.svelte';import{modal}from'./lib/stores/';</script><main>{#if$modal.open==true}<Modal/>{/if}<buttonon:click={()=>($modal.open=true)}>Showmodal</button></main>
Enter fullscreen modeExit fullscreen mode

We now got this:

modal_opener
And if pressing the button:

modal

So we import the Modal component and the modal store
We put the Modal component inside a Svelte-if. $modal references the store, so we only show the component if$modal.open is true.

We now have a modal that will be closed if click outside the modal, if press escape button on keyboard or if pressing the modal ok-button. It can be displayed from anywhere just importing the store and set open to true and in the same way you can set the title and message to display different things, for example error messages.

Now let's dig into the code that makes it work. Seeing to the functionality it provides there is a surprisingly small amount of code.

Here is theModal.svelte component again

<script>import{modal}from'../lib/stores/';constclose=()=>($modal.open=false);consthandle_keydown=(e)=>{if(e.key==='Escape')returnclose();};</script><svelte:windowon:keydown|once={handle_keydown}/><dialogopenon:click|self|preventDefault|once={close}><article><h3>{$modal.title}</h3><p>{$modal.message}</p><footer><buttonon:click|once={close}>OK</button></footer></article></dialog>
Enter fullscreen modeExit fullscreen mode

Import the store so can use it.

import{modal}from'../lib/stores/';
Enter fullscreen modeExit fullscreen mode

Function that will close the modal by setting the store.

constclose=()=>($modal.open=false);
Enter fullscreen modeExit fullscreen mode

Handler for keydown that will be shown a bit further down, only call the close() function when escape is pressed.

consthandle_keydown=(e)=>{if(e.key==='Escape')returnclose();};
Enter fullscreen modeExit fullscreen mode

In Svelte we can use the specialsvelte:window tag here we use it to bind an eventlistener for keydown to the window object, same as you would be able to do in regular javascript.
It uses the specialonce DOM modifier. By usingonce the listener will delete itself after running once, it can be useful in many situations

<svelte:windowon:keydown|once={handle_keydown}/>
Enter fullscreen modeExit fullscreen mode

In pico.css modals are easily created with element with an element inside. These are not special, just regular html-elemnts.

But let's analyze the below code. There is aon:click listener bound to the<dialog>element, so the semi-transparent area outside the modal-box. And it runs the close() function making the dialog close.

<dialogopenon:click|self|preventDefault|once={close}>
Enter fullscreen modeExit fullscreen mode

By usingself the on:click will only fire if we explicit click anywhere on the<dialog> element, i.e. the background. Without this the on:click would also fire if clicked anywhere on the modal-box. Handy feature :)

preventDefault should not be needed but I put it there cause i wanted to show it. It prevents default behavior and is the same as using the preventDefault() in an eventhandler, this can be handy if you for example want to define an inline function for the on:click handler, like:

on:submit|preventDefault={(e)=>dosomethingsimple}
Enter fullscreen modeExit fullscreen mode

Svelte is filled with smart stuff like this, check the documentation if your curios about other DOM modifiers.

Hope you learned something. This was tiring to write, I will stick to writing devlogs. ;)

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Sweden
  • Education
    Dalarna University
  • Work
    Student
  • Joined

More fromZoppatorsk

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp