My Honest Review of Tailwind, Radix UI, and Shadcn UI
Tags: tailwindcss, programming, opensource, css
Published: 2023-08-08 17:47:53

## My Honest Review Of These CSS Librarieis

In recent years, there has been a growing trend towards using CSS libraries to speed up and simplify the development of web applications. Three of the most popular CSS libraries today are Tailwind, Radix UI, and Shadcn UI.

---

**Tailwind** is a utility-first CSS framework that allows you to build custom styles with a minimal amount of code. It's very popular among developers because it's highly customizable and can be used to create a wide variety of designs. However, Tailwind can be a bit difficult to learn at first, and it can be easy to make mistakes if you're not careful.

**Radix UI** is a component-based CSS library that provides a set of ready-made components that you can use to build your web application. It's a good choice for developers who want to get started quickly without having to worry about writing custom CSS. However, Radix UI can be a bit limiting if you need to create custom components, and it can be more expensive than other CSS libraries.

**Shadcn UI** is a relatively new CSS library that combines the best features of Tailwind and Radix UI. It's highly customizable like Tailwind, but it also provides a set of ready-made components like Radix UI. Shadcn UI is a good choice for developers who want the flexibility of Tailwind with the convenience of a component library.

Here is a table that summarizes the advantages, disadvantages, and key features of each CSS library:

| Tailwind    | Advantages |  Disadvantages |  Key Features  |
|------|---|----|-----|
| Tailwind    | Highly customizable, can be used to create a wide variety of designs |  Can be difficult to learn at first, easy to make mistakes |  Utility-first CSS framework, allows you to build custom styles with a minimal amount of code  |
| Radix UI    | Ready-made components, easy to get started |  Can be limiting if you need to create custom components, more expensive than other CSS libraries |  Component-based CSS library, provides a set of ready-made components that you can use to build your web application  |
| Shadcn UI    | Highly customizable, ready-made components, easy to learn |  Not as widely used as Tailwind or Radix UI |  	Combines the best features of Tailwind and Radix UI, highly customizable, provides a set of ready-made components  |

---

## Installation

**Here is a quick overview of how to set up each library:**

- **Tailwind:** To set up Tailwind, you need to install the `tailwindcss` package and the `postcss` package. You can do this with the following command:

```bash
npm install tailwindcss postcss
```

