How to Create a Responsive Navbar in React with TailwindCSS + DaisyUI
Jasser Mark Arioste
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.
- DrawerLayout
- 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
1
Install tailwindcss + daisyUI dependencies:
yarn add tailwindcss daisyui autoprefixer postcss
1
Initialize tailwind into the project
npx tailwindcss init -p
1
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")], }
1234567891011
Delete everything inside globals.css file and add tailwind utility classes.
#globals.css @tailwind base; @tailwind components; @tailwind utilities;
1234
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;
123456789101112131415161718192021222324
Run the project
yarn dev
1
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;
123456789101112131415161718192021222324252627282930313233
Use the DrawerLayout
component in app.tsx
... import DrawerLayout from "../components/DrawerLayout"; function MyApp({ Component, pageProps }: AppProps) { return ( <DrawerLayout> <Component {...pageProps} /> </DrawerLayout> ); } ...
1234567891011
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
1
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;
1234567891011121314151617181920212223242526272829303132333435363738394041
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;
1234567891011121314151617181920
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;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
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> ... } ...
1234567891011121314
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