# or
yarn add @zag-js/toast @zag-js/vue
```

## Anatomy

To set up the toast 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 toast package into your project

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

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

```html
<script setup>
  import * as toast from "@zag-js/toast"
  import { normalizeProps, useMachine } from "@zag-js/vue"
  import { computed } from "vue"

  // 1. Create the toaster
  const toaster = toast.createStore({
    placement: "top-end",
    overlap: true,
  })
</script>

<script setup>
  // 2. Design the toast component
  const props = defineProps<{ toast: toast.Options, index: number, parent: toast.GroupService }>()

  const machineProps = computed(() => ({ ...props.toast, parent: props.parent, index: props.index }))
  const service = useMachine(toast.machine, machineProps)

  const api = computed(() => toast.connect(service, normalizeProps))
</script>

<template>
  <div v-bind="api.getRootProps()">
    <h3 v-bind="api.getTitleProps()">{{ api.title }}</h3>
    <p v-bind="api.getDescriptionProps()">{{ api.description }}</p>
    <button @click="api.dismiss()">Close</button>
  </div>
</template>

<script setup>
  // 3. Design the toaster
  const service = useMachine(toast.group.machine, { id: "1", store: toaster })
  const api = toast.group.connect(service, normalizeProps)
</script>

<template>
  <div v-bind="api.getGroupProps()">
    <Toast
      v-for="toast in api.getToasts()"
      :key="toast.id"
      :toast="toast"
      :index="index"
      :parent="service"
    />
  </div>
  <RestOfYourApp />
</template>

<script setup>
  // 4. Within your app
  const topRightToast = () => toast.create({ title: "Hello" })

  const bottomRightToast = () =>
    toast.create({ title: "Data submitted!", type: "success" })
</script>

<template>
  <button @click="topRightToast">Add top-right toast</button>
  <button @click="bottomRightToast">Add bottom-right toast</button>
</template>
```

The use the toast effectively, you need to understand these key aspects:

### Toast Group

- `toast.group.machine` â The state machine representation of a group of toasts.
  It is responsible for spawning, updating and removing toasts.
- `toast.group.connect` â function gives you access to methods you can use to
  add, update, and remove a toast.

  > We recommend setting up the toast group machine once at the root of your
  > project.

### Toast Item

- `toast.machine` â The state machine representation of a single toast.
- `toast.connect` â The function that takes the toast machine and returns
  methods and JSX properties.

## Creating a toast

There are five toast types that can be created with the toast machine. `info`,
`success`, `loading`, `custom` and `error`.

To create a toast, use the `toaster.create(...)` method.

```jsx
toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
})
```

The options you can pass in are:

- `title` â The title of the toast.
- `description` â The description of the toast.
- `type` â The type of the toast. Can be either `error`, `success` , `info`,
  `loading`, or `custom`.
- `duration` â The duration of the toast. The default duration is computed based
  on the specified `type`.
- `onStatusChange` â A callback that listens for the status changes across the
  toast lifecycle.
- `removeDelay` â The delay before unmounting the toast from the DOM. Useful for
  transition.

## Changing the placement

Use the `placement` property when you call the `toaster.create(...)` to change
the position of the toast.

```jsx {4}
toaster.info({
  title: "Hello World",
  description: "This is a toast",
  placement: "top-start",
})
```

## Overlapping toasts

When multiple toasts are created, they are rendered in a stack. To make the
toasts overlap, set the `overlap` property to `true`.

```jsx
const toaster = toast.createStore({
  overlap: true,
})
```

When using overlap, the toast's placement must match the `placement` of the
toast group (which is `bottom` by default).

> Be sure to set up the [required styles](#requirement) to make the toasts
> overlap correctly.

## Changing the duration

Every toast has a default visible duration depending on the `type` set. Here's
the following toast types and matching default durations:

<PropValueTable
  items={{
    headings: ["type", "duration"],
    data: [
      ["info", "5000"],
      ["error", "5000"],
      ["success", "2000"],
      ["loading", "Infinity"],
    ],
  }}
/>

You can override the duration of the toast by passing the `duration` property to
the `toaster.create(...)` function.

```jsx {5}
toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  duration: 6000,
})
```

> You can also use the `toaster.upsert(...)` function which creates or updates a
> toast.

## Using portals

Using a portal is helpful to ensure that the toast is rendered outside the DOM
hierarchy of the parent component. To render the toast in a portal, wrap the
rendered toasts in the `ToastProvider` within your framework-specific portal.



## Programmatic control

To update a toast programmatically, you need access to the unique identifier of
the toast.

This identifier can be either:

- the `id` passed into `toaster.create(...)` or,
- the returned random `id` when the `toaster.create(...)` is called.

You can use any of the following methods to control a toast:

- `toaster.upsert(...)` â Creates or updates a toast.
- `toaster.update(...)` â Updates a toast.
- `toaster.remove(...)` â Removes a toast instantly without delay.
- `toaster.dismiss(...)` â Removes a toast with delay.
- `toaster.pause(...)` â Pauses a toast.
- `toaster.resume(...)` â Resumes a toast.

```jsx {2,11-15}
// grab the id from the created toast
const id = toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  duration: 6000,
  placement: "top-start",
})

// update the toast
toaster.update(id, {
  title: "Hello World",
  description: "This is a toast",
  type: "success",
})

// remove the toast
toaster.remove(id)

