Building a modal with Lit Element
Let's build a simple modal dialog box with a nice look and interactive buttons
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:
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!