Building CampaignHawk: Populating Modals (Part 7)
So now that we have our modal broken into segments, we need to populate those segments with inputs. In the first section we have a column of text inputs; in the second we have an image and a button; in the third we have a textarea; in the fourth we will have our submit or discard buttons.
Step 1: Input Fields
Fortunately this one is quite easy. Since we’re using flex and flex-direction as column, most of the work is already done for us.
That said, there is a lot of styling that needs to be done to our inputs to make them look right.
Let’s start by adding four input fields in volunteer-form-column-55:
<div className="volunteer-form-column-55">
<input type="text" placeholder="First name" />
<input type="text" placeholder="Last name" />
<input type="email" placeholder="Email" />
<input type="text" placeholder="Phone" />
</div>
Then we need to add a ton of styling to our input. I’ll go over what’s being done after the code block:
input {
background-color: transparent;
border: none;
border-bottom: 1px solid #888;
border-radius: 0;
outline: none;
height: 3rem;
width: 100%;
font-size: 1rem;
padding: 0;
box-shadow: none;
transition: all .3s;
&:focus {
border-bottom: 1px solid green;
box-shadow: 0 1px 0 0 green;
}
}
We’re changing the background color to transparent so it inherits the color of whatever it’s on top of. Then we’re removing the border, border radius, outline, padding, and box-shadow, and adding a new border to the bottom.
Then we set the height of the input to 3rem, with width 100%, font-size 1rem and transitioning everything.
The last thing we’re doing is changing the border on the bottom to green when someone focuses on the input field. This should really only be used for validation, which is something I’ll end up implementing much later on.
And that’s it for inputs.
Step 2: Image and Buttons
Now we need to add the profile image and a button to add a new profile picture. The first thing we’ll do is style the profile picture, then we’ll deal with the buttons. Let’s add an img with a wrapper div around it with the class profile-image-wrapper
<div className="volunteer-form-column-45">
<div className="profile-image-wrapper">
<img src="https://goo.gl/PoNcsv" />
</div>
</div>
We want the profile image to be circular and 150px by 150px. We also want the images to be centered within the circle. To do this, we need to add the following properties:
.profile-image-wrapper {
height: 150px;
width: 150px;
border-radius: 50%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
And that’s it for the image. Now we need to add styling to our buttons. We’re going to have two types of buttons, so we might as well style both of them at the same time. One type will have a class button and it will be solid and raise up when hovered over, and the other will have class button-flat and will be transparent until hovered over, at which point it flips colors.
Let’s first style the things they have in common, mostly pertaining to shape, size, borders, etc. This should all be pretty self-explanatory:
.button, .button-flat {
border: none;
border-radius: 2px;
display: inline-block;
outline: 0;
padding: 1rem 1.5rem;
text-transform: uppercase;
vertical-align: middle;
-webkit-tap-highlight-color: transparent;
}
Then we’ll style the regular button. We want to get rid of any text-decoration in case the default tries to underline our text. Then we want to set our font color to white and set our background to our $default-text-color. We also want to set the cursor to pointer so it feels clickable.
And lastly, on hover, we want the background to get lighter and we want a box-shadow to appear, giving the appearance that the item has lifted off of the page:
.button {
text-decoration: none;
color: white;
background-color: $default-text-color;
text-align: center;
letter-spacing: .5px;
transition: all 0.2s ease;
cursor: pointer;
&:hover {
background-color: lighten($default-text-color, 5%);
box-shadow: 2px 2px 2px 0px #888;
}
}
Our button-flat is going to be simpler. It has a transparent background until it’s hovered-over, at which point the background and text swap colors.
.button-flat {
box-shadow: none;
background-color: transparent;
color: $default-text-color;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
&:hover {
color: white;
background-color: $default-text-color;
}
}
Let’s go ahead and add a flat button to our modal:
<div className="volunteer-form-column-45">
<div className="profile-image-wrapper">
<img className="volunteer-profile-image" src="https://goo.gl/PoNcsv" />
</div>
<button className="button-flat">Upload Photo</button>
</div>
Unfortunately there are some spacing issues with the button and I’m too lazy to fix them the real way, so go ahead and add the following within volunteer-form-column-45 to fix the awkward button spacing:
button {
margin-top: 10px;
margin-bottom: -20px;
}
The last thing we want to do in this section is add a button to close the modal in the top right. Just below our “upload photo” button, add the following:
<button className="button-flat">Upload Photo</button>
<div className="close-modal-x">×</div>
Remember when we gave this container a position of relative for seemingly no reason? Well, this is the reason. We want to position the “x” absolutely in the top right, and an absolutely positioned div will look for the nearest container that is either relative or absolutely positioned. So if we didn’t set this container to relative, the “x” would be placed in the top right of the screen and not in the modal.
All we’re doing in this styling is positioning it to the top right, resizing, and setting cursor to pointer. Then it changes color to a lighter gray when hovered over and transitions in and out:
.close-modal-x {
position: absolute;
font-size: 1.5em;
top: 5px;
right: 0px;
cursor: pointer;
transition: all 0.1s ease;
&:hover {
color: #888;
}
}
Step 3: Textarea
Now we need to add a text area to the third section. Add the following to volunteer-form-column-100:
<textarea placeholder="Additional notes" />
Then within volunteer-form-column-100 in styles.scss add the code below to style our textarea. This will set the size and color and change the border to something more proper. We’re also adding some padding to the placeholder text so it doesn’t bump up against our border.
textarea {
background-color: white;
width: 93%;
height: 100%;
font-size: 1rem;
border-radius: 2px;
border: 1px solid #888;
&::-webkit-input-placeholder {
padding: 8px;
}
}
And that’s it for the textarea.
Step 4: More Buttons
The last thing we need to do is add a submit and a discard button to the bottom of the modal. First, add the buttons to the component:
<div className="submit-modal-buttons">
<button className="button">Submit</button>
<button className="button-flat">Discard</button>
</div>
We’ve already handled styling for the buttons, so this is basically done… except there are some spacing issues between the buttons and with the modal. We can handle the spacing between the buttons and with the right-side of the first button with margins, but that still leaves us with some weird spacing on the modal. Rather than do it the right way, I’m just going to use translateY and call it a day because it’s very performant and nobody else will know the difference.
.submit-modal-buttons {
padding: 0 20px;
transform: translateY(-15px);
display: flex;
flex-direction: row-reverse;
button {
&:first-child {
margin-right: 15px;
}
margin: 0 5px;
}
}
And now we have a completed modal.
Next Steps
The next thing we need to do is connect our modal content to our modal container. Then we need to add a few events to trigger the modal to hide or show with the proper content. We’ll also need a contact list modal to make sure we’re passing in the right content.
Sam Corcos is the lead developer and co-founder of Sightline Maps, the most intuitive platform for 3D printing topographical maps, as well as LearnPhoenix.io, an advanced tutorial site for building scaleable production apps with Phoenix and React.
Cumulative Time
Additional
- Building CampaignHawk: An open-source election canvassing app with Meteor and React (Part 1)
- File Structure and Packages (Part 2)
- Styling the Sidenav (Part 3)
- Styling Tooltips (Part 4)
- Connecting Tooltips with React (Part 5)
- Making Modals (Part 6)
- Populating Modals (Part 7)
- Connecting Modals with React (Part 8)
- Mapbox and Data (Part 9)
- Thinking about Data (Part 10)
- Mapbox and GeoJSON (Part 11)
- Mapbox.js and Meteor Data (Part 12)
- Popouts and Radio Buttons (Part 13)
- Radio Button Styling (Part 14)
- Triggering Functions with Radio Buttons (Part 15)
- Spacial Analysis Overview (Part 16)
- Clustering with Leaflet Markercluster (Part 17)
- Making a Precinct Data Layer (Part 18)
- Scaling Colors and Values with D3 (Part 19)
- Styling the Precinct Data Layer (Part 20)
- Toggling Data Layers (Part 21)
- Voter Filter Data Layer (Part 22)