// dismiss the toast
toaster.dismiss(id)
```

## Handling promises

The toast group API exposes a `toaster.promise()` function to allow you update
the toast when it resolves or rejects.

> With the promise API, you can pass the toast options for each promise
> lifecycle. **The `loading` option is required**

```jsx
toaster.promise(promise, {
  loading: {
    title: "Loading",
    description: "Please wait...",
  },
  success: (data) => ({
    title: "Success",
    description: "Your request has been completed",
  }),
  error: (err) => ({
    title: "Error",
    description: "An error has occurred",
  }),
})
```

## Pausing the toasts

There are three scenarios we provide to pause a toast from timing out:

- When the document loses focus or the page is idle (e.g. switching to a new
  browser tab), controlled via the `pauseOnPageIdle` context property.
- When the `toaster.pause(id)` is called.

```jsx
// Global pause options
const service = useMachine(toast.group.machine, {
  pauseOnPageIdle: true,
})

// Programmatically pause a toast (by `id`)
// `id` is the return value of `api.create(...)`
toaster.pause(id)
```

## Limiting the number of toasts

Toasts are great but displaying too many of them can sometimes hamper the user
experience. To limit the number of visible toasts, pass the `max` property to
the group machine's context.

```jsx {3}
const toaster = toast.createStore({
  max: 10,
})
```

## Focus Hotkey for toasts

When a toast is created, you can focus the toast region by pressing the
`alt + T`. This is useful for screen readers and keyboard navigation.

Set the `hotkey` context property to change the underlying hotkey.

```jsx
const service = useMachine(toast.group.machine, {
  hotkey: ["F6"],
})
```

## Listening for toast lifecycle

When a toast is created, you can listen for the status changes across its
lifecycle using the `onStatusChange` callback when you call
`toaster.create(...)`.

The status values are:

- `visible` - The toast is mounted and rendered
- `dismissed` - The toast is visually invisible but still mounted
- `unmounted` - The toast has been completely unmounted and no longer exists

```jsx {3-7}
toaster.info({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  onStatusChange: (details) => {
    // details => { status: "visible" | "dismissed" | "unmounted" }
    console.log("Toast status:", details)
  },
})
```

## Changing the gap between toasts

When multiple toasts are rendered, a gap of `16px` is applied between each
toast. To change this value, set the `gap` context property.

```jsx {3}
const service = useMachine(toast.group.machine, {
  gap: 24,
})
```

## Changing the offset

The toast region has a default `16px` offset from the viewport. Use the `offset`
context property to change the offset.

```jsx {4-8}
const service = useMachine(toast.group.machine, {
  offsets: "24px",
})
```

## Styling guide

### Requirement

The toast machine injects a bunch of css variables that are required for it to
work. You need to connect these variables in your styles.

```css
[data-part="root"] {
  translate: var(--x) var(--y);
  scale: var(--scale);
  z-index: var(--z-index);
  height: var(--height);
  opacity: var(--opacity);
  will-change: translate, opacity, scale;
}
```

To make it transition smoothly, you should includes `transition` properties.

```css
[data-part="root"] {
  transition:
    translate 400ms,
    scale 400ms,
    opacity 400ms;
  transition-timing-function: cubic-bezier(0.21, 1.02, 0.73, 1);
}

[data-part="root"][data-state="closed"] {
  transition:
    translate 400ms,
    scale 400ms,
    opacity 200ms;
  transition-timing-function: cubic-bezier(0.06, 0.71, 0.55, 1);
}
```

### Toast styling

When a toast is created and the `api.getRootProps()` from the `toast.connect` is
used, the toast will have a `data-type` that matches the specified `type` at its
creation.

You can use this property to style the toast.

```css
[data-part="root"][data-type="info"] {
  /* Styles for the specific toast type */
}

[data-part="root"][data-type="error"] {
  /* Styles for the error toast type */
}

[data-part="root"][data-type="success"] {
  /* Styles for the success toast type */
}

[data-part="root"][data-type="loading"] {
  /* Styles for the loading toast type */
}
```

## Methods and Properties

### Machine API

The toast's `api` exposes the following methods:

**`getCount`**
Type: `() => number`
Description: The total number of toasts

**`getToasts`**
Type: `() => ToastProps<any>[]`
Description: The toasts

**`subscribe`**
Type: `(callback: (toasts: Options<O>[]) => void) => VoidFunction`
Description: Subscribe to the toast group

### Data Attributes

**`Root`**

**`data-scope`**: toast
**`data-part`**: root
**`data-state`**: "open" | "closed"
**`data-type`**: The type of the item
**`data-placement`**: The placement of the toast
**`data-align`**: 
**`data-side`**: 
**`data-mounted`**: Present when mounted
**`data-paused`**: Present when paused
**`data-first`**: 
**`data-sibling`**: 
**`data-stack`**: 
**`data-overlap`**: Present when overlapping

**`GhostBefore`**

**`data-scope`**: toast
**`data-part`**: ghost-before
**`data-ghost`**: 

**`GhostAfter`**

**`data-scope`**: toast
**`data-part`**: ghost-after
**`data-ghost`**: 

### CSS Variables

<CssVarTable name="toast" />
A toggle group is used to toggle either one option or multiple options.

## Resources


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



**Features**

- Fully managed keyboard navigation
- Supports horizontal and vertical orientation
- Support for multiple selection

## Installation

To use the toggle group machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/toggle-group @zag-js/vue