Skip to content

The application UI kit for React and Vue.

Seventy-three components and layouts you copy into your project, built on Tailwind CSS v4. Same API on both frameworks.

npm install @headlessui/react motion clsx @heroicons/react
pnpm add @headlessui/react motion clsx @heroicons/react
yarn add @headlessui/react motion clsx @heroicons/react
bun add @headlessui/react motion clsx @heroicons/react
npm install reka-ui motion-v @heroicons/vue
pnpm add reka-ui motion-v @heroicons/vue
yarn add reka-ui motion-v @heroicons/vue
bun add reka-ui motion-v @heroicons/vue

Date range picker

Docs

Two calendars, presets, keyboard navigation.

Country and phone

Docs

Flags, dial codes, numbers formatted as you type.

One-time code

Docs

Six boxes, paste-aware, auto-advance.

Type any six digits.

Multi-select and tags

Docs

Search, create on the fly, remove with Backspace.

  • design
  • frontend

Overlays and toasts

Docs

A command palette on ⌘K, focus-trapped dialogs, toasts on Sonner.

Stats and meters

Docs

Bars under the figure, a qualified change, an animated meter.

Revenue
$12,480
14% up on last month (good)
Sign-ups
1,284
9% down on last month (bad)
Storage6.8 of 10 GB

Catalogue

Seventy-three components, twelve categories.

From a page shell to a single status dot. Each category has its own page in the docs, and every component ships with its examples and its API.

Auth layout, Detail layout, Sidebar layout, Split view and 1 more.

12 Rue de la Paix, 75002 Paris, France

Collapsible section, Detail header, Divider, Heading and 4 more.

PNG or JPEG, 512 by 512.

Code input, Date picker, Date range picker, Fieldset and 7 more.

Checkbox, Combobox, Country select, Listbox and 5 more.

Confirm dialog, Dialog, Form dialog, Slideover and 2 more.

Breadcrumbs, Command palette, Navbar, Pagination and 3 more.

pay_3K9dQ

22 Sep

$1,240.00

pay_8Fh2L

21 Sep

$86.00

Data table, Export menu, Filter bar, Table and 1 more.

Customer
Daniel Essomba
Status
active
Reference
cus_8F3K2QW

Avatar, Badge, Description list, Fact list and 2 more.

  1. Payment captured

  2. Mariam added a note

    Customer asked for a copy of the invoice.

  3. Invoice sent

Notes, Notification, Timeline.

Revenue

$12,480

Sign-ups

1,284

API calls

8,400 of 10,000

Meter, Sparkline, Stat band.

Your trial ends in three days.

Saving changes…

Alert, Empty page, Empty state, Notice and 3 more.

73

Components and layouts in 12 categories, with the same API in React and Vue. Copied into your project, yours to change.

Browse all

Principles

Built the way you would build it yourself.

Four things that are true today, nothing that is still on a roadmap.

Yours, in your repo.

Every component is a file you copy into your project. Rename it, restyle it, delete what you do not need. Nothing to update, nothing to wait on.

src/components/button.tsx

import * as Headless from '@headlessui/react'
import clsx from 'clsx'
import React, { forwardRef } from 'react'
import { Link } from './link'

const styles = {
  base: [
    // Base
    'relative isolate inline-flex items-baseline justify-center gap-x-2 rounded-lg border text-base/6 font-semibold',
    // Sizing
    'px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/6',

src/components/button.vue

<script setup lang="ts">
import { computed } from 'vue'
import { vInteractions } from './interactions'
import Link from './link.vue'
import TouchTarget from './touch-target.vue'

const styles = {
  base: [
    // Base
    'relative isolate inline-flex items-baseline justify-center gap-x-2 rounded-lg border text-base/6 font-semibold',
    // Sizing
    'px-[calc(--spacing(3.5)-1px)] py-[calc(--spacing(2.5)-1px)] sm:px-[calc(--spacing(3)-1px)] sm:py-[calc(--spacing(1.5)-1px)] sm:text-sm/6',

One API, two frameworks.

The React kit builds on Headless UI, the Vue kit on Reka UI. Same names, same props, same slots, so the docs read the same whichever you pick.

import { Button } from '@/components/button'

export default function Page() {
  return (
    <Button color="light" href="/settings">
      Settings
    </Button>
  )
}
<script setup lang="ts">
import Button from '@/components/button.vue'
</script>

<template>
  <Button color="light" href="/settings">
    Settings
  </Button>
</template>

Every state, in the file.

Hover, focus, active, open, disabled: each one is a data attribute, styled with plain Tailwind classes you can read and change.

button.tsx

const styles = {
  base: [
    // Focus
    'focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-accent-500',
    // Disabled
    'data-disabled:opacity-50',
  ],
  plain: [
    // Hover and active
    'border-transparent text-zinc-950 data-active:bg-zinc-950/5 data-hover:bg-zinc-950/5',
    // Dark mode
    'dark:text-white dark:data-active:bg-white/10 dark:data-hover:bg-white/10',
  ],
}

button.vue

const styles = {
  base: [
    // Focus
    'focus:not-data-focus:outline-hidden data-focus:outline-2 data-focus:outline-offset-2 data-focus:outline-accent-500',
    // Disabled
    'data-disabled:opacity-50',
  ],
  plain: [
    // Hover and active
    'border-transparent text-zinc-950 data-active:bg-zinc-950/5 data-hover:bg-zinc-950/5',
    // Dark mode
    'dark:text-white dark:data-active:bg-white/10 dark:data-hover:bg-white/10',
  ],
}

Tokens, not a theme file.

Tailwind CSS v4 tokens, with an accent you set once as CSS variables. Dark mode is a variant, not a second stylesheet.

app.css

@import "tailwindcss";

@theme inline {
  --color-accent-500: var(--accent-500, var(--color-blue-500));
  --color-accent-600: var(--accent-600, var(--color-blue-600));
}

:root {
  --accent-500: oklch(0.65 0.118 184.7);
  --accent-600: oklch(0.6 0.118 184.7);
}
Storage68%

Theme

Your brand color, in seven lines.

Pick a hue. The kit derives the seven stops it reads, and every component follows, in light and in dark. Paste the block in your CSS and you are done.

Accent hue

184.7°

Notifications

What we send, and how often.

On this device only.

Storage6.8 of 10 GB
September 2026

app.css

:root {
  --accent-200: oklch(0.882 0.033 184.7);
  --accent-300: oklch(0.809 0.058 184.7);
  --accent-400: oklch(0.707 0.091 184.7);
  --accent-500: oklch(0.65 0.118 184.7);
  --accent-600: oklch(0.6 0.118 184.7);
  --accent-700: oklch(0.53 0.125 184.7);
  --accent-900: oklch(0.379 0.081 184.7);
}