Prerequisites
Before starting the project make sure to install the following utilities:
Creating a new Next application
Let's create a fresh Next application so that we can go through all the steps together.
Step 1
Create new project
npx create-next-app@latest
cd my-project
Installing and configuring Tailwind CSS and TW Elements React
Step 1
Install and initialize Tailwind CSS (if you haven't already)
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
If you have created a new next app, then the file structure should look similar to this
Yes
, ESLint - Yes
, `src/` directory - Yes
, App Router - both examples included in this tutorial
my-project/
├── node_modules/
├── public/
├── src/
│ ├── pages/ - needs to be created
│ ├── app/
│ │ ├── favicon.ico
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── index.css
│ ├── ...
│ └── index.js
├── package-lock.json
├── package.json
├── next.config.js
├── tsconfig.config.js
├── ...
└── tailwind.config.js
my-project/
├── node_modules/
├── public/
├── src/
│ ├── pages/
│ ├──── app/
│ │ ├── _app.tsx
│ │ ├── _document.tsx
│ │ └── index.tsx
│ └── styles/
│ └── globals.css
├── package-lock.json
├── package.json
├── next.config.js
├── tsconfig.config.js
├── ...
└── tailwind.config.js
Step 2
Install TW Elements React.
npm install tw-elements-react
Step 3
Add the paths to all of your template files in your
tailwind.config.js
file.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"./node_modules/tw-elements-react/dist/js/**/*.js",
// Or if using `src` directory:
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/tw-elements-react/dist/js/**/*.js"
],
theme: {
extend: {},
},
darkMode: "class",
plugins: [require("tw-elements-react/dist/plugin.cjs")]
}
Step 4
Add the @tailwind
directives for each of Tailwind’s layers to
your ./src/app/global.css
or ./src/styles/globals.css
file. There will be more rules if you picked to install tailwind when creating the next app. You can remove them if you want. If you leave them the darkmode may not work properly.
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 5
Change the inter
font to the Roboto
font in:
-
./src/app/layout.tsx
- if chosenApp Router
-
./src/pages/_app.tsx
- without routing
import "./globals.css";
import { Roboto } from "next/font/google";
const roboto = Roboto({ weight: "400", subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={roboto.className}>{children}</body>
</html>
);
}
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { Roboto } from "next/font/google";
import "tw-elements/dist/css/tw-elements.min.css";
const roboto = Roboto({ weight: "400", subsets: ["latin"] });
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<style jsx global>{`
html {
font-family: ${roboto.style.fontFamily};
}
`}</style>
<Component {...pageProps} />
</>
);
}
Step 6
Import globally in ./src/app/layout.tsx
or ./src/pages/_app.tsx
TW Elements React CSS file (you could do it also in specific component which are using TE React).
import "tw-elements-react/dist/css/tw-elements-react.min.css";
Step 7
Go to the src/pages
folder and create a new, standalone file with name of your component (for example MyComponent.tsx
. Inside import TE React components which you want to use. Our components need to be used in client mode so let's not forget to add "use client"
before anything we do in this file.
"use client";
import React, { useState } from "react";
import { TECollapse, TERipple } from "tw-elements-react";
export default function CollapseBasicExample(): JSX.Element {
const [show, setShow] = useState(false);
const toggleShow = () => setShow(!show);
return (
<>
<TERipple rippleColor="light">
<a
className="inline-block rounded bg-primary mr-2 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
role="button"
onClick={toggleShow}
>
Link
</a>
</TERipple>
<TERipple rippleColor="light">
<button
type="button"
className="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
onClick={toggleShow}
>
Button
</button>
</TERipple>
<TECollapse show={show}>
<div className="block rounded-lg bg-white p-6 shadow-lg dark:bg-neutral-700 dark:text-neutral-50">
Some placeholder content for the collapse component. This panel is
hidden by default but revealed when the user activates the relevant
trigger.
</div>
</TECollapse>
</>
);
}
If you see errors that say: "Attempted import error" you can try importing the components with use of next/dynamic
import dynamic from "next/dynamic";
const TECollapse = dynamic(() =>
import("tw-elements-react").then((res) => res.TECollapse)
);
const TERipple = dynamic(() =>
import("tw-elements-react").then((res) => res.TERipple)
);
Step 8
Import (for example in src/app/page.tsx
) newly created component wrapping it into dynamic
import with ssr
object set to false
.
import dynamic from "next/dynamic";
const DynamicComponent = dynamic(() => import("../pages/MyComponent"), { ssr: false });
const Home = () => {
return (
<>
<DynamicComponent />
</>
);
};
export default Home;
Step 9
Start the app and see if everything's fine
npm run dev