Skip to content
Destyler Destyler Destyler

Getting Started

A quick tutorial to get you up and running with Destyler.

The next release containing the Node support migration requires Node.js 22.22.3 or newer. See Node support and migration before upgrading an application from Node 20.

Implementing a Popover​

In this quick tutorial, we will install and style the Popover component.

  1. Install the package

    Install the component from your command line.

    Terminal window
          
            
    npm install @destyler/popover @destyler/vue
    Terminal window
          
            
    npm install @destyler/popover @destyler/react
    Terminal window
          
            
    npm install @destyler/popover @destyler/svelte
    Terminal window
          
            
    npm install @destyler/popover @destyler/solid
  2. Import the parts

    Import and structure the parts.

    Popover.vue
    <script setup lang="ts">
    import * as popover from "@destyler/popover"
    import { normalizeProps, useMachine } from "@destyler/vue"
    import { computed,useId } from "vue"
    const [state, send] = useMachine(popover.machine({ id: useId() }))
    const api = computed(() => popover.connect(state.value, send, normalizeProps))
    </script>
    <template>
    <div>
    <button v-bind="api.getTriggerProps()">
    Click me
    </button>
    <div v-bind="api.getPositionerProps()">
    <div v-bind="api.getContentProps()">
    <div v-bind="api.getTitleProps()">
    Presenters
    </div>
    <div v-bind="api.getDescriptionProps()">
    Description
    </div>
    <button>
    Action Button
    </button>
    <button v-bind="api.getCloseTriggerProps()"/>
    </div>
    </div>
    </div>
    </template>
    Popover.tsx
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/react'
    import { useId } from 'react'
    export default function Popover() {
    const [state, send] = useMachine(popover.machine({ id: useId() }))
    const api = popover.connect(state, send, normalizeProps)
    return (
    <>
    <div>
    <button {...api.getTriggerProps()}>
    Click me
    </button>
    <div {...api.getPositionerProps()}>
    <div {...api.getContentProps()}>
    <div {...api.getTitleProps()}>
    Presenters
    </div>
    <div {...api.getDescriptionProps()}>
    Description
    </div>
    <button>
    Action Button
    </button>
    <button {...api.getCloseTriggerProps()}>
    </button>
    </div>
    </div>
    </div>
    </>
    )
    }
    Popover.svelte
    <script lang="ts">
    import * as popover from "@destyler/popover"
    import { normalizeProps, useMachine } from "@destyler/svelte"
    const id = $props.id();
    const [state, send] = useMachine(popover.machine({ id }));
    const api = $derived(popover.connect(state, send, normalizeProps));
    </script>
    <div>
    <button {...api.getTriggerProps()}>
    Click me
    </button>
    <div {...api.getPositionerProps()}>
    <div {...api.getContentProps()}>
    <div {...api.getTitleProps()}>
    Presenters
    </div>
    <div {...api.getDescriptionProps()}>
    Description
    </div>
    <button>
    Action Button
    </button>
    <button {...api.getCloseTriggerProps()}></button>
    </div>
    </div>
    </div>
    Popover.tsx
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/solid'
    import { createMemo, createUniqueId } from 'solid-js'
    export default function PopoverPage() {
    const [state, send] = useMachine(popover.machine({ id: createUniqueId() }))
    const api = createMemo(() => popover.connect(state, send, normalizeProps))
    return (
    <>
    <div>
    <button
    {...api().getTriggerProps()}
    >
    Click me
    </button>
    <div {...api().getPositionerProps()}>
    <div
    {...api().getContentProps()}
    >
    <div
    {...api().getTitleProps()}
    >
    Presenters
    </div>
    <div
    {...api().getDescriptionProps()}
    >
    Description
    </div>
    <button>
    Action Button
    </button>
    <button
    {...api().getCloseTriggerProps()}
    >
    </button>
    </div>
    </div>
    </div>
    </>
    )
    }
  3. Style the component

    Style the component with CSS.

    <script setup lang="ts">
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/vue'
    import { computed, useId } from 'vue'
    import './Popover.css'
    const [state, send] = useMachine(popover.machine({ id: useId() }))
    const api = computed(() => popover.connect(state.value, send, normalizeProps))
    </script>
    <template>
    <div>
    <button
    class="popover-trigger"
    v-bind="api.getTriggerProps()"
    >
    View Details
    </button>
    <div
    class="popover-positioner"
    v-bind="api.getPositionerProps()"
    >
    <div
    class="popover-content"
    v-bind="api.getContentProps()"
    >
    <div
    class="popover-title"
    v-bind="api.getTitleProps()"
    >
    Essential Information
    </div>
    <div
    class="popover-description"
    v-bind="api.getDescriptionProps()"
    >
    Explore our minimalist interface designed for maximum efficiency and clarity.
    </div>
    <button class="popover-button primary">
    Continue
    </button>
    <button
    class="popover-button secondary"
    v-bind="api.getCloseTriggerProps()"
    >
    Close
    </button>
    </div>
    </div>
    </div>
    </template>
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/react'
    import { useId } from 'react'
    import './Popover.css'
    export default function Popover() {
    const [state, send] = useMachine(popover.machine({ id: useId() }))
    const api = popover.connect(state, send, normalizeProps)
    return (
    <div>
    <button className="popover-trigger" {...api.getTriggerProps()}>
    View Details
    </button>
    <div className="popover-positioner" {...api.getPositionerProps()}>
    <div className="popover-content" {...api.getContentProps()}>
    <div className="popover-title" {...api.getTitleProps()}>
    Essential Information
    </div>
    <div className="popover-description" {...api.getDescriptionProps()}>
    Explore our minimalist interface designed for maximum efficiency and clarity.
    </div>
    <button className="popover-button primary">
    Continue
    </button>
    <button
    className="popover-button secondary"
    {...api.getCloseTriggerProps()}
    >
    Close
    </button>
    </div>
    </div>
    </div>
    )
    }
    <script lang="ts">
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/svelte'
    const id = $props.id();
    const [state, send] = useMachine(popover.machine({ id }));
    const api = $derived(popover.connect(state, send, normalizeProps));
    </script>
    <div>
    <button
    class="popover-trigger"
    {...api.getTriggerProps()}
    >
    View Details
    </button>
    <div
    class="popover-positioner"
    {...api.getPositionerProps()}
    >
    <div
    class="popover-content"
    {...api.getContentProps()}
    >
    <div
    class="popover-title"
    {...api.getTitleProps()}
    >
    Essential Information
    </div>
    <div
    class="popover-description"
    {...api.getDescriptionProps()}
    >
    Explore our minimalist interface designed for maximum efficiency and clarity.
    </div>
    <button class="popover-button primary">
    Continue
    </button>
    <button
    class="popover-button secondary"
    {...api.getCloseTriggerProps()}
    >
    Close
    </button>
    </div>
    </div>
    </div>
    <style>
    @import './Popover.css';
    </style>
    import * as popover from '@destyler/popover'
    import { normalizeProps, useMachine } from '@destyler/solid'
    import { createMemo, createUniqueId } from 'solid-js'
    import './Popover.css'
    export default function PopoverPage() {
    const [state, send] = useMachine(popover.machine({ id: createUniqueId() }))
    const api = createMemo(() => popover.connect(state, send, normalizeProps))
    return (
    <div>
    <button class="popover-trigger" {...api().getTriggerProps()}>
    View Details
    </button>
    <div class="popover-positioner" {...api().getPositionerProps()}>
    <div class="popover-content" {...api().getContentProps()}>
    <div class="popover-title" {...api().getTitleProps()}>
    Essential Information
    </div>
    <div class="popover-description" {...api().getDescriptionProps()}>
    Explore our minimalist interface designed for maximum efficiency and clarity.
    </div>
    <button class="popover-button primary">
    Continue
    </button>
    <button
    class="popover-button secondary"
    {...api().getCloseTriggerProps()}
    >
    Close
    </button>
    </div>
    </div>
    </div>
    )
    }
  4. Demo

    Here’s a complete demo.

Summary

The steps above outline briefly what’s involved in using a Destyler in your application.

These components are low-level enough to give you control over how you want to wrap them. You’re free to introduce your own high-level API to better suit the needs of your team and product.

In a few simple steps, we’ve implemented a fully accessible Popover component, without having to worry about many of its complexities.

  • Adheres to WAI-ARIA design pattern.

  • Can be controlled or uncontrolled (defaultOpen / open + onOpenChange, and the same pattern for checked/value).

  • Customize side, alignment, offsets, collision handling.

  • Focus is fully managed and customizable.

  • Dismissing and layering behavior is highly customizable.