Recently, I was working on a project that needed a wifi icon. It was for a React project. The idea was that you would be able to pass the status of the wifi icon as a prop and it would update the display.
The icon had 7 different states!
Then, just to add another level of fancy, when you're in searching mode, the icon animates.
So, how do you go about building something like this? First, things first...
Let's open a Terminal window I'm going to create a react project with Create React App:
Let's navigate into the directory that was created and run our application:
You'll notice that it automatically refreshes our browser. You should see a spinning React logo, indicating that our application is running properly
Within App.js let's modify some of the code. Within our paragraph tag, I'm going to change the text to read, "One wifi to rule them all."
I'm also going to delete our tag.
Let's change most of the code within App.css, too. Remove everything except what's inside the and class.
Let's change the background color to the nice, deep purple .
Next, let's create a Wifi component where we'll be doing most of our work.
Inside of the src directory, let's create a folder called Components. Let's create a file called Wifi.js.
Within our new file, I'm going to type and tab. I have a snippet running inside VS code that will use this shortcut to automatically stub out a functional React component.
Let's name our component Wifi.
Inside the return statement, let's just add the text Wifi so that we can make sure it's rendering correctly.
Whenever I create a React component, I always use named exports. Using a consistent approach makes everything so much easier. You don't have to try to remember which components have a default export and which ones have a named export because everything uses a named export. Consistency means less room for error.
Within App.js let's import our new component:
and display it inside our tag.
Save the files and you should see everything automatically reload within our browser:
Let's jump over to Figma where I mocked up what we'll be creating.
You'll see all the various wifi states stacked up on top of each other:
The easiest way to get this out of Figma and into code is to stack all these icons on top of each other, group them together, and export it as a single SVG.
Now, let's open the SVG image from Figma directly inside of VS Code.
It looks a little crazy with lots of numbers and letters.
If you don't have a lot of experience with SVGs, you can think of it like an Illustrator file for the web. It's a vector file, which means that the lines are text coordinates, based on math. Whereas, a raster image file is based on pixels. The good news about an SVG is that you can make it as big or as small as you'd like and change the color, all within code. Additionally, the file can be compressed and cached easily since it's text.
We're going to copy all of the SVG code and paste it directly within our Wifi component.
As soon as I hit Save, you'll notice that VS Code automatically reformats my code for me. That's because I have an extension installed within VS Code called Prettier. It is fabulous! I'll include a link to it within the description below.
Now, I'm going to clean up our SVG file. Most of the time when Illustrator or Sketch exports an SVG, they include a lot of extraneous code and metadata that isn't needed for display.
Now, I want to figure out what each refers to. I'm going to add a to each . We can turn them back on one by one to determine.
If we check the browser, you won't be able to see the icon.
Now, let's turn the first "back on"
Since it's showing us the first level, let's add an id of `and uncomment line.
Now, let's do the same with the next :
Let's add an and uncomment
Let's do the same thing for and .
This is for when the wifi is turned off. Let's add and uncomment
We can also assume the last one is our exclamation point for when there's an error. Add .
Next, remove all of the attributes.
Let's put a class name on our so that we can target our elements without worrying about it potentially conflicting with other items on the page.
Open up App.css. Here's the fun part where we can start styling everything.
By default, let's hide all our and then we'll turn them back "on" based on the state:
For a Poor Connection, let's add a class name of to the . The only element that we'll need to display is the , which we can target within our CSS:
We can do something similar for each of the remaining levels.
Level 2, a fair connection:
Level 3, good connection:
Level 4, excellent connection:
Our no wifi, will be similar. Let's add a class of to the and target it within our CSS:
The wifi error state will use a similar method, but we'll need to change the opacity of the levels, as well. Let's add a class of to .
Last state: search. This one is a little different because it's similar to an excellent wifi condition, except each of the bars needs to be animating.
Let's write the definition first:
I'm going to add a class name of to and then target each of the levels within CSS:
is fine, but for every level after, I'll delay the animation:
Obviously, you can speed up or slow down the animation by changing the property and the that has been defined within the property.
The only remaining piece is to make the class that we've been adding to the SVG dynamic so that we can change it on the fly via a react prop.
On line 3, where we declare the icon, change it to accept a prop of :
Now, on line 7, where lives, let's use an inline conditional that says, "if exists, display the class as and whatever is. Otherwise, just display the class as "
Awesome! If you're curious, you can check out all of [the code on GitHub.]()
Now, let's test it, just to make sure.
In App.js change our component to . Give it a save and refresh and it should appear as expected within the browser.
🎉 Technically, we're done! We did what we set out to do, but I believe we can take it a step further.
This looks great on a dark background. But, let's pretend for a minute that without app, we want it to appear on a light background. Right now, light and dark themes are all the rage. How do we do this without having to create an entirely different component?
The answer is really quite simple. — Only because SVGs and CSS are perfect for this type of implementation.
As I mentioned earlier, you can control the color of an SVG with CSS.
Let's set up some variables within CSS to hold our color values.
Now, if you're unfamiliar with variables within CSS, they're pretty easy. When you declare the value, it will look like this, with two in front of the name:
Then, when you want to call it, you use and put the name of the variable inside the parentheses. In our case, it might look something like this:
I told you, it was easy!
The cool part about CSS variables is they're scoped. Meaning, I could define a inside our class, but create a variable inside a class elsewhere. The two won't conflict.
Let's set the default, first. At the top of our App.css document, right below , let's add the following code (around line 15):
You'll notice that even though the is yellow, I didn't name it . That's because
I wanted the name to be more semantic. The icon might not always be the color "yellow". We want the names to tell us what they represent, not what they are.
Now, we can set the default, by adding the following line within our definition:
Then, just down to our definition. Update your code to the following:
If you're curious to see if these are really working, try changing the hex values in our variable definition:
Within App.js, in our tag, I'm going to add a class of
Within App.css, right below our definition, on line 16, I'm going to make our page have a light background with dark text:
Right below our variable definitions, around line 26, I'm going to override our variables:
Now, by simply adding or removing the class on the in our app and by changing the prop on our component, we have complete control over the icon and the colors being displayed.
Receive a weekly email of the Internet's best from articles, to tutorials, to pro tips.