Skip to main content
Zag is a headless component library that models UI interactions as finite state machines. Write your component logic once and use it across React, Vue, Solid, Svelte, and Preact — with full accessibility built in.

Get Started

Learn what Zag is and why state machines make better UI components.

Installation

Install Zag and connect it to your framework in minutes.

Components

Browse 50+ production-ready component machines.

Build Your Own

Create custom state machine components for your design system.

Why Zag?

Framework Agnostic

One codebase for React, Vue, Solid, Svelte, and Preact via lightweight adapters.

Accessible by Default

Every component follows WAI-ARIA authoring practices — keyboard, focus, and ARIA handled automatically.

Headless

Zero styles. Bring your own CSS, Tailwind, CSS Modules, or any styling solution.

State Machine Powered

Built on statecharts — predictable, testable, and easy to reason about.

TypeScript First

Fully typed APIs with schema-based type inference throughout.

Incremental Adoption

Each component is a separate npm package — install only what you need.

Quick start

1

Install a component machine

Install the machine for the component you want to use, plus the adapter for your framework.
npm install @zag-js/tooltip @zag-js/react
2

Use the machine in your component

Call useMachine to start the state machine, then connect to get prop getters for your elements.
import { useMachine, normalizeProps } from "@zag-js/react"
import * as tooltip from "@zag-js/tooltip"
import { useId } from "react"

export function Tooltip() {
  const service = useMachine(tooltip.machine, { id: useId() })
  const api = tooltip.connect(service, normalizeProps)

  return (
    <>
      <button {...api.getTriggerProps()}>Hover me</button>
      {api.open && (
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>Tooltip content</div>
        </div>
      )}
    </>
  )
}
3

Style with CSS

Use data-part and data-* state attributes to style components using any CSS approach.
[data-part="content"] {
  background: #111;
  color: #fff;
  padding: 4px 8px;
  border-radius: 4px;
}

[data-part="trigger"][data-state="open"] {
  outline: 2px solid currentColor;
}

Explore components

Form inputs

Checkbox, Switch, Radio Group, Number Input, Tags Input, Editable, Pin Input, Slider

Overlays

Dialog, Popover, Tooltip, Hover Card, Menu, Combobox, Select

Navigation

Tabs, Accordion, Pagination, Steps, Tree View, Navigation Menu

Date & Time

Date Picker, Timer, Carousel, Progress, Tour

Build docs developers (and LLMs) love