user18175092
user18175092

Reputation:

Icons for Nextjs and tailwind layout

I was looking through a tutorial located here: https://daily-dev-tips.com/posts/creating-a-sidebar-layout-in-nextjs-with-tailwind/ about a sidebar.

I was wondering if there was a way to use Icons (like heroicons) within the layout file. referenced below:

import Link from "next/link";
import { useRouter } from "next/router";
import HomeIcon from "@heroicons/react/outline";

export default function Layout({ children }) {
  const router = useRouter();

  const menuItems = [
    {
      href: "/",
      title: "Home",
    },
    {
      href: "/about",
      title: "About",
    },
    {
      href: "/contact",
      title: "Contact",
    },
  ];

  return (
    <div className="min-h-screen flex flex-col">
      <header className="bg-white sticky top-0 h-14 flex justify-center items-center font-semibold uppercase">
        Next.js sidebar menu
      </header>
      <div className="flex flex-col md:flex-row flex-1">
        <aside className="bg-black w-full md:w-60">
          <nav>
            <ul>
              {menuItems.map(({ href, title }) => (
                <li className="m-2" key={title}>
                  <Link href={href}>
                    <a
                      className={`flex p-2 bg-black text-white rounded hover:bg-red-600 cursor-pointer ${
                        router.asPath === href && "bg-black text-red-600"
                      }`}
                    >
                      {title}
                    </a>
                  </Link>
                </li>
              ))}
            </ul>
          </nav>
        </aside>
        <main className="flex-1">{children}</main>
      </div>
    </div>
  );
}

I tried

  href: "/",
  title: "Home",
  icon: <HomeIcon />,

but then I wasn't sure exactly how to incorporate it. Any ideas?

Upvotes: 3

Views: 7556

Answers (3)

MagnusEffect
MagnusEffect

Reputation: 3925

One of the most preferred icons utility is React-icons. You can simply install the npm package from here.

And you can view & search icons from here.

In the code you can use it like this, suppose you want to use AiFillHome icon, then just import it in the file like this,

import {AiFillHome} from "react-icons/ai";

And use it like

<AiFillHome />

You can check the props in the mentioned docs.

Upvotes: -1

yohanes
yohanes

Reputation: 2675

First, import as below:

import { ChatIcon, HomeIcon, PhoneIcon } from "@heroicons/react/outline";

Then put the icons in menu items:

const menuItems = [
    {
      href: "/",
      title: "Homepage",
      icon: <HomeIcon className="h-4 w-4 mx-2" />,
    },
    {
      href: "/about",
      title: "About",
      icon: <ChatIcon className="h-4 w-4 mx-2" />,
    },
    {
      href: "/contact",
      title: "Contact",
      icon: <PhoneIcon className="h-4 w-4 mx-2" />,
    },
  ];

then, update your list by adding icon here {menuItems.map(({ href, title, icon }) and at the achor {icon} {title}

   {menuItems.map(({ href, title, icon }) => (
      <li className="m-2" key={title}>
         <Link href={href}>
             <a className={`inline-flex items-center w-full p-2 bg-fuchsia-200 rounded hover:bg-fuchsia-400 cursor-pointer ${router.asPath === href && "bg-fuchsia-600 text-white"}`}
             >
                {icon} {title}
             </a>
          </Link>
       </li>
    ))}

and update the Link anchor class flex become inline-flex items-center w-full

Finally, the complete layout.js file is as follows:

import Link from "next/link";
import { useRouter } from "next/router";
import { ChatIcon, HomeIcon, PhoneIcon } from "@heroicons/react/outline";

export default function Layout({ children }) {
  const router = useRouter();

  const menuItems = [
    {
      href: "/",
      title: "Homepage",
      icon: <HomeIcon className="h-4 w-4 mx-2" />,
    },
    {
      href: "/about",
      title: "About",
      icon: <ChatIcon className="h-4 w-4 mx-2" />,
    },
    {
      href: "/contact",
      title: "Contact",
      icon: <PhoneIcon className="h-4 w-4 mx-2" />,
    },
  ];

  return (
    <div className="min-h-screen flex flex-col">
      <header className="bg-purple-200 sticky top-0 h-14 flex justify-center items-center font-semibold uppercase">
        Next.js sidebar menu
      </header>
      <div className="flex flex-col md:flex-row flex-1">
        <aside className="bg-fuchsia-100 w-full md:w-60">
          <nav>
            <ul>
              {menuItems.map(({ href, title, icon }) => (
                <li className="m-2" key={title}>
                  <Link href={href}>
                    <a
                      className={`inline-flex items-center w-full p-2 bg-fuchsia-200 rounded hover:bg-fuchsia-400 cursor-pointer ${
                        router.asPath === href && "bg-fuchsia-600 text-white"
                      }`}
                    >
                      {icon} {title}
                    </a>
                  </Link>
                </li>
              ))}
            </ul>
          </nav>
        </aside>
        <main className="flex-1">{children}</main>
      </div>
    </div>
  );
}

Upvotes: 2

saleh shokouhi
saleh shokouhi

Reputation: 545

i suggest change the array object like this.

sample https://codesandbox.io/s/epic-stitch-h5gn89?file=/src/App.js

 {
  href: "/",
  title: "Home",
  icon: "HomeIcon",
  }

and use this component i found on this link.(i changed some of it) https://github.com/tailwindlabs/heroicons/issues/278#issuecomment-851594776

in this solution dont need to import eche icon one by one

DynamicHeroIcon.tsx

// DynamicHeroIcon.tsx
// Simple Dynamic HeroIcons Component for React (typescript / tsx)
// by: Mike Summerfeldt (IT-MikeS - https://github.com/IT-MikeS)

import { FC } from "react";
import * as HIcons from "@heroicons/react/outline";

const DynamicHeroIcon: FC<{ icon: string } & React.HTMLProps<HTMLElement>> = (
  props
) => {
  const { ...icons } = HIcons;
  const Fprops = { ...props };
  delete Fprops.icon;
  // @ts-ignore
  const TheIcon: JSX.Element = icons[props.icon];

  return (
    <>
      {/* @ts-ignore */}
      <TheIcon {...Fprops} aria-hidden="true" />
    </>
  );
};

export default DynamicHeroIcon;

and use it like this.

import DynamicHeroIcon from "./components/DynamicHeroIcon";

<DynamicHeroIcon style={{ width: "52px" }} icon={"HomeIcon"} />



  {list.map((item) => {
       return <DynamicHeroIcon style={{ width: "52px" }} icon={item.icon} />;
      })}

Upvotes: 1

Related Questions