All Projects → mattjennings → headlessui-svelte

mattjennings / headlessui-svelte

Licence: other
No description, website, or topics provided.

Programming Languages

typescript
32286 projects
Svelte
593 projects
javascript
184084 projects - #8 most used programming language

This project is no longer maintained

Please use @rgossiaux/svelte-headlessui instead as it is a full port of Headless UI. I had only managed to complete the Switch component, but @rgossiaux has done a fantastic job in getting full API coverage.


headlessui-svelte

Unofficial Headless UI Svelte components. Very much a work in progress, use with caution.

npm install @mattjennings/headlessui-svelte

Usage

See Components for which are available.

The goal is to keep the API as close to @headlessui/react as possible.

<script>
  import { Switch } from "@mattjennings/headlessui-svelte";

  let enabled = false;
</script>

<Switch.Group>
  <div class="flex items-center">
    <Switch.Label class="mr-4">Enable notifications</Switch.Label>
    <Switch
      bind:checked={enabled}
      class={`${
        enabled ? "bg-blue-600" : "bg-gray-200"
      } relative inline-flex items-center h-6 rounded-full w-11 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500`}>
      <span
        class={`${
          enabled ? "translate-x-6" : "translate-x-1"
        } inline-block w-4 h-4 transform bg-white rounded-full transition-transform`} />
    </Switch>
  </div>
</Switch.Group>

For comparison, this is the @headlessui/react version:

import { useState } from 'react'
import { Switch } from '@headlessui/react'

export default function CustomLabelExample() {
  const [enabled, setEnabled] = useState(false)

  return (
    <Switch.Group>
      <div className="flex items-center">
        <Switch.Label className="mr-4">Enable notifications</Switch.Label>
        <Switch
          checked={enabled}
          onChange={setEnabled}
          className={`${
            enabled ? 'bg-blue-600' : 'bg-gray-200'
          } relative inline-flex items-center h-6 rounded-full w-11 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500`}
        >
          <span
            className={`${
              enabled ? 'translate-x-6' : 'translate-x-1'
            } inline-block w-4 h-4 transform bg-white rounded-full transition-transform`}
          />
        </Switch>
      </div>
    </Switch.Group>
  )
}

Caveats

Event forwarding

Until the on:* syntax is supported in Svelte, each internal component will need to explicitly forward every possible event so that they can be used. The scope of this package is small enough that I could do that, but it would be annoying.

One idea is to go the React-way and use on-* props for event listeners. This would not be the ideal API, but it would work.

For now, components will at least emit the following events:

  • click
  • focus
  • blur
  • keypress
  • keydown
  • keyup

Dynamic elements

Until dynamic elements are supported in Svelte, I'm using a modified internal version of svelte-elements to support the as prop.

SvelteKit

You might get the following error (or similar) when running in development with SvelteKit:

Cannot read property 'default' of null

This can be fixed by either restarting the dev server (for some reason it only happens the first time), or adding the library to kit.vite.optimizeDeps.exclude in svelte.config.js:

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    vite: {
      optimizeDeps: {
        exclude: ['@mattjennings/headlessui-svelte']
      }
    }
  }
}

Components

  • Switch
  • Menu
  • Listbox
  • Disclosure
  • Dialog
  • Popover
  • Radio Group
  • Transition
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].