Leveraging shadow components with the Next.js pages directory

I am facing an issue with getting a simple shadcn button to work because I am unable to import the button. Although I am using nextjs 13, I am still utilizing the pages directory. Below is the process of how I installed shadcn.

Here is the installation command as directed on the webpage

npx shadcn-ui@latest init

The input for the command line was:

✔ Would you like to use TypeScript (recommended)? … no / yes
✔ Which style would you like to use? › Default
✔ Which color would you like to use as base color? › Slate
✔ Where is your global CSS file? … styles/globals.css
✔ Would you like to use CSS variables for colors? … no / yes
✔ Where is your tailwind.config.js located? … tailwind.config.js
✔ Configure the import alias for components: … @/components
✔ Configure the import alias for utils: … @/lib/utils
✔ Are you using React Server Components? … no / yes
✔ Write configuration to components.json. Proceed? … yes

The difficulty I encounter is that after installing the button, I cannot find the lib folder

// File path: @components/ui/button.ts
//Error: TS2307: Cannot find module '@/lib/utils' or its corresponding type declarations.
import { cn } from "@/lib/utils"
...

Below is my automatically created folder structure

.
├── src
│   └── pages
│       └── home.tsx 
├── @
│   └── components
│       └── ui
│       │    ├── alert-dialog.tsx
│       │    ├── button.tsx
│       │    └── dropdown-menu.tsx
│       │
│       └─ lib
│           └── utils.ts
├── styles
│   └── globals.css
├── next.config.js
├── package.json
├── postcss.config.js
├── tailwind.config.js
└── tsconfig.json

Note that this differs slightly from the example structure provided by shadcn. The @ was generated automatically

.
├── app
│   ├── layout.tsx
│   └── page.tsx
├── components
│   ├── ui
│   │   ├── alert-dialog.tsx
│   │   ├── button.tsx
│   │   ├── dropdown-menu.tsx
│   │   └── ...
│   ├── main-nav.tsx
│   ├── page-header.tsx
│   └── ...
├── lib
│   └── utils.ts
├── styles
│   └── globals.css
├── next.config.js
├── package.json
├── postcss.config.js
├── tailwind.config.js
└── tsconfig.json

My components.json file looks like this

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.js",
    "css": "styles/globals.css",
    "baseColor": "slate",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

and here is my tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
    ],
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    ...
  },
  plugins: [require("tailwindcss-animate"), require("daisyui")],
}

What could be the issue here?

Answer №1

In the example provided, the @ symbol is not indicating a folder but rather a path alias.

To resolve this issue, move your components and lib directories to the src directory:

.
├── src
│   └── pages
│       └── home.tsx 
│
├── components
│   ├── ui
│   │    ├── alert-dialog.tsx
│   │    ├── button.tsx
│   │    └── dropdown-menu.tsx
│   
├─ lib
│    └── utils.ts
│  
└─ styles
     └── globals.css

Next, update your tsconfig.json file as follows:

"paths": {
  "@/*": ["./src/*"]
}

This configuration means that when you use @/components/whatever, the compiler will look for this path at ROOT => src/components/whatever. Similarly, @/lib/utils translates to <ROOT>/lib/utils.

However, with your current setup, using

import { cn } from "@/lib/utils"
would result in looking for it at
./@/components/ui/button/@/lib/utils
, which does not exist.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the power of VueJs through chaining actions and promises

Within my component, I have two actions set to trigger upon mounting. These actions individually fetch data from the backend and require calling mutations. The issue arises when the second mutation is dependent on the result of the first call. It's cr ...

How can I show a title when redirecting a URL in VUE JS?

My current setup includes a navigation drawer component that changes the title based on the user's route. For example, when navigating to the home page (e.g. "/"), the title updates to "Home", and when navigating to the profile page (e.g. /profile), t ...

Should we avoid using 'RedirectToAction' with AJAX POST requests in ASP.NET?

As a newcomer to jQuery, Json, and Ajax, I am putting in the effort to grasp the concepts clearly, but I am facing some difficulties. I have an ajax POST Delete method that is currently functional, however, my professor has suggested that I refactor the c ...

Is combining Nuxt 3 with WP REST API, Pinia, and local storage an effective approach for user authentication?

