Skip to main content
Post image
ยท 9 min read

Creating a Responsive React Navbar with Tailwind CSS

Introductionโ€‹

In this article, you'll see how to create responsive navbars in refine apps using the following CSS frameworks:

  1. Tailwind CSS
  2. Bootstrap

refine is a React-based framework for building internal tools using helper hooks, components, and providers. It provides amazing functionality for rapid development while ensuring extreme customizability. Everything is separate from your UI components and business logic in refine-based Apps. So, you can create UI components or code your flow. You can build admin panels, B2B applications, and dashboards using refine. But it's not limited to only these three scenarios.

Steps we'll cover:

Setting Up a refine Appโ€‹

We'll use superplate tool to create an empty React-based refine application.

npx superplate-cli -o refine-headless refine-navbar

Navigate to the refine-navbar folder and run npm run dev command.

app welcome page

We're using four resources posts, categories, users and events for the navigation purpose.

Create pages/posts folder

src/pages/posts/list.tsx
export const postList = () => <p className="post">Post Page</p>

Create pages/categories folder

src/pages/categories/list.tsx
export const categoryList = () => <p className="category">Category Page</p>

Create pages/users folder

src/pages/users/list.tsx
export const userList = () => <p className="user">User Page</p>

Create pages/events folder

src/pages/events/list.tsx
export const eventList = () => <p className="event">Event Page</p>

Create index.tsx file inside pages folder and add the following code to it.

src/pages/index.tsx
export * from "./posts";
export * from "./categories";
export * from "./users";
export * from "./events";

<Refine /> is the root component of the application. resources is a property of <Refine /> representing API Endpoints. The name property of every single resource should match one of the endpoints in your API.

resources use Page components to handle data and perform rendering. Page components are passed to resources as an array of objects.

Add these resources as a prop to the <Refine /> component:

src/App.tsx
import { Refine } from "@pankod/refine-core";
import React from "react";
import 'App.css'
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import { postList, categoryList, userList, eventList } from "pages";

const App: React.FC = () => {
return (
<Refine
routerProvider={routerProvider}
dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
resources={[{ name: "posts", list: postList }, { name: "categories", list: categoryList }, { name: "users", list: userList }, { name: "events", list: eventList }]}
/>
);
};

export default App;

refine works based on consuming data from APIs. You can consume Rest APIs using dataproviders. Data providers are refine components that make it possible to consume APIs and data services easily.

For this tutorial, we don't want consume API since we only want to focus navigating. The key point is dataProvider is required property. So we need give it anyway even if we don't want to consume the API. We use the fake Rest API available at https://api.fake-rest.refine.dev/.

Also, add following code inside App.css:

src/App.css
.post, .category, .user, .event {
text-align: center;
}

and import it inside App.tsx:

src/App.tsx
import 'App.css'
post page

Responsive Navbar with Tailwindโ€‹

Tailwind provides utility classes for creating components. We need to set up Tailwind CSS before starting to create a navbar with it.

Install tailwindcss and its peer dependencies using the following command:

npm i -D tailwindcss postcss autoprefixer

Then, init command to generate tailwind.config.js file.

npx tailwindcss init

Now, add paths of all template files in tailwind.config.js file:

tailwind.config.js
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
};

After that, add all @tailwind directives in src/index.css file:

src/index.css
@tailwind base;
@tailwind components;
@tailwind utilities;

Add "index.css" import inside the src/App.tsx file.

src/App.tsx
import 'index.css';

Now, We can use Tailwind to style our application.

We're using the following tailwind classes for creating a responsive navbar layout:

  • flex sets the display mode of container to flex.
  • flex-col changes the flex direction to column.
  • min-h-screen sets the minimum height of the element to min-height: 100vh.
  • container max-auto centers the container.
  • flex justify-between adds space between the flex items.
  • w-32 indicates that element has (32*4) 128px width.
  • ml-2 provides 8px margin to the element from left.
  • items-center pushes items to the center.
  • hidden sets element visibility to hidden.
  • md:flex displays flex when screen size is atleast medium.
  • md:hidden sets visibility to hidden when screen size is atleast medium.
  • text-green-500 changes text color to green with 500 font weight.
  • bg-white sets the background color of the element to white.

Layout component is used for the customization of refine app's layout. Create components/Layout.tsx file inside the src folder.

Create the following navbar using Tailwind CSS inside the Layout component. We can get all the menuItems from <Refine /> using useMenu() hook.

src/components/Layout.tsx
import { useMenu, LayoutProps } from "@pankod/refine-core";
import React from "react";

export const Layout: React.FC<LayoutProps> = ({ children }) => {

const { menuItems } = useMenu();

return (
<div className="flex min-h-screen flex-col">
<div className="mb-2 md:border-b py-2">
<div className="container mx-auto">
<div className="flex justify-between gap-2">
<img
className="w-32 ml-2"
src="https://refine.dev/img/refine_logo.png"
alt="Logo"
/>
<ul className="hidden md:flex">
{menuItems.map(({ name, route }) => (
<li key={name} className="float-left">
<a
className="flex cursor-pointer items-center gap-1 rounded-sm px-2 py-1 mt-2 capitalize decoration-indigo-500 decoration-2 underline-offset-1 transition duration-300 ease-in-out"
>
<span className="text-green-500">{name}</span>
</a>
</li>
))}
</ul>
</div>
</div>
</div>
<div className="bg-white">{children}</div>
</div>
);
};

This layout is passed as a prop to the <Refine /> component:

src/App.tsx
import { Layout } from "components/Layout";

const App: React.FC = () => {
return (
<Refine
...
Layout={Layout}
/>
);
};

The output of the above code is as follows:

post page

