Skip to content
Destyler Destyler Destyler
A Build UI for
Your design system
Framework-agnostic state machines and unstyled interaction primitives for building your own design system.

Zero-Styling Freedom

Your design system, your rules. Every component starts as a blank canvas ready for your creativity.

Truly Composable

Build complex UIs effortlessly with modular components that work seamlessly together.

Accessibility Foundations

Keyboard interactions and ARIA patterns provide a foundation. Validate the accessibility of your complete application, including its styling and content.

State Machine Powered

Predictable behavior, fewer bugs. State machines ensure rock-solid component interactions.

Dialog.vue
          
<script setup lang="ts">
import * as dialog from '@destyler/dialog'
import normalizeProps, useMachine from '@destyler/vue'
import computed, useId from 'vue'
const [state, send] = useMachine(dialog.machine(
id: useId(),
))
const api = computed(() => dialog.connect(state.value, send, normalizeProps))
</script>
<template>
<button v-bind="api.getTriggerProps()">
Open Dialog
</button>
<Teleport v-if="api.open" to="body">
<div>
<div v-bind="api.getBackdropProps()" />
<div v-bind="api.getPositionerProps()">
<div v-bind="api.getContentProps()">
<h2 v-bind="api.getTitleProps()">
Edit profile
</h2>
<p v-bind="api.getDescriptionProps()">
Make changes to your profile here. Click save when you are done.
</p>
<button v-bind="api.getCloseTriggerProps()">
<div />
</button>
<input placeholder="Enter name...">
<button>
Save Changes
</button>
</div>
</div>
</div>
</Teleport>
</template>
Dialog.tsx
import * as dialog from '@destyler/dialog'
import { normalizeProps, useMachine } from '@destyler/react'
import { useId } from 'react'
import { createPortal } from 'react-dom'
export default function Dialog() {
const [state, send] = useMachine(dialog.machine({
id: useId(),
}))
const api = dialog.connect(state, send, normalizeProps)
return (
<>
<button {...api.getTriggerProps()}>
Open Dialog
</button>
{api.open && createPortal(
<div>
<div {...api.getBackdropProps()} />
<div {...api.getPositionerProps()}>
<div {...api.getContentProps()}>
<h2 {...api.getTitleProps()}>
Edit profile
</h2>
<p {...api.getDescriptionProps()}>
Make changes to your profile here. Click save when you are done.
</p>
<button {...api.getCloseTriggerProps()}>
<div />
</button>
<input placeholder="Enter name..." />
<button>
Save Changes
</button>
</div>
</div>
</div>,
document.body,
)}
</>
)
}
Dialog.svelte
<script lang="ts">
import * as dialog from '@destyler/dialog'
import { normalizeProps, useMachine, portal } from '@destyler/svelte'
const id = $props.id()
const [state, send] = useMachine(dialog.machine({ id }))
const api = $derived(dialog.connect(state, send, normalizeProps))
</script>
<button {...api.getTriggerProps()}>
Open Dialog
</button>
{#if api.open}
<div use:portal>
<div {...api.getBackdropProps()} ></div>
<div {...api.getPositionerProps()}>
<div {...api.getContentProps()}>
<h2 {...api.getTitleProps()}>
Edit profile
</h2>
<p {...api.getDescriptionProps()}>
Make changes to your profile here. Click save when you are done.
</p>
<button {...api.getCloseTriggerProps()}>
<div ></div>
</button>
<input placeholder="Enter name...">
<button >
Save Changes
</button>
</div>
</div>
</div>
{/if}
Dialog.tsx
import * as dialog from '@destyler/dialog'
import { normalizeProps, useMachine } from '@destyler/solid'
import { createMemo, createUniqueId } from 'solid-js'
import { Portal } from 'solid-js/web'
export default function Dialog() {
const [state, send] = useMachine(dialog.machine({
id: createUniqueId(),
}))
const api = createMemo(() => dialog.connect(state, send, normalizeProps))
return (
<>
<button {...api().getTriggerProps()}>
Open Dialog
</button>
{ api().open && (
<Portal mount={document.body}>
<div>
<div {...api().getBackdropProps()} />
<div {...api().getPositionerProps()}>
<div {...api().getContentProps()}>
<h2 {...api().getTitleProps()}>
Edit profile
</h2>
<p {...api().getDescriptionProps()}>
Make changes to your profile here. Click save when you are done.
</p>
<button {...api().getCloseTriggerProps()}>
<div />
</button>
<input placeholder="Enter name..." />
<button>
Save Changes
</button>
</div>
</div>
</div>
</Portal>
)}
</>
)
}

Build your design system with xstate component today

Finite state machines for building accessible design systems and UI components. Works with React, Vue and Solid.

Get started

Build with Destyler

See What's Possible

Explore real-world applications built by developers who trust Destyler. From pepper to enterprises, see how our xstate components power modern web experiences.