Headless UI Menu component React example
A custom dropdown menu in React using Headless UI shows compound component usage with render props for state access. Example: import { Menu } from '@headlessui/react'; function MyDropdown() { return (<Menu as="div" className="relative"><Menu.Button className="rounded bg-blue-600 px-4 py-2 text-white ...">Options</Menu.Button><Menu.Items className="absolute right-0 mt-1"><Menu.Item>{({ active }) => (<a className={`${active && "bg-blue-500 text-white"} ...`} href="/account-settings">Account settings</a>)}</Menu.Item><Menu.Item>{({ active }) => (<a className={`${active && "bg-blue-500 text-white"} ...`} href="/documentation">Documentation</a>)}</Menu.Item><Menu.Item disabled><span className="opacity-75 ...">Invite a friend (coming soon!)</span></Menu.Item></Menu.Items></Menu>); }
Tailwind UI React example with Headless UI and Transitions
A complete React example showing a list of people with a Menu dropdown for each person, using Headless UI Menu and Transition components. The example demonstrates: importing Menu and Transition from @headlessui/react, using Fragment from react, importing icons from @heroicons/react/solid, defining data as a constant array, mapping over people to render list items, using Menu as a compound component with Menu.Button and Menu.Items, using Transition with enter/leave animation classes, using render props to access active state from Menu.Item. Full code: import { Menu, Transition } from "@headlessui/react"; import { DotsVerticalIcon } from "@heroicons/react/solid"; import { Fragment } from "react"; const people = [{name: "Calvin Hawkins", email: "calvin.hawkins@example.com", image: "https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"}, {name: "Kristen Ramos", email: "kristen.ramos@example.com", image: "https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"}, {name: "Ted Fox", email: "ted.fox@example.com", image: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"}]; export default function Example() { return (<ul className="divide-y divide-gray-200">{people.map((person) => (<li key={person.email} className="flex py-4"><img className="h-10 w-10 rounded-full" src={person.image.src} alt="" /><div className="ml-3"><p className="text-sm font-medium text-gray-900">{person.name}</p><p className="text-sm text-gray-500">{person.email}</p></div><Menu as="div" className="relative ml-3 inline-block text-left">{({ open }) => (<><div><Menu.Button className="flex items-center rounded-full bg-gray-100 text-gray-400 hover:text-gray-600 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-gray-100 focus:outline-none"><span className="sr-only">Open options</span><DotsVerticalIcon className="h-5 w-5" aria-hidden="true" /></Menu.Button></div><Transition show={open} as={Fragment} enter="transition ease-out duration-100" enterFrom="transform opacity-0 scale-95" enterTo="transform opacity-100 scale-100" leave="transition ease-in duration-75" leaveFrom="transform opacity-100 scale-100" leaveTo="transform opacity-0 scale-95"><Menu.Items static className="ring-opacity-5 absolute right-0 mt-2 w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black focus:outline-none"><div className="py-1"><Menu.Item>{({ active }) => (<a href="#" className={classNames(active ? "bg-gray-100 text-gray-900" : "text-gray-700", "block px-4 py-2 text-sm")} >View details</a>)}</Menu.Item><Menu.Item>{({ active }) => (<a href="#" className={classNames(active ? "bg-gray-100 text-gray-900" : "text-gray-700", "block px-4 py-2 text-sm")} >Send message</a>)}</Menu.Item></div></Menu.Items></Transition></> )}</Menu></li>))}</ul>); }
Tailwind UI React and Vue example conversion approach
When converting Tailwind UI examples to React and Vue, the approach focuses on: (1) Using the correct syntax (JSX for React, single-file components for Vue), (2) Making transitions real with Headless UI transition components or Vue native transition, (3) Handling interactive elements with Headless UI components, (4) Converting repeated markup into basic loops for data-driven elements while keeping everything in one example, (5) Pulling icons from Heroicons library instead of inlining SVGs. The goal is to keep examples simple, maintain single-place visibility of all code, and avoid making architectural assumptions about how users will structure their components.
Headless UI Transition component for React
Headless UI provides a Transition component for React that allows you to add enter/leave animations to elements entirely using Tailwind classes. It is inspired by the Vue transition component. The component accepts props: show (boolean to control visibility), enter (classes applied during entire enter phase), enterFrom (classes at start of enter), enterTo (classes at end of enter), leave (classes applied during entire leave phase), leaveFrom (classes at start of leave), leaveTo (classes at end of leave). Example: <Transition show={isOpen} enter="transition-opacity duration-75" enterFrom="opacity-0" enterTo="opacity-100" leave="transition-opacity duration-150" leaveFrom="opacity-100" leaveTo="opacity-0">I will fade in and out</Transition>
Headless UI first release components
The first public release of Headless UI in October 2020 included React and Vue libraries with three components: Menu Button (dropdown), Listbox (custom select), and Switch (toggle). These components use compound components pattern with context (React) or provide/inject (Vue) to abstract complexity while remaining class-friendly for styling with Tailwind.
Headless UI v1.0 component library
Headless UI v1.0 released April 14, 2021, includes the following components: Menu Button (for dropdown menus with links or buttons), Listbox (for custom select implementations), Switch (for custom toggle switches), Disclosure (for showing/hiding content in place), Dialog (for modal dialogs and mobile navigation), Popover (for panels that pop up on top of the page), and Radio Group (for custom radio selection UIs). These components handle complex behavior like focus management and nested focus management.
Elements React integration example
Example of using Elements in React: use custom elements as JSX with camelCase class names (className), no special setup required. el-dropdown and el-menu work as drop-in replacements for framework-specific UI libraries. Use standard React patterns like onClick handlers on buttons and conditional rendering. The custom elements are framework-agnostic.
Elements framework compatibility
Elements custom elements work with any JavaScript framework that supports HTML, including Svelte, Rails, React, and vanilla HTML. Since they are based on standard HTML custom elements and the popover API, they function anywhere a script tag can be used. Elements can be used in React as an alternative to framework-specific libraries like Headless UI or React Aria.
Elements Svelte integration example
Example of using Elements in Svelte: bind input value to state with bind:value directive, wrap content in el-autocomplete custom element, include input and button children, use el-options with anchor and popover for dropdown, fill el-option elements with values. Svelte's two-way binding works directly with the custom form elements.
Elements Rails integration example
Example of using Elements in Rails: use el-select with name attribute (e.g., name='car_id') so the value is included in form submissions. Set value to a dynamic value from the controller (e.g., value='<%= @selected_car.id %>'). Use el-selectedcontent to display the selected item name. Loop through options using el-option elements with value set to the database id. The form_with helper works as normal; Elements integrates as a standard form control.
Vue transition component utility-friendly API
Vue's built-in <transition> component supports enter/leave transitions with utility-friendly attributes: enter-active-class (utilities applied during enter), enter-from-class (utilities for start of enter), enter-to-class (utilities for end of enter), leave-active-class (utilities applied during leave), leave-from-class (utilities for start of leave), and leave-to-class (utilities for end of leave). Example: <transition enter-active-class="transition-opacity duration-75" enter-from-class="opacity-0" enter-to-class="opacity-100" leave-active-class="transition-opacity duration-150" leave-from-class="opacity-100" leave-to-class="opacity-0">
Transition component props for styling enter/leave states
The Transition component from @tailwindui/react supports six props for controlling transitions: enter and leave props accept utility classes applied throughout the transition phase, enterFrom and leaveFrom props accept utility classes for the initial state, and enterTo and leaveTo props accept utility classes for the final state. This allows composition of Tailwind utilities to create enter/leave animations.
@tailwindui/react Transition component API
The @tailwindui/react library provides a <Transition> component for enter/leave transitions with utility-first styling. The component accepts the following props: show (boolean to control visibility), enter (utility classes applied during enter transition), enterFrom (utility classes for the start state of enter), enterTo (utility classes for the end state of enter), leave (utility classes applied during leave transition), leaveFrom (utility classes for the start state of leave), and leaveTo (utility classes for the end state of leave). Example usage: <Transition show={isOpen} enter="transition-opacity duration-75" enterFrom="opacity-0" enterTo="opacity-100" leave="transition-opacity duration-150" leaveFrom="opacity-100" leaveTo="opacity-0">content</Transition>