Let's make it mobile responsive by adding the mobile menu:

src/components/Layout.tsx
...
<div className="flex flex-col md:hidden border-b pl-3">
{menuItems.map(({ name, route }) => (
<a className="flex cursor-pointer items-center gap-1 rounded-sm px-2 py-1 mt-2 capitalize decoration-indigo-500 decoration-2 underline-offset-1 transition duration-300 ease-in-out"
>
<span className="text-green-500">{name}</span>
</a>
))}
</div>
...
post page

Add navigation functionality to the navbarโ€‹

We need to use Link component in the Layout.tsx will look like this:

src/components/Layout.tsx
import { useMenu, LayoutProps, useRouterContext } from "@pankod/refine-core";
import React from "react";

export const Layout: React.FC<LayoutProps> = ({ children }) => {

const { menuItems } = useMenu();
const { Link } = useRouterContext();

return (
<div className="flex min-h-screen flex-col">
<div className="mb-2 md:border-b py-2">
<div className="container mx-auto">
<div className="flex justify-between gap-2">
<img
className="w-32 ml-2"
src="https://refine.dev/img/refine_logo.png"
alt="Logo"
/>
<ul className="hidden md:flex">
{menuItems.map(({ name, route }) => (
<li key={name} className="float-left">
<Link
className="flex cursor-pointer items-center gap-1 rounded-sm px-2 py-1 mt-2 capitalize
decoration-indigo-500 decoration-2 underline-offset-1 transition duration-300 ease-in-out"
to={name}
>
<span className="text-green-500">{name}</span>
</Link>
//highlight-
</li>
))}
</ul>
</div>
</div>
</div>
<div className="bg-white">{children}</div>
</div>
);
};



Responsive Navbar with Bootstrapโ€‹

I've already walked you through setting up refine app. Now, we'll create navbar inside Layout.tsx and pass it as a prop to <Refine /> component.

First, install react-bootstrap:

npm install bootstrap react-bootstrap

react-bootstrap comes only with js. It doesn't have any CSS styles. That's why we installed bootstrap, which contains CSS.

App.tsx
import "bootstrap/dist/css/bootstrap.min.css"

Add navbar component inside the layout component and then create navbar items. We'll use refine logo for our navbar.

src/components/Layout.tsx
import { Navbar, Nav } from 'react-bootstrap'

<div>
<Navbar className="navbar-border" >
<img className="brand-image" src={"https://refine.dev/img/refine_logo.png"} width="100px" height="100px" />
<Nav>
{menuItems.map(({ name, label, icon, route }) => (
<Nav.Link className="nav-link">{name}</Nav.Link>
))}
</Nav>
</Navbar>
<div>{children}</div>
</div>

Add following CSS classes to App.css file:

src/App.css
.navbar-border {
border-bottom: 1px solid gray;
}

.nav-link {
margin-top: 5px;
text-transform: capitalize;
}

.brand-image {
margin: 0 15px !important;
}
post page

<Navbar.Toggle /> creates hamburger menu when screen size equals to minimum width set by expand attribute in Navbar component. You can do this in the following way:

src/components/Layout.tsx
import { useMenu, LayoutProps } from "@pankod/refine-core";
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css"
import { Navbar, Nav } from 'react-bootstrap'

export const Layout: React.FC<LayoutProps> = ({ children }) => {

const { menuItems } = useMenu();

return (
<div>
<Navbar className="navbar-border" expand="lg" >
<img className="brand-image" src={"https://refine.dev/img/refine_logo.png"} width="100px" height="100px" />
<Navbar.Toggle />
<Navbar.Collapse>
<Nav>
{menuItems.map(({ name, label, icon, route }) => (
<Nav.Link className="nav-link">{name}</Nav.Link>
))}
</Nav>
</Navbar.Collapse>
</Navbar>
<div>{children}</div>
</div>
);
};
post page


discord banner

Add React Router to Bootstrap Navbarโ€‹

Now, we're done with creating a responsive navbar using react-bootstrap.

Add <Link> component inside <Nav> like this:

src/components/Layout.tsx
import { useMenu, LayoutProps, useRouterContext } from "@pankod/refine-core";
import React from "react";

import "bootstrap/dist/css/bootstrap.min.css"
import { Navbar, Nav } from 'react-bootstrap'

export const Layout: React.FC<LayoutProps> = ({ children }) => {

const { menuItems } = useMenu();
const { Link } = useRouterContext();

return (
<div>
<Navbar className="navbar-border" expand="lg" >
<img className="brand-image" src={"https://refine.dev/img/refine_logo.png"} width="100px" height="100px" />
<Navbar.Toggle />
<Navbar.Collapse>
<Nav>
{menuItems.map(({ name, label, icon, route }) => (
<Link className="nav-link" to={name}>
<span>{name}</span>
</Link>
))}
</Nav>

</Navbar.Collapse>
</Navbar>
<div>{children}</div>
</div>
);
};

Conclusionโ€‹

Refine works with any custom design or UI framework. Every UI framework helps in creating layouts by providing utility classes or pre-designed components. In this article we implemented responsive navbar using Tailwind and Bootstrap. You can choose any framework and design components according to your needs.

Live StackBlitz Exampleโ€‹



Related Articles

Software Engineer
OTP Authentication with Supabase and Twilio in React
ยท 13 min read
Frontend developer
How to Create Dynamic Forms in React CRUD app with Ant Design
ยท 24 min read
Frontend Developer
Create Full Featured Admin Panel with React and Ant Design
ยท 13 min read

From Same Author

Software Engineer
CSS Grid vs Flexbox - A brief guide
ยท 8 min read
Software Engineer
Temporal API - A new approach to managing Date and Time in JS
ยท 7 min read