Once you have installed the packages, you need to create a `tailwind.config.js` file in the root directory of your project. This file will contain the configuration settings for Tailwind. You can find more information about the configuration settings in the [Tailwind documentation](https://tailwindcss.com/docs/configuration)

---

- **Radix UI:** To set up Radix UI, you need to install the `radix-ui/themes` package, then any other package that follows. Today I'll show you how to install the followinng

- `radix-ui/themes`
- `radix-ui/react-alert-dialog`

## Getting Started

### Installation

### 1. Install Radix Themes

Install the package from your command line.

| npm                          | yarn                      | pnpm                          |
|------------------------------|---------------------------|-------------------------------|
| `npm install @radix-ui/themes` | `yarn add @radix-ui/themes` | `pnpm install @radix-ui/themes` |

### 2. Import the CSS file

Import the global CSS file at the root of your application.

```bash
import '@radix-ui/themes/styles.css'; 
```

### 3. Add the Theme component

Wrap the root of your application in a `Theme` component.

```tsx
import { Theme } from '@radix-ui/themes';

export default function () {
  return (
    <Theme>
      <MyApp />
    </Theme>
  );
}
```

### 4. Start building

You are now ready to use Radix Themes components.

```tsx
import { Flex, Text, Button } from '@radix-ui/themes';

export default function MyApp() {
  return (
    <Flex direction="column" gap="2">
      <Text>Hello from Radix Themes :)</Text>
      <Button>Let's go</Button>
    </Flex>
  );
}
```

### Customizing your theme

[Learn More](https://www.radix-ui.com/themes/docs/overview/getting-started#customizing-your-theme)

---

## Installing react-alert-dialog with radix-ui

---

### Install the Component

```bash
npm install @radix-ui/react-dialog 
```

### Usage

```tsx
//index.tsx

import React from 'react';
import * as AlertDialog from '@radix-ui/react-alert-dialog';
import './styles.css';

const AlertDialogDemo = () => (
  <AlertDialog.Root>
    <AlertDialog.Trigger asChild>
      <button className="Button violet">Delete account</button>
    </AlertDialog.Trigger>
    <AlertDialog.Portal>
      <AlertDialog.Overlay className="AlertDialogOverlay" />
      <AlertDialog.Content className="AlertDialogContent">
        <AlertDialog.Title className="AlertDialogTitle">Are you absolutely sure?</AlertDialog.Title>
        <AlertDialog.Description className="AlertDialogDescription">
          This action cannot be undone. This will permanently delete your account and remove your
          data from our servers.
        </AlertDialog.Description>
        <div style={{ display: 'flex', gap: 25, justifyContent: 'flex-end' }}>
          <AlertDialog.Cancel asChild>
            <button className="Button mauve">Cancel</button>
          </AlertDialog.Cancel>
          <AlertDialog.Action asChild>
            <button className="Button red">Yes, delete account</button>
          </AlertDialog.Action>
        </div>
      </AlertDialog.Content>
    </AlertDialog.Portal>
  </AlertDialog.Root>
);

export default AlertDialogDemo;
```

### Using Default CSS

```css

/* styles.css */

@import '@radix-ui/colors/black-alpha.css';
@import '@radix-ui/colors/mauve.css';
@import '@radix-ui/colors/red.css';
@import '@radix-ui/colors/violet.css';

/* reset */
button {
  all: unset;
}

.AlertDialogOverlay {
  background-color: var(--black-a9);
  position: fixed;
  inset: 0;
  animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}

.AlertDialogContent {
  background-color: white;
  border-radius: 6px;
  box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 90vw;
  max-width: 500px;
  max-height: 85vh;
  padding: 25px;
  animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}
.AlertDialogContent:focus {
  outline: none;
}

.AlertDialogTitle {
  margin: 0;
  color: var(--mauve-12);
  font-size: 17px;
  font-weight: 500;
}

.AlertDialogDescription {
  margin-bottom: 20px;
  color: var(--mauve-11);
  font-size: 15px;
  line-height: 1.5;
}

.Button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  padding: 0 15px;
  font-size: 15px;
  line-height: 1;
  font-weight: 500;
  height: 35px;
}
.Button.violet {
  background-color: white;
  color: var(--violet-11);
  box-shadow: 0 2px 10px var(--black-a7);
}
.Button.violet:hover {
  background-color: var(--mauve-3);
}
.Button.violet:focus {
  box-shadow: 0 0 0 2px black;
}
.Button.red {
  background-color: var(--red-4);
  color: var(--red-11);
}
.Button.red:hover {
  background-color: var(--red-5);
}
.Button.red:focus {
  box-shadow: 0 0 0 2px var(--red-7);
}
.Button.mauve {
  background-color: var(--mauve-4);
  color: var(--mauve-11);
}
.Button.mauve:hover {
  background-color: var(--mauve-5);
}
.Button.mauve:focus {
  box-shadow: 0 0 0 2px var(--mauve-7);
}

@keyframes overlayShow {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes contentShow {
  from {
    opacity: 0;
    transform: translate(-50%, -48%) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}
```

### Using Component with Tailwind CSS

```tsx

//index.tsx

import React from 'react';
import * as AlertDialog from '@radix-ui/react-alert-dialog';

const AlertDialogDemo = () => (
  <AlertDialog.Root>
    <AlertDialog.Trigger asChild>
      <button className="text-violet11 hover:bg-mauve3 shadow-blackA7 inline-flex h-[35px] items-center justify-center rounded-[4px] bg-white px-[15px] font-medium leading-none shadow-[0_2px_10px] outline-none focus:shadow-[0_0_0_2px] focus:shadow-black">
        Delete account
      </button>
    </AlertDialog.Trigger>
    <AlertDialog.Portal>
      <AlertDialog.Overlay className="bg-blackA9 data-[state=open]:animate-overlayShow fixed inset-0" />
      <AlertDialog.Content className="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[500px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none">
        <AlertDialog.Title className="text-mauve12 m-0 text-[17px] font-medium">
          Are you absolutely sure?
        </AlertDialog.Title>
        <AlertDialog.Description className="text-mauve11 mt-4 mb-5 text-[15px] leading-normal">
          This action cannot be undone. This will permanently delete your account and remove your
          data from our servers.
        </AlertDialog.Description>
        <div className="flex justify-end gap-[25px]">
          <AlertDialog.Cancel asChild>
            <button className="text-mauve11 bg-mauve4 hover:bg-mauve5 focus:shadow-mauve7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
              Cancel
            </button>
          </AlertDialog.Cancel>
          <AlertDialog.Action asChild>
            <button className="text-red11 bg-red4 hover:bg-red5 focus:shadow-red7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-medium leading-none outline-none focus:shadow-[0_0_0_2px]">
              Yes, delete account
            </button>
          </AlertDialog.Action>
        </div>
      </AlertDialog.Content>
    </AlertDialog.Portal>
  </AlertDialog.Root>
);

export default AlertDialogDemo;
```

---

- **Shadcn UI:** To set up Shadcn UI, you need to initialize a new shadcn project with yours, shadcn comes with a CLI that integrates with your favorite `frameworks`, example are `Next.js`, `Vite`, `Remix`, `Gatsby`, `Astro` etc. Pick your favorite framework and run the CLI

### Example using Next.js

1. **Create project:**

Start by creating a new Next.js project using `create-next-app`

```bash
pnpm create next-app@latest my-app --typescript --tailwind --eslint
```

2. **Run the CLI:**

Run the `shadcn-ui` init command to setup your project:

```bash
pnpm dlx shadcn-ui@latest init
```

3. **Configure components.json:**

You will be asked a few questions to configure `components.json`:

```
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? › › app/globals.css
Do you want 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
```

4. **App structure:**

```
.
├── 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
```

- I place the UI components in the `components/ui` folder.

- The rest of the components such as `<PageHeader />` and `<MainNav />` are placed in the `components` folder.

- The `lib` folder contains all the utility functions. I have a `utils.ts` where I define the `cn` helper.

- The `styles` folder contains the global CSS.

5. **That's it:**

You can now start adding components to your project.

```bash
pnpm dlx shadcn-ui@latest add button
```

---

The command above will add the `Button` component to your project. You can then import it like this:

```bash
import { Button } from "@/components/ui/button"

export default function Home() {
  return (
    <div>
      <Button>Click me</Button>
    </div>
  )
}
```

## Key Features

Sure, here are the key features of Tailwind, Radix UI, and Shadcn UI:

**Tailwind**

- Highly customizable
- Can be used to create a wide variety of designs
- Easy to learn
- Can be used with any JavaScript framework
- Provides a wide range of utility classes
- Can be used to create custom components

---

**Radix UI**

- Ready-made components
- Easy to get started
- Provides a wide range of components
- Supports a variety of screen sizes
- Well-documented
- Actively maintained

---

**Shadcn UI**

- Combines the best features of Tailwind and Radix UI
- Highly customizable
- Provides a set of ready-made components
- Easy to learn
- Actively maintained

---

Here is a table that summarizes the key features of each CSS library:

| Tailwind  | Highly customizable, can be used to create a wide variety of designs, easy to learn, can be used with any JavaScript framework, provides a wide range of utility classes, can be used to create custom components |
|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Radix UI  | Ready-made components, easy to get started, provides a wide range of components, supports a variety of screen sizes, well-documented, actively maintained                                                         |
| Shadcn UI | Combines the best features of Tailwind and Radix UI, highly customizable, provides a set of ready-made components, easy to learn, actively maintained                                                             |


---

## My recommendation

Sure, here is a summary of the three CSS libraries, along with my recommendation for which is the easiest to set up and understand:

- **Tailwind** is the most customizable library, but it can also be the most difficult to learn and set up. It's a good choice for developers who want to have complete control over their CSS, but it may not be the best choice for beginners.

- **Radix UI** is the easiest library to set up and understand. It provides a set of ready-made components that you can use to build your web application, without having to write any custom CSS. However, Radix UI is not as customizable as Tailwind, so it may not be the best choice for developers who need a lot of control over their CSS.

- **Shadcn UI** is a good compromise between Tailwind and Radix UI. It's more customizable than Radix UI, but it's also easier to set up and understand than Tailwind. Shadcn UI is a good choice for developers who want a balance of customization and ease of use.

**My recommendation for the easiest library to set up and understand is Shadcn UI.** It's a good choice for developers of all levels, and it provides a good balance of customization and ease of use.