# or
yarn add @zag-js/tabs @zag-js/solid
```

## Anatomy

To set up the tabs correctly, you'll need to understand its anatomy and how we
name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.



## Usage

First, import the tabs package into your project

```jsx
import * as tabs from "@zag-js/tabs"
```

The tabs package exports two key functions:

- `machine` â The state machine logic for the tabs widget.
- `connect` â The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
tabs machine in your project ð¥

```jsx
import * as tabs from "@zag-js/tabs"
import { normalizeProps, useMachine } from "@zag-js/solid"
import { createMemo, createUniqueId, For } from "solid-js"

const data = [
  { value: "item-1", label: "Item one", content: "Item one content" },
  { value: "item-2", label: "Item two", content: "Item two content" },
  { value: "item-3", label: "Item three", content: "Item three content" },
]

export function Tabs() {
  const service = useMachine(tabs.machine, {
    id: createUniqueId(),
    defaultValue: "item-1",
  })

  const api = createMemo(() => tabs.connect(service, normalizeProps))

  return (
    <div {...api().getRootProps()}>
      <div {...api().getListProps()}>
        <For each={data}>
          {(item) => (
            <button {...api().getTriggerProps({ value: item.value })}>
              {item.label}
            </button>
          )}
        </For>
      </div>
      <For each={data}>
        {(item) => (
          <div {...api().getContentProps({ value: item.value })}>
            <p>{item.content}</p>
          </div>
        )}
      </For>
    </div>
  )
}
```

### Setting the initially selected tab

To set the initially selected tab, pass the `defaultValue` property to the
machine's context.

```jsx {2}
const service = useMachine(tabs.machine, {
  defaultValue: "tab-1",
})
```

Subsequently, you can use the `api.setValue` function to programatically set the
selected tab.

```jsx
api.setValue("tab-2")
```

### Controlled tabs

To control the selected tab programmatically, pass the `value` and
`onValueChange` properties to the machine function.

```tsx
import { createSignal } from "solid-js"

export function ControlledTabs() {
  const [value, setValue] = createSignal("tab-1")

  const service = useMachine(tabs.machine, {
    get value() {
      return value()
    },
    onValueChange(details) {
      setValue(details.value)
    },
  })

  return (
    // ...
  )
}
```

### Changing the orientation

The default orientation of the tabs is horizontal. To change the orientation,
set the `orientation` property in the machine's context to `"vertical"`.

```jsx {2}
const service = useMachine(tabs.machine, {
  orientation: "vertical",
})
```

### Showing an indicator

To show an active indicator when a tab is selected, you add the
`tabIndicatorProps` object provided by the `connect` function.

```jsx {13}
// ...
return (
  <div {...api().getRootProps()}>
    <div {...api().getListProps()}>
      {data.map((item) => (
        <button
          {...api().getTriggerProps({ value: item.value })}
          key={item.value}
        >
          {item.label}
        </button>
      ))}
      <div {...api().getIndicatorProps()} />
    </div>
    {data.map((item) => (
      <div {...api().getContentProps({ value: item.value })} key={item.value}>
        <p>{item.content}</p>
      </div>
    ))}
  </div>
)
```

### Disabling a tab

To disable a tab, set the `disabled` property in the `getTriggerProps` to
`true`.

When a Tab is `disabled`, it is skipped during keyboard navigation and it is not
clickable.

```jsx
//...
<button {...api.getTriggerProps({ disabled: true })}></button>
//...
```

### Listening for events

- `onValueChange` â Callback invoked when the selected tab changes.
- `onFocusChange` â Callback invoked when the focused tab changes.

```jsx {2-7}
const service = useMachine(tabs.machine, {
  onFocusChange(details) {
    // details => { value: string | null }
    console.log("focused tab:", details.value)
  },
  onValueChange(details) {
    // details => { value: string }
    console.log("selected tab:", details.value)
  },
})
```

### Manual tab activation

By default, the tab can be selected when the receive focus from either the
keyboard or pointer interaction. This is called "automatic tab activation".

The other approach is "manual tab activation" which means the tab is selected
with the Enter key or by clicking on the tab.

```jsx {2}
const service = useMachine(tabs.machine, {
  activationMode: "manual",
})
```

### RTL Support

The tabs machine provides support right to left writing directions. In this
mode, the layout and keyboard interaction is flipped.

To enable RTL support, set the `dir` property in the machine's context to `rtl`.

```jsx {2}
const service = useMachine(tabs.machine, {
  dir: "rtl",
})
```

## Styling guide

### Selected state

When a tab is selected, a `data-selected` attribute is added to the trigger and
content elements.

```css
[data-part="trigger"][data-state="active"] {
  /* Styles for selected tab */
}

[data-part="content"][data-state="active"] {
  /* Styles for selected tab */
}
```

### Disabled state

When a tab is disabled, a `data-disabled` attribute is added to the trigger
element.

```css
[data-part="trigger"][data-disabled] {
  /* Styles for disabled tab */
}
```

### Focused state

When a tab is focused, you the `:focus` or `:focus-visible` pseudo-class to
style it.

```css
[data-part="trigger"]:focus {
  /* Styles for focused tab */
}
```

When any tab is focused, the list is given a `data-focus` attribute.

```css
[data-part="list"][data-focus] {
  /* Styles for when any tab is focused */
}
```

### Orientation styles

All parts of the tabs component have the `data-orientation` attribute. You can
use this to set the style for the horizontal or vertical tabs.

```css
[data-part="trigger"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical tabs */
}

[data-part="root"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical root */
}

[data-part="indicator"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical tab-indicator */
}

