The intent of this tutorial is to build a simple but extensible Modal Window component, with these key features:

  • responsive: full width on small devices, fixed width on bigger ones;
  • accepting every kind of content: html, images or others React components;
  • three way to close the modal: using the ESC key, clicking outside the window, clicking on a dedicated close “X” button.

To style our component, we’ll use JSS, a high performance CSS abstraction written in Javascript, that promise us some essential benefits:

  • scoped selectors with unique generated classname, no need to use ridiculous naming conventions like .block__elem--size-big (any reference to BEM is entirely coincidental ;-) )
  • one stylesheet for each component, mounted in runtime with the component itself;

All the info on JSS here: http://cssinjs.org/

Before starting.

If you’re in a hurry, you can play with the finished version of this tutorial in CodeSandbox: https://codesandbox.io/s/400lp1yjjw
Otherwise keep reading!

STEP 1: creation of modal component.

To create the modal we need two components:

  1. SimpleModal.js, the modal itself, with its stylesheet JSS file SimpleModalStyles.js
  2. SimpleModalLauncher.js: the parent component that displays the opener button or link, and manage the visibility of the modal with its own state.

SimpleModal.js: the rendered markup.

The html (JSX) markup is really simple, basically 3 elements: the main wrapper .modalOverlay contains the modal window .modalContent and the close button .closeButton. The modal window accepts {children} as prop, so we can assign to this component every kind of content.

Here a simulation of the modal with an image as child. You can easily change the appearance with some line of JSS (CSS).

SimpleModal.js: the close action.

As clarified at the beginning, this component wont manage it’s visibility, this means that by itself it will be always visible. We’ll manage its visibility from its parent component SimpleModalLauncher.js.

However this component contains some elements that if clicked, they are being able to close it. How is it possible to invoke the close action from within the component, if this action is declared outside the component? The answer is really simple, we will pass this action from outside as functional prop. The name of this prop will beonCloseRequest.

So, we need to invoke onCloseRequest function in these three events:

  1. clicking on the close button;
  2. pressing ESC key;
  3. clicking outside the modal window.

1. I need to close the modal clicking on close button

It’s very simple: we call the onCloseRequest function on onClick event on .closeButton.

Managing the other two events.

For the other events we need to to add two listener on component mounting:

  • window.addEventListener('keyup') for keyboard key press.
  • document.addEventListener('click') for mouse click;

Note: we’ll remove these listener on unmounting of the component to avoid duplicated events, see the example below.

2. I need to close the modal clicking on ESC keyboad key.

If 'keyup' event is invoked, the handleKeyUp() function checks which is the pressed key, and if it matches, it calls the onCloseRequest() function and removes the listener (27 is the code for ESC key).

3. I need to close the modal clicking outside the modal window.

If 'click' event is invoked, the handleOutsideClick() function checks which DOM element was clicked. If the clicked element (e.target) is different from the modal window (!this.modal.contains(e.target), it calls the onCloseRequest() function and removes the listener.

The complete component:

Let’s put all together to see the complete component file SimpleModal.js.

The style

Let’s look at the style file SimpleModalStyles.js.
We’ll use a flex-box to center in the page the modal window vertically and horizontally, adding a keyframe animation to show it with a fade-in effect.

As you can see, JSS is nothing but a javascript object, where you have to declare all the css properties you need, converting their name with a camelcase convention to avoid the use of javascript minus (-) operator, e.g.: background-color => backgroundColor. Simple, isn’t it?

STEP 2: creation of the launcher component.

Now that our modal is ready, we need to build the launcher component. This component will take care of:

  • displaying a button or a link that opens the modal;
  • managing the visibility of the modal with its own state.

SimpleModalLauncher.js: the rendered markup.

In this component we have 2 elements:

  1. the <button>: it invokes the handleToggleModal() function on onClick event, taking care of toggle visibility of the modal window.
  2. the <SimpleModal /> component: it renders the modal window only if the state variable showModal is true, passing the handleToggleModal() function as prop, allowing itself to manage the closing of the window.

SimpleModalLauncher.js: toggle the visibility of the modal window.

Before this component is mounted (see constructor statement below), we set the state variable showModal to false, to ensure that the initial visibility of the modal will be hidden.

The handleToggleModal() function manage the visibility of the modal simply swapping the showModal value from false to true and vice versa.

The complete component:

Below you cah see the complete fileSimpleModalLauncher.js

Putting all together.

Here you can see the complete example hosted on CodeSandbox. Please give the sandbox some time for loading.

Thanks for reading and please give me a “clap” if you liked this tutorial.

--

--