React Hustle

How to Create a Responsive Navbar in React with TailwindCSS + DaisyUI

JA

Jasser Mark Arioste

How to Create a Responsive Navbar in React with TailwindCSS + DaisyUI

In this tutorial, I’ll show you how to easily implement a responsive navbar layout in react using tailwindcss and DaisyUI.

What is TailwindCSS?

Tailwind CSS is an open source CSS framework. The main feature of this library is that, unlike other CSS frameworks like Bootstrap, it does not provide a series of predefined classes for elements such as buttons or tables. Instead, it creates a list of “utility” CSS classes that can be used to style each element by mixing and matching

— wikipedia.org

While tailwindcss can be used to create components in any imaginable way, the weakness is its low level classes sometimes makes it hard for beginners to create a consistent ui. And that’s where daisyUI comes in!

What is DaisyUI?

DaisyUI is a high-level component library for tailwindcss. While tailwindcss uses low level classes, DaisyUI uses high level classes to build components, some examples are btn , modal , dropdown , badge , etc. We can still use the low level classes provided by tailwind if we want to tweak the components from daisyUI. I think that this combination of low-level classes (tailwind) + high-level classes (daisyUI) makes building components a lot faster and results in a more maintainable code.

What is a Responsive Navbar Component?

A responsive navbar component is a navigation component that allows users to easily navigate to your website. It shows a horizontal navigation bar for desktop users showing the full menu. On mobile, it only shows a menu button, that pulls in a drawer. Sometimes it can be tricky to implement especially when you take into account mobile + desktop + html semantics. In this tutorial we’ll take a look on how to implement it using daisyUI. Okay with that out of the way, lets start!

There are 2 main components that we need to create for the responsive navbar component.

  1. DrawerLayout
  2. Navbar - Desktop and Mobile

We will create a next.js project to implement the component in this tutorial.

Step 0: Project Setup

Lets create a new project using next.js cli:

npx create-next-app --ts navbar-example && cd navbar-example

Install tailwindcss + daisyUI dependencies:

yarn add tailwindcss daisyui autoprefixer postcss

Initialize tailwind into the project

npx tailwindcss init -p

Modify the generated tailwindcss.config.js and add content array to tell tailwind where our components are located. and add daisyui as one of the plugins:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [require("daisyui")],
}

Delete everything inside globals.css file and add tailwind utility classes.

#globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Modify index.tsx to make use of tailwind classes

//index.tsx

import type { NextPage } from "next";
import Head from "next/head";

const Home: NextPage = () => {
  return (
    <div className="container mx-auto">
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1 className="text-2xl">
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>
      </main>
    </div>
  );
};

export default Home;

Run the project

yarn dev

Step 1: Implementing the DrawerLayout component

Creating the DrawerLayout component.

First we implement the drawer layout component before adding a navbar. The DrawerLayout component will be the outermost layout component that covers the inner layout component.

//components/DrawerLayout.tsx
import React from "react";

type Props = {
  children: React.ReactNode;
};

const DrawerLayout = ({ children }: Props) => {
  return (
    <div className="drawer">
      <input
        id="app-drawer"
        type="checkbox"
        className="drawer-toggle"
        checked
      />
      <div className="drawer-content flex flex-col">{children}</div>
      <div className="drawer-side">
        <label htmlFor="app-drawer" className="drawer-overlay"></label>
        <ul className="menu p-4 overflow-y-auto w-80 bg-base-100">
          <li>
            <a>Sidebar Item 1</a>
          </li>
          <li>
            <a>Sidebar Item 2</a>
          </li>
        </ul>
      </div>
    </div>
  );
};

export default DrawerLayout;

Use the DrawerLayout component in app.tsx

...
import DrawerLayout from "../components/DrawerLayout";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <DrawerLayout>
      <Component {...pageProps} />
    </DrawerLayout>
  );
}
...

Current output:

Notice that currently the DrawerComponent is always shown. That’s because we added a checked property in #app-drawer element. The #app-drawe r element will reflect the state of our DrawerComponent

Adding a toggle functionality for our DrawerComponent

I’d like to use SessionStorage to store the state for our DrawerComponent so first let’s install usehooks-ts package so that we can use the useSessionStorage custom hook. With this, we can toggle the state from anywhere in our application.

yarn add usehooks-ts@2.6.0

Adding the state:

//components/DrawerComponent.tsx
import React from "react";
import { useSessionStorage } from "usehooks-ts";

type Props = {
  children: React.ReactNode;
};