[data-part="list"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical list */
}
```

### The tab indicator

The tab indicator styles have CSS variables for the `transitionDuration` and
`transitionTimingFunction` defined in it.

The transition definition is applied when the selected tab changes to allow the
indicator move smoothly to the new selected tab.

```css
[data-part="indicator"] {
  --transition-duration: 0.2s;
  --transition-timing-function: ease-in-out;
}
```

You'll also need to set the styles for the indicator to match your design.

```css
[data-part="indicator"] {
  --transition-duration: 0.2s;
  --transition-timing-function: ease-in-out;
}
```

## Methods and Properties

### Machine Context

The tabs machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; trigger: (value: string) => string; list: string; content: (value: string) => string; indicator: string; }>`
Description: The ids of the elements in the tabs. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`loopFocus`**
Type: `boolean`
Description: Whether the keyboard navigation will loop from last tab to first, and vice versa.

**`value`**
Type: `string`
Description: The controlled selected tab value

**`defaultValue`**
Type: `string`
Description: The initial selected tab value when rendered.
Use when you don't need to control the selected tab value.

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: The orientation of the tabs. Can be `horizontal` or `vertical`
- `horizontal`: only left and right arrow key navigation will work.
- `vertical`: only up and down arrow key navigation will work.

**`activationMode`**
Type: `"manual" | "automatic"`
Description: The activation mode of the tabs. Can be `manual` or `automatic`
- `manual`: Tabs are activated when clicked or press `enter` key.
- `automatic`: Tabs are activated when receiving focus

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Callback to be called when the selected/active tab changes

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Description: Callback to be called when the focused tab changes

**`composite`**
Type: `boolean`
Description: Whether the tab is composite

**`deselectable`**
Type: `boolean`
Description: Whether the active tab can be deselected when clicking on it.

**`navigate`**
Type: `(details: NavigateDetails) => void`
Description: Function to navigate to the selected tab when clicking on it.
Useful if tab triggers are anchor elements.

**`dir`**
Type: `"ltr" | "rtl"`
Description: The document's text/writing direction.

**`id`**
Type: `string`
Description: The unique identifier of the machine.

**`getRootNode`**
Type: `() => ShadowRoot | Node | Document`
Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

### Machine API

The tabs `api` exposes the following methods:

**`value`**
Type: `string`
Description: The current value of the tabs.

**`focusedValue`**
Type: `string`
Description: The value of the tab that is currently focused.

**`setValue`**
Type: `(value: string) => void`
Description: Sets the value of the tabs.

**`clearValue`**
Type: `VoidFunction`
Description: Clears the value of the tabs.

**`setIndicatorRect`**
Type: `(value: string) => void`
Description: Sets the indicator rect to the tab with the given value

**`syncTabIndex`**
Type: `VoidFunction`
Description: Synchronizes the tab index of the content element.
Useful when rendering tabs within a select or combobox

**`focus`**
Type: `VoidFunction`
Description: Set focus on the selected tab trigger

**`selectNext`**
Type: `(fromValue?: string) => void`
Description: Selects the next tab

**`selectPrev`**
Type: `(fromValue?: string) => void`
Description: Selects the previous tab

**`getTriggerState`**
Type: `(props: TriggerProps) => TriggerState`
Description: Returns the state of the trigger with the given props

### Data Attributes

**`Root`**

**`data-scope`**: tabs
**`data-part`**: root
**`data-orientation`**: The orientation of the tabs
**`data-focus`**: Present when focused

**`List`**

**`data-scope`**: tabs
**`data-part`**: list
**`data-focus`**: Present when focused
**`data-orientation`**: The orientation of the list

**`Trigger`**

**`data-scope`**: tabs
**`data-part`**: trigger
**`data-orientation`**: The orientation of the trigger
**`data-disabled`**: Present when disabled
**`data-value`**: The value of the item
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused
**`data-ssr`**: Present when not rendered in the browser. Useful for ssr styling

**`Content`**

**`data-scope`**: tabs
**`data-part`**: content
**`data-selected`**: Present when selected
**`data-orientation`**: The orientation of the content

**`Indicator`**

**`data-scope`**: tabs
**`data-part`**: indicator
**`data-orientation`**: The orientation of the indicator

### CSS Variables

<CssVarTable name="tabs" />

## Accessibility

### Keyboard Interactions

**`Tab`**
Description: When focus moves onto the tabs, focuses the active trigger. When a trigger is focused, moves focus to the active content.

**`ArrowDown`**
Description: Moves focus to the next trigger in vertical orientation and activates its associated content.

**`ArrowRight`**
Description: Moves focus to the next trigger in horizontal orientation and activates its associated content.

**`ArrowUp`**
Description: Moves focus to the previous trigger in vertical orientation and activates its associated content.

**`ArrowLeft`**
Description: Moves focus to the previous trigger in horizontal orientation and activates its associated content.

**`Home`**
Description: Moves focus to the first trigger and activates its associated content.

**`End`**
Description: Moves focus to the last trigger and activates its associated content.

**`Enter + Space`**
Description: In manual mode, when a trigger is focused, moves focus to its associated content.
Tag inputs render tags inside an input, followed by an actual text input. By
default, tags are added when text is typed in the input field and the `Enter` or
`Comma` key is pressed. Throughout the interaction, DOM focus remains on the
input element.

## Resources


[Latest version: v1.33.1](https://www.npmjs.com/package/@zag-js/tags-input)
[Logic Visualizer](https://zag-visualizer.vercel.app/tags-input)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tags-input)



**Features**

- Typing in the input and pressing enter will add new items
- Clear button to reset all tags values
- Add tags by pasting into the input
- Delete tags on backspace
- Edit tags after creation
- Limit the number of tags
- Navigate tags with keyboard
- Custom validation to accept/reject tags

## Installation

To use the tags input machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tags-input @zag-js/solid