If you're building a website or web app, you're probably going to use icons to help communicate information to your users. But how do you organize all those icons and make sure they're consistent across your site?
In this post, we will explore the benefits of organizing icons in a Next.js site using a single file. By using this pattern, you can ensure consistency across your site and simplify the process of replacing icons. This pattern was inspired by Shadcn's Taxonomy repository, which is a great resource for Next.js app router examples, utilities, and patterns
Benefits of Organizing Icons
Before we dive into how to organize icons, let's first take a look at why it's important to do so. Here are a few benefits:
- Consistency: By organizing your icons in a single place, you ensure that they're consistent across your site. This helps to create a cohesive and professional look and feel.
- Simplicity: Organizing your icons makes it easier to replace them if needed. If you ever need to replace an icon, you'll only need to change a single line in a single file.
- Less Code: By importing a single component that has access to all icons, you require less code and fewer imports.
Now that we've established why it's important to organize your icons, let's take a look at how to do it.
Using a Single File for Icons
To organize our icons in a Next.js site, we're going to use a single file. This file will act as an abstraction layer that helps organize the icons in a single place and ensures that they're consistent across the site.
We can define our icons in a file called icons.tsx
. Here's an example:
import { Logo } from "@/config/logo"
import { GithubIcon } from "@/components/github-icon"
import {
X,
Copy,
ClipboardCheck,
ChevronLeft,
ChevronRight,
} from "lucide-react"
export const Icons = {
logo: Logo,
close: X,
copy: Copy,
chevronLeft: ChevronLeft,
chevronRight: ChevronRight,
gitHub: GithubIcon,
}
In this file, we're using Lucide for most of the icons, but we can also use custom icons like Logo
. All icons need to have the same interface, which in this example is only that they take a className
attribute.
Importing and Using Icons
Now that we have our icons organized in a single file, we can easily import and use them in other files.
Here's an example of how to import and use icons in a component:
import { Icons } from "@/components/icons"
<div>
<Icons.chevronLeft />
<Icons.chevronRight/>
</div>
By importing a single component, we have access to all icons, requiring less code and fewer imports.
Styling Icons with Tailwind
We can style our icons using Tailwind by using the className
attribute. Here's an example:
<Icons.chevronRight className="ml-2 h-4 w-4" />
This will add a margin to the left of the icon and set its height and width to 4 pixels.
Custom icons with image
In website design, custom icons are essential components to improve user experience and navigation. For custom icons, we can define a simple component like this one for any image in Next.js:
import logo from "@/public/favicon.svg"
import Image from "next/image"
export function Logo({ className = "h-6 w-6" }: { className?: string }) {
return (
<div className={className}>
<Image src={logo} alt="Logo" />
</div>
)
}
You can import that logo into Icons.tsx
as shown in the "Using a Single File for Icons" section.
Custom icons with SVG elements
Another way to create custom icons is to define them with svg code directly. In this case, we can define another component not only defines an icon, but also accepts LucideProps
making it even more compatible and customizable.
import { LucideProps } from "lucide-react"
export function GithubIcon({ ...props }: LucideProps) {
return (
<svg
aria-hidden="true"
focusable="false"
data-prefix="fab"
data-icon="github"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512"
{...props}
>
<path
fill="currentColor"
d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"
></path>
</svg>
)
}
You can import that logo into Icons.tsx
as shown in the Using a Single File for Icons" section.
Conclusion
In this article, we've covered the benefits of organizing icons in a Next.js site and the best way to do so using a single file and Tailwind for styling. By adopting this approach, you can ensure consistency, simplicity, and write less code.
If you're interested in learning more about Next.js and front-end development, be sure to check out our other articles on this blog.