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
Type a project name, in my case svelte-modal
Choose svelte as framework
Choose regular svelte
As instruction says, got to directory and run
npminstall
I am lazy and don't like writing a lot of CSS so for this I will usepicocss
So now run
npminstall @picocss/pico
Start up the dev server with
npm run dev
You should now see this in the browser.
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>
Let's go toapp.css
and just delete all the contents as it's not needed.
Now, lets import pico.css
gotomain.js
and add this
import'@picocss/pico/css/pico.min.css';
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;
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 thestores
folder 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'});
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>
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>
We now got this:
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>
Import the store so can use it.
import{modal}from'../lib/stores/';
Function that will close the modal by setting the store.
constclose=()=>($modal.open=false);
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();};
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}/>
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}>
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}
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)
For further actions, you may consider blocking this person and/orreporting abuse