My current project involves utilizing NUXT 3 for the frontend and integrating Wordpress as the backend. The data is transmitted from the backend to the frontend through the REST API. The application functions as a content management system (CMS), with all ...

Is it possible to implement a custom radio tab index without using JavaScript

Is it possible to apply the tabindex attribute on custom radio buttons, hide the actual input element, and use keyboard shortcuts like Tab, Arrow Up, and Arrow Down to change the value? Check out this example on StackBlitz ...

Using CSS to position elements absolutely while also adjusting the width of the div

In one section of my website, I have a specific div structure. This structure consists of two divs stacked on top of each other. The first div is divided into two parts: one part with a width of 63% and another part with a button. Beneath the first div, t ...

Guidelines for implementing a vuex getter within the onMounted hook in Vue

Currently, my process involves fetching data from a database and storing it in vuex. I am able to retrieve the data using a getter in the setup method, but I would like to manipulate some of that data before the page is rendered, ideally in the onMounted m ...

Ways to prompt a window resize event using pure javascript

I am attempting to simulate a resize event using vanilla JavaScript for testing purposes, but it seems that modern browsers prevent the triggering of the event with window.resizeTo() and window.resizeBy(). I also tried using jQuery $(window).trigger(' ...

What happens with page rendering when neither getStaticProps nor getServerSideProps are defined on a page?

My current Next.js project is missing the definition of both rendering methods on certain pages. What happens to those pages when neither getStaticProps nor getServerSideProps are included? ...

Different choices for data attributes in React

Recently, I downloaded a new app that requires multiple API calls. The first API call retrieves 20 Objects, each with its own unique ID. The second API call is made based on the IDs from the first call. To display this data in my component: <div> ...

Receiving the final outcome of a promise as a returned value

Seeking to deepen my comprehension of promises. In this code snippet, I am working on creating two promises that will return the numbers 19 and 23 respectively. However, when attempting to console log the value returned from the first promise, I encounte ...

Mapbox GL JS stops displaying layers once a specific zoom level or distance threshold is reached

My map is using mapbox-gl and consists of only two layers: a marker and a circle that is centered on a specific point. The distance is dynamic, based on a predefined distance in meters. The issue I'm facing is that as I zoom in and move away from the ...

JEST: Troubleshooting why a test case within a function is not receiving input from the constructor

When writing test cases wrapped inside a class, I encountered an issue where the URL value was not being initialized due to dependencies in the beforeAll/beforeEach block. This resulted in the failure of the test case execution as the URL value was not acc ...

Can a hyperlink exist without a specified href attribute?

One scenario could be when I receive this specific code from a third-party source <a class="cs_import">Add contacts from your Address Book</a> Curiously, the link "Add contacts from your Address Book" does not redirect to any page as expected ...

Subscriber client successfully activated and operational via the command line interface

I have incorporated a script into my PHP file that reads the Pusher channel and performs various actions when a new event occurs on the specified channel. If I access the following URL in my browser: http:/localhost/pusher.php and keep it open, the p ...

Tips for removing the default hover and click effects from a Material-UI CardActionArea

Check out the card sample with a lizard photo on https://material-ui.com/components/cards. When you hover over the cardActionArea, it will get darker or lighter based on the theme. Clicking on the card will make the picture change its brightness relative ...

"Enhance Your Website with jQuery: Organized Lists with Fixed Length, Connected,

I currently have a list that is separated into three columns, structured as follows: Column1 Column2 Column3 1 4 7 2 5 8 3 6 9 The list ranges from 1 to 9 and each column consists of a fixed number of rows (3). I am lo ...

React Bootstrap always displays tooltips

I have integrated react-bootstrap into my project. I am currently attempting to keep a tooltip always displayed, but I am facing some challenges in achieving this. Below are the approaches I have tried so far: <Card style={{width: '10rem'}} ...

What are the best ways to personalize my code using Angular Devextreme?

Our development team is currently utilizing Angular for the front-end framework and ASP.net for the back-end framework. They are also incorporating Devextreme and Devexpress as libraries, or similar tools. However, there seems to be difficulty in implement ...

Issue encountered when trying to import an image URL as a background in CSS using Webpack

I have been trying to add a background image to my section in my SCSS file. The linear gradient is meant to darken the image, and I'm confident that the URL is correct. background-image: url(../../assets/img/hero-bg.jpg), linear-gradient(r ...