Troubleshooting shadcn/ui: Style Conflicts, Rendering Issues, and TypeScript Errors
It’s 2 AM. I’m staring at a button component on my screen—it should be a nice blue button, but it looks like a plain HTML button without even a border radius.
This isn’t my first time dealing with shadcn/ui style issues. Honestly, in the past three months, I’ve hit more pitfalls than I’ve written code. Style conflicts, components not rendering, TypeScript errors—these problems feel like shadcn/ui’s “signature features.” Every new project seems to encounter at least a few of them.
Today I’m documenting these common issues and solutions, hoping to help you avoid some of the same detours.
Debugging Style Conflicts
Style conflicts are the most common problem, accounting for about 40% of all issues. There are several main causes:
CSS Variable Conflicts
shadcn/ui uses CSS variables to manage theme colors, defined in globals.css:
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 2%;
}
Here’s the issue. If your project already has its own theme configuration, or if you’ve modified Tailwind’s color settings before installing shadcn/ui, these two configurations might clash.
How to debug?
First, open globals.css and check if all CSS variables are present. Then examine the colors configuration in tailwind.config.js:
module.exports = {
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
},
},
},
}
These two must correspond. If any variable is missing, the corresponding style won’t work.
My experience: Before installing shadcn/ui, backup both tailwind.config.js and globals.css. After installation, compare the differences and manually restore any overwritten configurations.
Shadow DOM vs Tailwind Conflicts
This one’s interesting. Shadow DOM is meant for style isolation, but Tailwind class names can’t penetrate Shadow DOM boundaries.
The most typical scenario is the Dialog component. DialogContent renders to document.body via Portal, escaping Shadow DOM’s scope—all styles are lost.
Two solutions:
First, simply don’t use Shadow DOM:
const MyDialogWC = r2wc(MyDialog, {
shadow: null // Turn off Shadow DOM
});
This way, Portal works normally, but style isolation is gone. You need to manually manage global styles and watch out for class name conflicts.
Second, use Safelist to force-include class names:
// tailwind.config.js
module.exports = {
safelist: [
'bg-primary',
'text-primary-foreground',
'hover:bg-primary/90',
'bg-red-500',
'h-9',
'h-10',
'px-3',
'px-4',
],
}
This approach guarantees style generation, but Safelist increases CSS file size. You need to weigh the trade-offs.
Coexisting with Other UI Libraries
If your project already uses MUI (Material-UI) and you want to migrate to shadcn/ui, you’ll encounter style conflicts.
The root cause is Tailwind’s Preflight—it resets all browser default styles. MUI’s styles get reset too, causing components to display abnormally.
Common attempts:
Some people disable Preflight:
module.exports = {
corePlugins: {
preflight: false, // Disable Preflight
},
}
But this has a side effect: Tailwind’s styles are also affected. Some components might display incorrectly.
Better approach:
Use Tailwind’s prefix feature to prefix all Tailwind classes:
module.exports = {
prefix: 'tw-', // All classes become tw-bg-blue-500
}
This way, Tailwind classes and MUI classes won’t conflict. However, you have to manually add tw- before every class name, which is a bit tedious.
My advice: If the project has many MUI components, don’t rush to migrate everything. Use the prefix approach for coexistence first—new components use shadcn/ui, old ones stay with MUI, and migrate gradually.
Tailwind Configuration Overwritten
I’ve hit this pitfall several times.
After running npx shadcn-ui@latest init, the Tailwind configuration file gets overwritten. Especially the plugins array—if you previously configured @tailwindcss/forms or other plugins, they disappear.
The symptoms are obvious: form input styles suddenly become weird, or some components show no styles at all.
Debugging steps:
- Open the backup of
tailwind.config.jsfrom before installation - Compare with the post-installation config file
- Restore missing plugins:
module.exports = {
// ... other config
plugins: [
require("@tailwindcss/forms"), // Restore this
require("tailwindcss-animate"),
],
}
Prevention: Before installing shadcn/ui, backup config files. Or use a dedicated configuration management script to track all plugins.
Debugging Components Not Rendering
Styles are fine, but components don’t display at all? This is also quite common.
Content Path Configuration Errors
Tailwind needs to know which files use its class names to generate corresponding CSS. This configuration is in the content field of tailwind.config.js.
The problem usually is: shadcn/ui’s component directories aren’t included.
Check configuration:
module.exports = {
content: [
'./src/app/**/*.{ts,tsx}',
'./src/components/**/*.{ts,tsx}', // This must be included
'./app/**/*.{ts,tsx}',
'./pages/**/*.{ts,tsx}',
],
}
If you place components in a UI library within node_modules, you also need to add:
content: [
// ... other paths
'./node_modules/@your-ui-lib/**/*.{ts,tsx}',
]
My experience: Every time you create a new component directory, remember to add the path to content configuration. Otherwise, Tailwind won’t scan these files, and class names won’t be generated.
globals.css Path Issues
shadcn/ui needs a CSS file to define theme variables. This file’s path is configured in components.json.
The problem usually is: the path is wrong, or there are multiple globals.css files.
Debugging method:
First check components.json:
{
"style": "default",
"css": "src/app/globals.css", // This path
}
Then confirm:
- Does this file actually exist?
- Is there only one globals.css in your project?
- Is globals.css properly imported into the main file?
If there are multiple globals.css files, delete extras and keep only one.
Import check:
In Next.js projects, globals.css should be imported in app/layout.tsx or pages/_app.tsx:
import '@/app/globals.css' // or './globals.css'
If not imported, CSS variables won’t work, and component styles are completely lost.
CSS Variables Not Defined
Sometimes, globals.css file exists, but variables aren’t defined.
The most typical case is dark mode. You switch to dark mode and find component colors are wrong—possibly because dark mode CSS variables aren’t configured.
Check globals.css:
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 2%;
}
Variables under .dark class must be defined. Otherwise, dark mode components have no styles.
Tailwind v4 special case:
If you’re using Tailwind v4, configuration is different:
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
}
This @theme inline mapping must exist. Otherwise, Tailwind v4 won’t recognize these variables.
Import Path Case Sensitivity Issues
I’ve hit this pitfall twice.
Windows filenames are case-insensitive, but Linux/Mac are sensitive. Local development works fine, but deployment to production errors out.
The symptom usually is: components render locally, but after pushing to server, module not found errors appear.
Typical error:
// ❌ Wrong: Button uppercase B
import { Button } from "@/components/ui/Button"
// ✅ Correct: button lowercase b
import { Button } from "@/components/ui/button"
shadcn/ui component filenames are all lowercase. Import paths must use lowercase.
Debugging method:
Check all component import statements to ensure paths match actual filenames. Especially check production environment error messages.
Debugging TypeScript Type Errors
TypeScript errors are relatively fewer, but still quite frustrating when encountered.
Variant Property Type Errors
shadcn/ui’s Button component has a variant property to switch button styles (default, destructive, outline, etc.).
The error message usually is:
Type '{ variant: string }' is not assignable to type 'IntrinsicAttributes & ButtonProps'.
Property 'variant' does not exist on type 'IntrinsicAttributes & ButtonProps'.
Root cause:
In the Button component’s type definition, the variant property isn’t properly exported.
Debugging method:
Open components/ui/button.tsx and check variant’s type definition:
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
},
},
}
)
interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
// VariantProps here is required
}
If VariantProps<typeof buttonVariants> is missing, the variant property’s type is gone.
My experience: When encountering this error, first check the component’s type definition. Ensure VariantProps is properly inherited.
React Version Incompatibility
If you’re using React 19, but some dependencies don’t support React 19 yet, you’ll encounter type errors.
The error message usually is:
npm error ERESOLVE unable to resolve dependency tree
npm error Found: [email protected]
Two solutions:
First, force install:
npm install --legacy-peer-deps
# or
npm install --force
This ignores peer dependency version requirements. But there may be compatibility issues.
Second, downgrade React:
npm install react@18 react-dom@18
Use React 18, and upgrade after dependencies update.
My advice: New projects are more stable with React 18. Consider upgrading after shadcn/ui and other dependencies all support React 19.
React Hook Form Type Issues
When using shadcn/ui’s Form component with React Hook Form and Zod, you’ll encounter type mapping issues.
The error message usually is:
Type 'info.${number}.fileName' is not assignable to type '"info" | "info.0" | "info.0.fileName"'
This is a dynamic form field type issue. Zod Schema’s type doesn’t match FormField’s name property type.
Solution:
Ensure Schema type is properly inferred:
const formSchema = z.object({
email: z.string().email(),
password: z.string(),
})
type FormValues = z.infer<typeof formSchema> // This type inference is required
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
})
FormField’s name property will automatically match Schema’s field names.
My experience: Dynamic forms (like those using useFieldArray) have more complex types. Need to carefully check Zod Schema definitions and TypeScript type inference.
Missing Type Dependencies
Sometimes, TypeScript errors are because @types/react or @types/react-dom aren’t installed.
The error message might be:
Could not find a declaration file for module 'react'
Solution:
npm install -D @types/react @types/react-dom
After installing, restart the TypeScript server (in VSCode, use Ctrl+Shift+P, type “TypeScript: Restart TS Server”).
Prevention: Install type dependencies at the start of new projects. Don’t wait until errors appear.
Best Practices and Prevention Measures
After hitting so many pitfalls, I’ve summarized some prevention measures.
Configuration Management Standards
Backup configuration files:
Before every shadcn/ui installation or Tailwind configuration modification, backup first:
cp tailwind.config.js tailwind.config.js.backup
cp globals.css globals.css.backup
After installation, compare differences and manually merge configurations.
Single configuration file:
One project should only use one tailwind.config.js and one globals.css. Don’t create multiple config files—easily causes conflicts.
Complete path configuration:
content configuration should include all component directories:
content: [
'./src/**/*.{ts,tsx}', // Use wildcards to cover all directories
'./app/**/*.{ts,tsx}',
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
]
Dependency Version Management
Check peerDependencies:
Before installing new dependencies, check their peerDependencies:
npm info <package> peerDependencies
If a dependency requires React 18, but your project uses React 19, consider compatibility.
Regularly update type dependencies:
npm update @types/react @types/react-dom
Keep type declarations synchronized with React version.
Testing Strategy
Test immediately after installation:
After completing shadcn/ui installation, immediately test styles:
- Create a simple page using several shadcn/ui components
- Check if styles display normally
- Test dark mode switching
- Run TypeScript compilation check
Production environment testing:
Local development working doesn’t mean production environment works:
npm run build
npm run preview
Build and preview to check if styles and types are normal.
Summary
After all this, shadcn/ui’s common problems mainly concentrate in three areas:
- Style conflicts: configuration files overwritten, CSS variable conflicts, coexistence with other UI libraries
- Components not rendering: content path configuration errors, globals.css path issues, import path case sensitivity
- TypeScript type errors: variant property type missing, React version incompatible, type dependencies missing
When encountering problems, debug in this sequence:
- First check configuration files (tailwind.config.js, globals.css)
- Then check path configurations (content, import paths)
- Finally check type definitions (component types, dependency versions)
If you’re just starting with shadcn/ui, I suggest trying the entire process in a blank project first. After becoming familiar with configurations and common issues, then use it in real projects.
shadcn/ui is great, but configuration is indeed a bit complex. After mastering these debugging methods, you won’t panic when encountering problems.
FAQ
Why are all styles lost after installing shadcn/ui?
• Whether tailwind.config.js plugins array is complete
• Whether globals.css path is correct
• Whether all CSS variables are defined
Solution: Backup config files before installation, compare differences after, and manually restore missing configurations.
Why are component styles wrong after switching to dark mode?
• .dark class must exist
• All theme variables need to be redefined
• Tailwind v4 requires @theme inline to map variables
Can shadcn/ui coexist with MUI?
• Set prefix: 'tw-' to prefix all Tailwind classes
• New components use shadcn/ui, old ones stay with MUI
• Migrate gradually, don't change everything at once
Disabling Preflight is not recommended as it affects Tailwind styles.
What to do when Button's variant property shows TypeScript error?
• VariantProps<typeof buttonVariants> must be inherited
• Ensure component file fully exports types
• Install @types/react and @types/react-dom
If type definition is missing, reinstall component with npx shadcn@latest add button.
Can I use shadcn/ui with React 19?
• Use --legacy-peer-deps or --force during installation
• Or specify react-is version in package.json overrides
• New projects recommend using React 18 first, upgrade after dependencies update
Component works locally but production shows module not found error?
• shadcn/ui component filenames are all lowercase (button.tsx)
• Import paths must match filenames (@/components/ui/button)
• Windows insensitive, Linux/Mac sensitive—local tests work but production errors
Check all import statements to ensure paths completely match.
8 min read · Published on: Apr 2, 2026 · Modified on: Apr 5, 2026
Related Posts
GitHub Actions Basics: YAML Workflow Structure and Trigger Configuration
GitHub Actions Basics: YAML Workflow Structure and Trigger Configuration
n8n Workflow Building: From Node Connections to Automation Scenario Design
n8n Workflow Building: From Node Connections to Automation Scenario Design
Supabase Database Design: Tables, Relationships & Row Level Security Guide

Comments
Sign in with GitHub to leave a comment