const DrawerLayout = ({ children }: Props) => {
  //initialize state here. we use a key and a default state
  const [open, setOpen] = useSessionStorage("drawer", false);
  return (
    <div className="drawer">
      <input
        id="app-drawer"
        type="checkbox"
        className="drawer-toggle"
        // checked property will now reflect our open state
        checked={open}
      />
      <div className="drawer-content flex flex-col">{children}</div>
      <div className="drawer-side">
        <label
          className="drawer-overlay"
          // add a onClick handler here to close the drawer
          onClick={() => setOpen(false)}
        ></label>
        <ul className="menu p-4 overflow-y-auto w-80 bg-base-100">
          <li>
            <a>Sidebar Item 1</a>
          </li>
          <li>
            <a>Sidebar Item 2</a>
          </li>
        </ul>
      </div>
    </div>
  );
};

export default DrawerLayout;

Toggling the component from inside our app

Inside index.tsx lets create a button and use useSessionStorage to toggle the state of our DrawerComponent :

//pages/index.tsx
import type { NextPage } from "next";
import { useSessionStorage } from "usehooks-ts";

const Home: NextPage = () => {
  const [, setOpen] = useSessionStorage("drawer", false);
  const toggleDrawer = () => setOpen((prev) => !prev);
  return (
    <div className="container mx-auto">
      <h1 className="text-2xl">
        Welcome to <a href="https://nextjs.org">Next.js!</a>
      </h1>
      <button className="btn" onClick={toggleDrawer}>
        Toggle Drawer
      </button>
    </div>
  );
};

export default Home;

Here’s the current output. Later on we’ll be toggling the drawer through the menu icon from inside the navbar component.

Step 2: Implementing the Navbar component

For this step we’ll now create a navbar component that shows the menu list. Let’s create a components/Navbar.tsx file and copy-paste the code below

//components/Navbar.tsx

import React from "react";
import { useSessionStorage } from "usehooks-ts";

const Navbar = () => {
  // toggle our drawer using useSessionStorage global state
  const [, setOpen] = useSessionStorage("drawer", false);
  const toggleDrawer = () => setOpen((prev) => !prev);
  return (
    <div className="w-full navbar bg-neutral">
      {/* Mobile menu button only shows for lg and below devices */}
      <div className="flex-none lg:hidden">
        <label className="btn btn-square btn-ghost" onClick={toggleDrawer}>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            className="inline-block w-6 h-6 stroke-current"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth="2"
              d="M4 6h16M4 12h16M4 18h16"
            ></path>
          </svg>
        </label>
      </div>
      {/* Website logo */}
      <div className="flex-1 px-2 mx-2">React Hustle</div>
      {/* Desktop menu only shows for lg and up devices */}
      <div className="flex-none hidden lg:block">
        <ul className="menu menu-horizontal">
          <li>
            <a>Home </a>
          </li>
          <li>
            <a>About</a>
          </li>
          <li>
            <a>Contact</a>
          </li>
        </ul>
      </div>
    </div>
  );
};

export default Navbar;

Lets use the Navbar inside the DrawerLayout component

//components/DrawerLayout.tsx

...
import Navbar from "./Navbar";
...
const DrawerLayout = ({ children }: Props) => {
      ...
      <div className="drawer-content flex flex-col">
        <Navbar />
        {children}
      </div>
      ...
}
...

That’s all let’s see the final output!

Final Step: Let’s see the output!

Mobile

Desktop

Conclusion

We’ve successfully created a responsive navbar component using tailwindcss + daisyUI and a utility package called usehooks-ts for react. For further learning, you may modify the navbar so that the menu items are dynamic. If you like this tutorial, please subscribe to our newsletter below and get amazing tutorials like this directly to your inbox!

Resources

Tailwind Docs - https://tailwindcss.com/docs/installation

DaisyUI Docs - https://daisyui.com/components/drawer/

usehooks-ts Docs - https://usehooks-ts.com/

Full code - https://github.com/jmarioste/navbar-example

Demo - https://navbar-example.vercel.app/

Share this post!

Related Posts

Disclaimer

This content may contain links to products, software and services. Please assume all such links are affiliate links which may result in my earning commissions and fees.
As an Amazon Associate, I earn from qualifying purchases. This means that whenever you buy a product on Amazon from a link on our site, we receive a small percentage of its price at no extra cost to you. This helps us continue to provide valuable content and reviews to you. Thank you for your support!
Donate to ReactHustle