Building a modal with Lit Element

Let's build a simple modal dialog box with a nice look and interactive buttons

jevisan
CodeX

--

Photo by Halacious on Unsplash

Notice: although this particular tutorial will extend an existing project, it’ll set the bases for building a stand alone modal that can be incorporated anywhere in a web component based application.

In a previous tutorial, we built a tic tac toe game with the light weight Javascript library Lit Element. Now, the game over screen was a little dull and a little disruptive with the component’s aesthetic. In this tutorial, we’ll fix that adding a nice modal that’ll display the game messages and that can be integrated within other components and pages that support web components. All right, let’s get to it.

Component base structure and properties

First of all, let’s remember a bit of project structure. As you remember, there’s the src folder that contains the source code for the main TicTacToe.js component. component. And, inside it, we also defined another component for each individual cell. Now, inside this folder we’re gonna generate our modal component.

./
├── tic-tac-toe/
│ ├── ...
│ ├── src/
│ │ ├── TicTacToe.js
│ │ ├── TicTacToeCell.js
│ │ └── ModalDialog.js
│ ├── ...

Here I’ve named mine Modaldialog but feel free to name it however you like. Now let us fill this file with the following code:

As you may notice, the structure of this file is similar to the other components. We import the LitElement library, along with the html and css functions to define our template and styles. We’re also importing a function called classMap that’s part of the litElement bundle. This function will allow us to map the component’s properties into css classes.

And speaking of properties, here we’ve also defined some that will define our modal. First the open property is a boolean that will tell the component to either show or remain hidden. Then the title and text properties will set the contents to be displayed in the modal. The clickAction is a text to be displayed in the modal's button. Last thing to notice here is the constructor method, that initialize the class with some initial values, in this case the open property will be set as false to hide the component when it's first instantiated in the page.

Styles and functionality

Now, the whole point of making a modal is to have a nice looking component to display messages in. We can't accomplish this without some styles, so let's define them along with the render method and the functionality. Please add these methods to out component class:

We won't enter in details of the css but let us just review briefly the most important bits. The :host just define a nice font for our modal. Now we have a wrapper div that'll contain everything and will center the component in the middle of the screen. Here is important to notice that this wrapper is always relative to it's parent, that can be another component, so this whole modal will be centered relative to its container. Next we have an overlay div that wont contain anything, its sole purpose is to set a little opacity on the background of the modal and to disable the modal when it's clicked on. Finally the dialog is the modal per se, and we define a nice styling for it alongside with the style of the button.

Now, we have the render method that defines the template for the component. All the html contents for the component are set here.

Let's talk for a sec about the classMap function, mentioned at the beginning. It receives a Javascript object with key-value pairs to set or unset classes based on the truthy values. In this case, it will always set the class wrapper as it's always receiving a true value for this key, and the open class will be set according to the open property of the component. In short, the classes in this div will be class="wrapper open" when the open prop is true, and just class="wrapper" when its false.

Then, the close method will set the open prop to false, and it is called by the event that'll trigger when you click on the overlay. It'll also be called at the event of the button click that'll be managed by the handleClick method. This handleClick method will also dispatch an event to the component's parent to let it know the button was just pressed. This will allow us to connect the button click in the modal with some custom routine in the parent, the game in this case.

Integrating with the app

Now it's all coming together! Let's integrate this with the complete app. Now although this tutorial is particularly focused on the tic tac toe game built in a previous one, the event triggering and listening can be extrapolated to any other implementation.

Now let us return to the TicTacToe.js file, that is, the game itself.

First at the top of the file, let's import the ModalDialog component. Now, as the app is defined, we tied everything up in the constructor to listen to the player-win and tie events, that are triggered when checking for the victory or tie conditions. In the event listener, we simply define an arrow function to set all the values for the modal component, particularly the open property will be set to true to display the modal. Finally, in the game render method, we'll just add a <modal-dialog> html element with a listener to its button-click event. This event is bind to the resetGame method, which only calls to the resetTiles and initGame. This last one was used in the previous tutorial to initialize the game's variables and board state, while the resetTiles will just reset all the symbols in the board cells to display no symbols.

Final results

Finally, this is how both cases for this modal will look like:

The modal to indicate player victory
Modal to indicate tie

Conclusion

We have built a Modal dialog component that's agnostic to the context so it can be add on any web component-based application. This modal has a nice styling and configurable title and text to display, as well as a button to trigger events in parent components to add functionality to our page.

I hope you enjoyed this little tutorial!

--

--

jevisan
CodeX
Writer for

Frontend developer, Python enthusiast, music lover and videogame geek