Home

Awesome

<a href="https://zagjs.com/" > <img alt="Zag.js hero image" src="https://repository-images.githubusercontent.com/383777434/87c5d462-1c65-45d7-9561-3f3f64d814f4"></img> </a>

Zag

<p> <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@zag-js/core.svg?style=flat"/> <img alt="Github Stars" src="https://badgen.net/github/stars/chakra-ui/zag" /> <a href="https://zagjs.com/discord"> <img alt="Discord" src="https://img.shields.io/discord/660863154703695893.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2" /> </a> </p>

Finite state machines for accessible JavaScript components


Documentation

To see the documentation, visit zagjs.com/

Releases

For changelog, Check CHANGELOG.md


Problem

With the rise of design systems and component-driven development, there's an endless re-implementation of common component patterns (Tabs, Menu, Modal, etc.) in multiple frameworks.

Most of these implementations seem to be fairly similar in spirit, the differences being around the reactivity and effects systems for the framework (e.g. useState, useEffect in React.js). Framework specific solutions tend to grow in complexity over time and often become hard to understand, debug, improve or test.

Solution

Zag is a JavaScript API that implements common component patterns using the state machine methodology.

Installation

npm i --save @zag-js/{component}

# or

yarn add @zag-js/{component}

{component} represents any component machine like dialog (@zag-js/dialog), tooltip (@zag-js/tooltip) , etc.

For framework specific solutions, we provide simple wrappers to help you consume the component state machines.

Usage

import { normalizeProps, useMachine } from "@zag-js/react"
import * as toggle from "@zag-js/toggle-group"
import { useId } from "react"

export function ToggleGroup() {
  const [state, send] = useMachine(toggle.machine({ id: useId() }))
  const api = toggle.connect(state, send, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <button {...api.getItemProps({ value: "bold" })}>B</button>
      <button {...api.getItemProps({ value: "italic" })}>I</button>
      <button {...api.getItemProps({ value: "underline" })}>U</button>
    </div>
  )
}

Guiding Principles


Fun Facts

Zag means to take a sharp change in direction. This clearly describes our approach of using state machines to power the logic behind UI components.

Teasers


Commands

Build commands

Our build is managed with esbuild and turborepo to provide fast, concurrent builds across the packages.

Examples

Since zag is framework agnostic, we need a way to test it within a framework. The examples/ directory includes starter projects for the frameworks we support.

E2E Tests

We've setup end-to-end tests for every machine we built. We use Playwright for testing and we ensure that the component works the same way regardless of the framework.

Contributing new machines/features

Other commands

Website


Inspirations


Contributions

Looking to contribute? Look for the Good First Issue label.

🐛 Bugs

Please file an issue for bugs, missing documentation, or unexpected behavior.

💡 Feature Requests

Please file an issue to suggest new features. Vote on feature requests by adding a 👍. This helps maintainers prioritize what to work on.


License

MIT © Segun Adebayo