Building CampaignHawk: Styling the Sidenav (Part 3)

So now that the wireframes are done and the basic file structure is in place, it’s time to start building out the user interface (UI). By the end of this, we should have a functional sidenav with icons.

We really only need one additional component to accomplish this task, though we might break this into two components later on.

Part 1: Sidenav Component

The sidenav will be a separate component within Map.jsx:

Sidenav = React.createClass({
render() {
return (
<nav className="sidenav">
icons
</nav>
)
}
})

Now Sidenav needs to be rendered within Map:

...
return (
<div>
<h1>This is where the map goes</h1>
<Sidenav />
</div>

)

Part 2: Styling

I’m going to start by resetting the html defaults on a few elements. Within styles.scss:

body, p, h1, h2, h3, h4, ul, li  {
padding: 0;
margin: 0;
}

The Sidenav will be 60 pixels wide, absolutely positioned to the left of the screen, and always the same height as the screen. I also want it slightly off-white with a shadow on the right to give the app some depth. Within styles.scss:

.sidenav {
position: absolute;
top: 0;
left: 0;
box-shadow: 0px 0px 15px 0px #888;
background-color: rgba(250,250,250,1);
width: 60px;
height: 100vh;
}

At this point, the app looks like the image below. You’ll notice that the sidenav covers part of the sentence we put in the Map component. We’ll deal with that later; we’re focusing on the sidenav for now.

Note that the word “This” in Map component is covered by the sidenav.

Part 3: Icons

We’re going to use Fontawesome for all of our icons. We will need to install the proper package:

$ meteor add fortawesome:fontawesome

Since we might want to change the list of tools later, we’re going to make a list of the classes that represent each of the icons and generate the list of icons dynamically:

render() {
let iconList = [
"fa fa-database",
"fa fa-user-plus",
"fa fa-users",
"fa fa-bicycle",
"fa fa-list-ul",
"fa fa-lightbulb-o",
"fa fa-list-ol",
"fa fa-line-chart",
"fa fa-cog"
]
...

Now that we have our list of classes, we want to generate a list of the icons we want in our sidenav:

let list = iconList.map((item) => {
return (
<li key={item} className="sidenav-list-item">
<i className={item}></i>
</li>
)
})

And finally let’s change what we return in our render function so we show this new list as an unordered list:

return (
<nav className="sidenav">
<ul className="sidenav-list">
{list}
</ul>
</nav>
)

The app now looks like the image below. Almost everything else can be handled by styles.

There are actually bullets to the left of each list item, but because we removed the padding, you can’t see them.

I’m a fan of nesting styles to avoid messing with other styles in a different part of the app. I’m also going to use flexbox for aligning items because it’s the future.

I want the first item in the list to be padded on the top by 20 pixels so it doesn’t feel constrained. I also want to get rid of the default bullets that come with an unordered list. You can’t see them in the image above because we removed the padding, but trust me, they’re there.

.sidenav-list {
&:first-child {
padding-top: 20px;
}
list-style-type: none;

...

Then we need to style the list items. We’re going to set the cursor to pointer, which gives you that nice pointer finger and makes React happier on mobile, set the padding between items to 20 pixels, display as flex and justify-content to the center. We’re also going to boost the font-size to 1.6em and change the opacity to 0.54 to make them gray.

.sidenav-list-item {
cursor: pointer;
padding: 20px;
display: flex;
opacity: 0.54;
font-size: 1.6em;
justify-content: center;
}

When you’ve gone through these steps, the sidenav should look like the image below.

Part 4: Fonts

The last thing to do is change the fonts into something decent. I’m not a big fonts guy, but I know a bad font when I see one. We’ll just use Open Sans, which has become a standard thanks to Google. At the top of styles.scss:

@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);
$font-stack: 'Open Sans', sans-serif;

And within our html reset, make the $font-stack we just created the default font-family:

body, p, h1, h2, h3, h4, ul, li {
font-family: $font-stack;
...

And that should do it for our sidenav.

Next Steps

The next thing we need to do is set up a hover-over tooltip for each of the toolbar items. We’ll do that with a new component called SidenavTooltip. We’ll also need to change the iconList items into objects that with a description.


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

Since one of the selling points of Meteor is that it’s really fast to develop prototypes, I’ve been tracking my hours with RescueTime to see how long I spend on this project. I’m going to start publishing charts to keep track:

As you can see, at this point in the project I’ve spent more time writing about the project than I have actually making the project…

Additional