Check out a free preview of the full Design Systems with React & Storybook course

The "Building a Modal" Lesson is part of the full, Design Systems with React & Storybook course featured in this preview video. Here's what you'd learn in this lesson:

Emma live codes a modal by creating a basic React component, and adds an icon as a stateless React component.


Transcript from the "Building a Modal" Lesson

>> Let's actually start building our modal. So our modal has our illustration, it has a header, it has a paragraph, our primary button, and then a close icon. For this, I'm just gonna use a basic React component, so SignUpModal. I am gonna make this have curly brackets with a return function, and you'll see why once we start animating.

So we have our modal wrapper, oops, that's gonna wrap our components. Now we need our illustration, so let's go and import that. So import Illustrations, that object we just created, from /assets. Also, while we're up here, let's import our PrimaryButton cuz we know we're gonna need that. And again, because we're already in the components folder, we can't just import from components.

So we actually have to import from /Buttons. So import PrimaryButton, from /Buttons. Okay, so we have our PrimaryButton we have our Illustrations being imported here. So we have our modal wrapper. The first thing that we see here is our illustration. So let's give it an image, give it a source.

This is gonna be Illustrations.SignUp, no exclamation, I'm just excited. For our alt tag.technically, this is not imperative to the user, right? This illustration doesn't really indicate anything that's of importance. We already have a title and we already have a paragraph. So I'm actually just gonna give us an alt of, you can add an explicit text like, sign up for an account.

But what we're gonna do is, we're gonna set aria-hidden="true". Cuz if I'm using a screen reader, I don't really care that this exists, it's not helping me in any way. Let's add our header, so we've got SignUpHeader, Sign Up. And then our text, SignUpText, so sign up today to get access.

And then lastly, our buttons, so PrimaryButton, sign up. Okay, so now we just have our modal. We've got our wrapper, our illustration, our header text, and primary button. The only thing we need is a close button here. So what you can do again from figma is export this icon as an SVG, export close icon.

Back inside of our assets, let's create one more folder called icons, And just drag in that SVG. Gonna rename you. And lastly, just add that to the export here. So, we did not use inline SVG for this illustration, which means that we actually just used it as a source attribute.

So I imported it and I just used it as source. That's not inline, that's being rendered as an image. For our close icon, we do wanna render this as an inline SVG. Because when I hover it, for example, maybe I wanna change the color, maybe I wanna manipulate the SVG dom contents itself.

And in that case, you need an inline. So what we're gonna do, let's create a wrapper around our close icon. So const, actually, what I'm gonna do, since this is gonna be inline SVG, I want to actually export this as a React component, let's do that. So inside of close-icon.svg, we'll just move this down so we have that SVG code.

So import React, and import styled. Let's create a wrapper. We're gonna need to set some styling on it, and that's why we're creating this wrapper. So const CloseIconWrapper, first of all, let me change this to a JavaScript file so that it's highlighting things, not an SVG. So we've got our wrapper, styled, and this is gonna be a styled SVG, so it's still semantic.

And inside of here, I just wanna set width to 100% and height to 100%. Now export const CloseIcon, it's gonna be a React component. This is simply gonna take our CloseIconWrapper, I'm gonna set aria-hidden="true". Why am I setting aria-hidden="true"? That's because our icon, we don't actually care about.

It's not giving our visually impaired users any information, this is gonna be a button element. So this is just the icon, and our users don't really care that it's a close icon. And inside of here, we can copy and paste this code. Now, that being said, I've already created a styled SVG, so we can actually just remove this SVG, I've already created it.

So it's just a path, it's just a simple path. So our CloseIcon is being exported. We need to add this to our exports in our index file, but this is a React component. So that's a simple export, so export * from /icons/CloseIcon. And now we can actually go and add this to our modal.

This is also coming from assets, so we can just import CloseIcon. And this needs to be a button because it's interactable. That's not a word, but you can interact with it. So I'm going to come down here, and I'm gonna create one more component called const CloseModalButton, it's gonna be a button.

We're gonna set some style, so cursor, I want it to be pointer, I don't want it to have a background, I wanna remove the border as well. So we had set position relative on this modal wrapper, and that's because what I want to do is, I wanna position this element in the top right corner.

And if you wanna absolutely position something against a parent, the parent needs position relative. And the item needs a position of absolute. So that's what we're doing here, position absolute. I want it to be at 40 pixels to the right, and I want it to be at 40 pixels to the top, so 40, 40.

And then I'm just gonna set width and height to 24 pixels. And lastly, just no padding, I don't need any padding. And what we can do now is just kind of render this under as the last thing inside of our modal wrapper, so CloseModalButton. I'm gonna give this an aria label because, again, there's no explicit text, so aria-label="Close Modal".

And inside is gonna be our CloseIcon, self closing tag. Okay, so we created this modal button. We have this icon, it's being exported as a stateless React component. And we're just including this here as being absolutely positioned against this modal parent. So if I go back to my primary index file and source, what we can do now, let's get rid of these buttons.

And also, now that we have an index file and components, I can actually just remove this button import, just import directly from components. But remember how I said this default export, this is not gonna work. So one last thing, let's make our primary button a named export, okay, so export const PrimaryButton.

We'll remove this default export at the bottom. Imports are important, letters are important. Can't export CloseIcon, one second. Export const CloseIcon, that is working. export * from /icons. This is a different error, at least, can't resolve styled. So this is in components. Did I spell something wrong, yeah.

Okay, so now that we have named primary button, named import, and named export, let's remove these and let's just import our SignUpModal from components. So now we can remove these, SignUpModal, And there we go. This is a little a little funky, this position absolute. Let's see what's going on, and then it looks like it's working decently well.

This is why, I didn't add a unit to my top. So if I go back to Modals.js, 40, here we go, forgot my unit, and now it's being positioned absolute.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now