# Using Tailwind UI The original Headless UI libraries for React & Vue were made by Tailwind Labs in order to serve as a foundation for [Tailwind UI](https://tailwindui.com/), a paid set of component templates. While this Svelte port has no affiliation with Tailwind Labs or Tailwind UI, one of the main motivations behind it is to make it easy to use Tailwind UI with Svelte. This page contains tips and instructions for converting their provided snippets to work with Svelte. You can convert either the React or the Vue templates to Svelte, if you are more familiar with one or the other framework. If you are unfamiliar with both React and Vue, below are some more comprehensive instructions for converting the React snippets. ## General concerns ### Heroicons Many Tailwind UI examples use the [heroicons](https://heroicons.com/) icon library. This library has official wrappers for React and Vue, but not for Svelte. For Svelte, you can use the wrapper library [@rgossiaux/svelte-heroicons](https://github.com/rgossiaux/svelte-heroicons), which provides the same API and component names as the official Tailwind wrappers, making it faster to convert Tailwind UI code to Svelte. Of course, you are free to use any other library you wish instead, if you prefer. ## Differences from React ### Component names The React library uses a `.` in the names of many components: `Tab.Group`, `Listbox.Button`, etc. The Svelte library does not use this pattern and instead exports every component under its own name with no dot: `TabGroup`, `ListboxButton`, etc. ### `useState` State declared with `useState` in React becomes just a normal variable in Svelte: ```jsx import { useState } from 'react' import { Switch } from '@headlessui/react' function MyToggle() { const [enabled, setEnabled] = useState(false) return ( // ... ) } ``` becomes ```svelte enabled = e.detail}> ``` ### JSX camelCased attribute names In React, some HTML attributes have different names from the standard ones that are used in Svelte. These are covered in the [React documentation](https://reactjs.org/docs/dom-elements.html#differences-in-attributes), but we repeat the most important differences here: * `className` in React becomes `class` in Svelte * `htmlFor` in React becomes `for` in Svelte * SVG attributes in React like `strokeWidth`, `strokeLinecap`, etc. become `stroke-width`, `stroke-linecap`, etc. in Svelte ### Event handlers In React, you pass event handlers using camelCased names: ```jsx import { useState } from 'react' import { Dialog } from '@headlessui/react' function MyDialog() { let [isOpen, setIsOpen] = useState(true) return ( setIsOpen(false)}> Deactivate account This will permanently deactivate your account

Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.

) } ``` In Svelte, you instead use the `on:` directive: ```svelte (isOpen = false)}> Deactivate account This will permanently deactivate your account

Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.

``` Furthermore, in the React library, event handlers will be called with the their data directly: ```jsx // ... ``` In the Svelte version, your handler will be passed a `CustomEvent` object, and you need to look at its `.detail` property: ```svelte selectedPerson = e.detail}> ``` ### Render props The React components make use of render props: ```jsx {({ close }) => ( )} ``` The Svelte equivalent of this pattern is to use [slot props](https://svelte.dev/tutorial/slot-props): ```svelte ``` ### Conditional rendering The standard way to do conditional rendering in React is with the `&&` operator: ```jsx {({ open }) => ( <> Is team pricing available? {open && (
{/* Using `static`, `Disclosure.Panel` is always rendered and ignores the `open` state. */} {/* ... */}
)} )}
``` In Svelte, you use the `{#if}` templating syntax instead: ```svelte Is team pricing available? {#if open}
{/if}
``` ### Iteration / mapping Tailwind UI frequenty does iteration using `Array.prototype.map()`: ```jsx {selectedPerson.name} {people.map((person) => ( {person.name} ))} ``` In Svelte, you accomplish this by using the `{#each}` template syntax: ```svelte selectedPerson = e.detail}> {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` Note that the key moves from the `key=` prop in React into the `{#each}` statement in Svelte. Don't forget to add this! ### Using a dynamic component In React, you can use a variable as a tag name: ```jsx {solutions.map((item) => ( // ...