Development preview

Getting started

Catalyst is a starter kit for building your own component systems with React — designed and developed by the Tailwind CSS team. It's a collection of beautiful, production-ready UI components you drop into your projects alongside your own code that are yours to customize, adapt, and make your own.

Catalyst is currently in development preview with unstable dependencies.

While not planned, we may need to introduce breaking changes in these dependencies on the road to Catalyst v1.0.


Before you start

Before you do anything else, make sure you've got a Tailwind CSS project set up that you'd like to use with Catalyst. Catalyst is built with React but isn't coupled to any specific React framework and can be used with Next.js, Remix, Inertia, or in any other React project.

For help creating a project and configuring Tailwind CSS, check out the framework guides in the Tailwind CSS documentation.

Catalyst is built around Tailwind's default theme configuration and relies on the default spacing scale, color palette, shadow scale, and more. You're of course free to customize anything you like, but you won't get the expected results out-of-the-box if you've made significant changes to the default theme and will need to edit the components to adapt them for your customizations.


Adding Catalyst to your project

To get started with Catalyst, first download the latest version from within your Tailwind UI account.

Then, unzip catalyst-ui-kit.zip and copy the component files from either the javascript or typescript folders into wherever you keep components in your own project:

Installing dependencies

Next install the dependencies used by the components in Catalyst:

npm install @headlessui/react@next clsx

Catalyst is currently in development preview and depends on a development build of Headless UI, so be sure to install @headlessui/react using the next tag.

Catalyst is also designed for the latest version of Tailwind CSS, which is currently Tailwind CSS v3.4. To make sure that you are on the latest version of Tailwind, update it via npm:

npm install tailwindcss@latest

Client-side router integration

By default, the Link component in Catalyst renders a plain HTML <a> element. You should update this component in your link.tsx or link.jsx file to use the link component provided by whichever framework or routing library you're using in your project.

 import { DataInteractive as HeadlessDataInteractive } from '@headlessui/react'
 import React from 'react'
 import NextLink, { type LinkProps } from 'next/link'
 
 export const Link = React.forwardRef(function Link(
   props: { href: string } & React.ComponentPropsWithoutRef<'a'>,
   props: LinkProps & React.ComponentPropsWithoutRef<'a'>,
   ref: React.ForwardedRef<HTMLAnchorElement>
 ) {
   return (
     <HeadlessDataInteractive>
       <a {...props} ref={ref} />
       <NextLink {...props} ref={ref} />
     </HeadlessDataInteractive>
   )
 })

We've provided ready-to-go examples for Next.js, Remix, and Inertia.js at the bottom of this page.

Optional: Setup Inter font family

We've designed Catalyst using Inter to ensure that the components look the same in all browsers and operating systems.

If you'd like to use Inter in your own projects, start by checking the documentation for the framework you're using — it's not uncommon for frameworks to have dedicated APIs for configuring custom fonts to simplify the developer experience.

If the framework you're using doesn't have a recommended way of setting up custom fonts, the easiest way to add Inter is by pointing a <link> tag to the CDN:

<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />

Then add "Inter" to your "sans" font family in your tailwind.config.js file:

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  // ...
}

Optional: Install Heroicons

We're using Heroicons (an icon set we designed ourselves) in Catalyst any time we need icons, and Heroicons has been designed to integrate seamlessly with Catalyst projects.

If you'd like to use Heroicons in your own projects, you can install it via npm:

npm install @heroicons/react

The components in Catalyst are designed to work best with 16×16 icons, so import the icons you need from @heroicons/react/16/solid:

import { Button } from '@/components/button'
import { PlusIcon } from '@heroicons/react/16/solid'

function Example() {
  return (
    <Button>
      <PlusIcon />
      Add item
    </Button>
  )
}

Framework integration examples

By default, the Link component in Catalyst renders a plain HTML <a> element. These examples show you how to update your Link component to use the Link component provided by your framework or routing library.

Integrating with Next.js

Update your link.tsx or link.jsx file to use the Link component from Next.js:

import { DataInteractive as HeadlessDataInteractive } from '@headlessui/react'
import NextLink, { type LinkProps } from 'next/link'
import React from 'react'

export const Link = React.forwardRef(function Link(
  props: LinkProps & React.ComponentPropsWithoutRef<'a'>,
  ref: React.ForwardedRef<HTMLAnchorElement>
) {
  return (
    <HeadlessDataInteractive>
      <NextLink {...props} ref={ref} />
    </HeadlessDataInteractive>
  )
})

Integrating with Remix

Update your link.tsx or link.jsx file to use the Link component from Remix:

import { DataInteractive as HeadlessDataInteractive } from '@headlessui/react'
import { Link as RemixLink, type LinkProps } from '@remix-run/react'
import React from 'react'

export const Link = React.forwardRef(function Link(
  props: { href: string | LinkProps['to'] } & Omit<LinkProps, 'to'>,
  ref: React.ForwardedRef<HTMLAnchorElement>
) {
  return (
    <HeadlessDataInteractive>
      <RemixLink {...props} to={props.href} ref={ref} />
    </HeadlessDataInteractive>
  )
})

Integrating with Inertia.js

Update your link.tsx or link.jsx file to use the Link component from Inertia.js:

import { DataInteractive as HeadlessDataInteractive } from '@headlessui/react'
import { Link as InertiaLink, type InertiaLinkProps } from '@inertiajs/react'
import React from 'react'

export const Link = React.forwardRef(function Link(
  props: InertiaLinkProps,
  ref: React.ForwardedRef<HTMLAnchorElement>
) {
  return (
    <HeadlessDataInteractive>
      <InertiaLink {...props} ref={ref} />
    </HeadlessDataInteractive>
  )
})