Exploring Chakra UI — Part 3: Building a responsive App Header and Sidebar with Chakra UI.

“Without requirements or design, programming is the art of adding bugs to an empty text file.” — Louis Srygley(ProgWisdom)

Amittras Pal
6 min readJan 23, 2022

This post is a part of the Exploring Chakra UI Series where we’re building a React app to search and explore TV shows and movies.

Today, we’ll be building the following:

Final result for today’s post.

TLDR; Find the entire file at the end of this post.

Alright, let’s get started with the UI of our application. Today, we’ll be setting up the Chakra UI in our application and build a responsive header and sidebar. You can follow the documentation to set up Chakra UI in the create-react app.

As in our case, we already have one provider in our index.js file (QueryClientProvider), we'll add another around it.

src/index.js

Passing the resetCSS prop as true resets the browser default CSS. Much like adding normalize.css in your application. That is it, we’re ready to use both QueryClient and Chakra in our application.

Planning the Layout

“Without requirements or design, programming is the art of adding bugs to an empty text file.”

Louis Srygley (ProgWisdom)

So let’s plan a bit of what we want our header to look like. We would have our application render different views corresponding to different screen sizes. Also we would want to have the least amount of code repeating for it.

Desktops design

We want to have a standard top bar that will stay fixed at the top of the screen while the rest of the body scrolls. On this bar, we want our App name at the left and on the right we will have our menus. These menus will be the categories that the user can explore (Movies, TV Shows, People etc.). Along with this, we want another button that will let the user toggle between dark and light mode of our app since that is a feature provided by Chakra UI out of the box.

Desktop Design Wireframe

Mobile Design

For smaller screens we will go with the hidden sidebar menu pattern. For this layout the only action on our top bar will be the color mode toggle button. The menu buttons will be hidden. A new button will be introduced to the left of out App Title which will open our sidebar from the left. Inside of this sidebar, we will have collapsible sections for the same menus we had on the desktop design.

Mobile Design Wireframe [with various states]

For both our designs, clicking the app title will lead the user back to the home page.

Menu Config File

Since we have two different layouts with exactly similar data, and quite similar behavior it makes a lot of sense to have a single place to store that configuration. From this configuration object, we can build out both layouts and not have to manipulate the actual JSX template if any changes are required later.

Let’s make a new file in the constants folder called menuConfig.js. From this file we will export a constant that will hold the configuration for our menu items in the UI.

src/constants/menuConfig.js

Here we are exporting an array called exploreRouterMenu, which holds objects for each menu item. Inside each one, we have a section id, its label, and the submenu items which is an array. Submenu items also consist of a label, the path that it routes to and and and icon.

PS: For icons, we’re using the react-icons package.

Great, now let’s get on with the Component. We’ll call this component AppHeader.jsx, and it will be placed in the Router folder where we put our RouterOutlet file earlier.

Building the App Header

Desktop View

src/components/Router/AppHeader.jsx

That’s a huge file. And it’ll get a little bigger. Let’s go over it closely. The only important bits to note here are the imports and how we’re using it. We have imported our menuConfig file here where we had kept our configuration for each menu item.

We’re using the Box component with a dnamic background color that’ll change according to our app’s color mode using the useColorModeValue hook. Inside, we have a Flex component which will hold our items.

In the first HStack, we have our heading, the app title, which is rendered as a Link from react-router using the as prop. This makes it clickable to navigate back to home from anywhere else. And we have an IconButton, which is conditionally rendered depending on the screen size. This will toggle our sidebar menu once we have that in place.

In the second HStack, we’re looping over out router menu, to render our menu items. The second HStack will not be visible on smaller devices, as we’ve put the following in the display prop:

<Box display={{ base: "none", md: "block" }}>
// menu items ...
</Box>

For each menu item, we’re rendering a Menu, and subsequently, for each submenu within, we’re rendering a MenuItem. Imagine writing each item manually within the JSX!!

Finally to the extreme right, we have our last IconButton, which toggles our application’s color mode. We’re using the useColorMode hook to render different icons conditionally and also using the function on each click.

If everything went well, we should have something like the following right now:

// Isert a GIF to show the behaviour.

Mobile View

The mobile view utilizes the Drawer component of the Chakra UI library.

Inside of the drawer component, we can place another list of items, but this time, utilizing the Accordion, instead of the menu to loop over our parent level items, and Accordion items will go into the submenu items.

Drawer component.

Let’s go over this bit a little. We are using the drawer component to create a sidebar which opens when the isOpen state is true. In our header section, we had a menu button which has display:{{md:none}} which makes it visible only on small devices. Additionally, for managing the state of the drawer, we’ll use the useDisclosure hook which will give us the open state as well the methods to open/close the drawer.

With that we have a responsive App Header and Sidebar Navigation for our application. This is quite dynamic too, since any changes in the route will have to be done in the routerMenu file only and not in the actual JSX going forward.

In my opinion though, it’s quite a large file as is, and it should be further broken up into smaller chunks for better maintainability. And that I am going to leave up to you.

The complete file.

Thank you for reading, I hope you found this useful. Stay tuned as we build this app further!! Let me know what your thoughts or optimizations for this component are.

--

--

Amittras Pal

An avid explorer of everything related to UI, and functional design in general. Front End developer always in search for something new.