Melt UI
Headless builders for Svelte.
Melt UI takes a different route from every other headless library here. It does not give you components at all. It gives you builders: functions that return element attribute bags and state stores, which you spread onto your own markup with a Svelte action.
At a glance
| Install | npm install @melt-ui/svelte |
| API shape | builders, not components |
| Styling | none, your markup entirely |
| Svelte 5 | a runes-based rewrite is published separately |
| MCP server | not published |
| License | MIT |
Install
npm install @melt-ui/svelte
What the code looks like
This is the whole idea. There is no <Dialog.Root> wrapper anywhere: your own elements receive the behaviour through use:melt.
<script lang="ts">
import { createDialog, melt } from '@melt-ui/svelte'
const {
elements: { trigger, overlay, content, title, close },
states: { open }
} = createDialog()
</script>
<button use:melt={$trigger} class="btn">Rename</button>
{#if $open}
<div use:melt={$overlay} class="overlay"></div>
<div use:melt={$content} class="panel">
<h2 use:melt={$title}>Rename project</h2>
<button use:melt={$close} class="btn">Cancel</button>
</div>
{/if}
Why that matters
No wrapper components means no extra DOM nodes, no fighting a library's element structure, and complete freedom over markup, transitions and conditional rendering. You keep Svelte's {#if} and its transition directives instead of learning a library's animation API.
Check your Svelte version first
The original package targets Svelte 4 stores. A separate runes-based rewrite exists for Svelte 5 under a different package. Confirm which one matches your project before installing, because the APIs are not interchangeable.
Choose it if
- You want zero imposed DOM structure and full control over markup.
- You are comfortable with the builder pattern and want the smallest possible abstraction.
Look elsewhere if
- You want a conventional component API. Bits UI is the more familiar shape.
- You want one obvious install path. The Svelte 4 and Svelte 5 split is a real papercut.