Introduction

Overview
Styling - TailwindCSS, Conditional styles or the asChild Parameter
Shadcn & Tweakcn - The component library from tomorrow
Dark and Light Mode - The most important functionality in web design
Lucide react - The easiest way to implement icons

Styling

Tailwind CSS

Tailwind is a convenient way to make use of predefined classes that help me create good looking UIs. While it takes some time to get used to all this classes, after some time they will make development way faster - finally no headache wich dealing with plain css anymore.

There are some very useful VS Code Extensions for Tailwind.

ExtensionDescription
HeadwindSorts the classes in the same order
Tailwind CSS IntelliSenseVS Code auto completion and suggestions
Tailwind DocumentationAccess the official Documentation inside VS Code
Tailwind FoldFold the classes, to make the files easier to view

Here I list some interesting CSS classes so I hopefully will remember them.

ClassNameDescription
truncateBreaks the sentence when to long…
line-clamp-3Max 3 lines of text before truncated…

Conditional styles

One way of using conditional styling is with the tool clsx

npm install --save clsx

asChild

A convenient way to pass a certain style of element A to element B is with the asChild parameter. This parameter will pass down the style to is child without the parent element to be rendered.

<Button asChild variant="outline">
	<Link href={ticketsPath()}>Go to Tickets</Link>
</Button>

Alternative I could also pass to the child element this className to directly access the style of the button without having to wrap the link.

className={buttonVariants({ variant: "outline"}

Shadcn & Tweakcn

The component library Shadcn

Creating every component dosen’t just take a lot of time, but often it also looks bad and the application ends up inconsistent. Because of that I like to use tools like shadcn wich delivers good looking components out of the box. Even better since these components can still be customized with Tailwind CSS since they themself were build with Tailwind CSS.

For setting up shadcn I only need to run inside my project this command:

npx shadcn@latest init

I will be prompted wich base color I like, wich I often answer with Neutral, since I’m gonna change the theme anyway later with tweakcn.

Shadcn will also add new files to the project structure and updated the global.css file

/components.json
/src/lib/utils.ts
/src/components/ui => once a component is added

Adding components In order to add now shadcn components, I only need to look them up in the documentation and run the documented command.

This is the example command for a shadcn button

npx shadcn@latest add button

Custom themes with tweakcn

Shadcn looks by default alredy pretty nice but together with tweakcn it’s just a completely different level. The way I can customize my whole theme with only a few button clicks just flashes me every time again. This is developer experience from another planet - big thanks to the creators <3

And thats not all, adding a new custom theme to my existing project couldn’t be easier. Literally all I need to do once I’m happy with my theme, is to click on the {} Code Button and copy & paste the command.

npx shadcn@latest add https://tweakcn.com/r/themes/solar-dusk.json

Dark and Light

In order to enable the dark and light theme, I first need to install next-themes with this command

npm install next-themes

As next I will need a location for the theme provider and switcher.

src/                              
└── components/  
    └── theme/
        β”œβ”€β”€ theme-provider.tsx
        └── theme-switcher.tsx
 

Theme Provider

The theme provider is used to take the default theme provider from next.js and customize it according to my preferring. With abstracting the theme-provider into its own file, it’s also gonna be easier to move it between different projects.

import { ThemeProvider as BaseThemeProvider } from "next-themes";
 
type ThemeProviderProps = {
  children: React.ReactNode;
};
 
const ThemeProvider = ({ children }: ThemeProviderProps) => {
  return (
    <BaseThemeProvider
      attribute="class"
      defaultTheme="system"
      enableSystem
      // disableTransitionOnChange
    >
      {children}
    </BaseThemeProvider>
  );
};
 
export { ThemeProvider };

Now I need to wrap the whole <body> in the root layout.tsx with the <ThemeProvider>.

  • Note for the HydrationWarning: For now I will add the suppressHydrationWarning to the <html> element. Later in the Road to Next course, I will learn a better way to handle this issue. lookup✏️
<html suppressHydrationWarning lang="en">
	<body>
      {/* Wrap here */}
	    <ThemeProvider>  
		    <Header></Header>
		    <main>
	            {children}
	        </main>
	    </ThemeProvider>
    </body>
</html>
  • Note for the import: I should not import the ThemeProvider from β€œnext-themes”, instead I should choose my custom made ThemeProvider.
import { ThemeProvider } from "@/components/theme/theme-provider";

ThemeSwitcher

The ThemeSwitcher component will enable me to switch between both themes. Its basically a button that onClick toggles the selectedThemes. Depending on the current theme, the button will contain a Moon or a Sun Icon.

"use client";
 
import { LucideMoon, LucideSun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
 
const ThemeSwitcher = () => {
  const { theme, setTheme } = useTheme();
 
  return (
    <Button
      variant="outline"
      size="icon"
      onClick={() => setTheme(theme === "light" ? "dark" : "light")}
    >
      <LucideSun
        className="
          h-4 w-4 rotate-0 scale-100 transition-all
          dark:-rotate-90 dark:scale-0
        "
      />
      <LucideMoon
        className="
          absolute h-4 w-4 rotate-90 scale-0 transition-transform
          dark:rotate-0 dark:scale-100
        "
      />
 
      <span className="sr-only">Toggle theme</span>
    </Button>
  );
};
 
export { ThemeSwitcher };

That’s it, now I just need to add the ThemeSwitcherComponent somewhere within my application and then I can switch between light and dark mode.


Lucide react

Lucide is a great source for finding all kinds of icon. The icon variety is not only very diverse, but its also extremely easy to import them in my project.

Installation

When creating a next.js project, it ususally supports lucide icons out of the box. However it’s also possible to install the package manually with

npm install lucide-react

Add a icon to the project

All i need to do for importing a lucide icon, is to open the one i like and click on the Copy JSX button. Then head over to my codebase and paste it.

While it’s just optional, it’s recommended to use the prefix Lucide. With that I can avoid naming issues with other components like the once from shadcn, since both can have the same name quite often.

<Castle />          // Default
<LucideCastle />.   // Preferred naming convention

Conclusion

Next.js really manages it to get rid of my biggest issue when creating a software - they always look awful. Making use of the styling and theming ability of the ecosystem of Next.js, just brings my application on a completely different level without spending years on a design carrier. Alone tweakcn, which offers an incredible amount of flexibility to shadcn components, leaves me speakless. Finally I’m able to create beautiful web apps in no time.