# Toaster
> Toaster creates temporary, floating messages in the edges of the screen that communicate information to the user.

<Callout variant="tip">

For persistent messaging, contextual or specific to a particular part of an application, consider [Notification component](/components/notification).

</Callout>

## Import

```js
import {
  createToastManager,
  Toaster,
  useToastManager
} from '@gemini-suite/vera-react';
```

- `createToastManager`: Factory to create a `toastManager`.
- `Toaster`: The wrapper component that provides `toastManager` for its children.
- `useToastManager`: The hook to consume `toastManager` in your React components.

  <Callout variant="tip">

  `toastManager` can also be used to create toasts from outside of your React components.

  </Callout>

## Provide toast manager

Add `<Toaster>` high up in your app's tree, preferably in the root component.

```jsx lineHighlight=4,10,12
import { Toaster, createToastManager } from '@gemini-suite/vera-react';

// `toastManager` instance can be created outside of your React component
const toastManager = createToastManager();

// provide `toastManager` in your root App component
function App() {
  return (
    <SomeGlobalProvider>
      <Toaster manager={toastManager}>
        <AppLayout>{children}</AppLayout>
      </Toaster>
    </SomeGlobalProvider>
  );
}
```

## Toast manager API

`toastManager` provides two methods:

```js
toastManager.addToast(toastDefinition); // returns disposer
toastManager.removeToast(toastId);
```

<Callout variant="tip">

`addToast()` returns a toast disposer function.

If you create toasts within `React.useEffect()` and the component becomes unmounted, the toasts
will be automatically dismissed.

</Callout>

### Toast definition

| Name         | Type                                                     | Default  | Description                                                                                                                                                                                                                                 | Required |
| ------------ | -------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `message`    | `ValueOrFunction<Renderable, string>`                    |          | Content of the message to display. You can provide a function that will receive `id` of the toast.                                                                                                                                          | Yes      |
| `type`       | `"info" \| "warning" \| "error" \| "success"`            | `"info"` | Type of the toast notification.                                                                                                                                                                                                             |          |
| `duration`   | `number \| null`                                         | `5000`   | The delay before the toast hides (in milliseconds). If set to `null`, toast will never dismiss.                                                                                                                                             |          |
| `isClosable` | `boolean`                                                | `false`  | When `true` toast will show a close button.                                                                                                                                                                                                 |          |
| `action`     | `{ label: string; onAction: (toastId: string) => void }` |          | An action to add next to the message.                                                                                                                                                                                                       |          |
| `id`         | `string`                                                 |          | The `id`. By default, we generate a unique `id` for each toast.                                                                                                                                                                             |          |
| `className`  | `string`                                                 |          | `className` to add to `Toast` component.                                                                                                                                                                                                    |          |
| `css`        | `StitchesCss`                                            |          | Apply styles directly to a `Toast` in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

---

## Examples

### Toast types

Toasts are used to provide relevant feedback to the user, typically after they've taken an action.
They can convey a `warning`, `error`, `success`, or `info` message.

<Callout variant="tip">

Toasts should be used for brief and direct communication. Only include the highest priority information and aim for no more than ~100 characters.

</Callout>

```jsx
() => {
  const toastManager = useToastManager();

  return (
    <Flex flow="column" gap="spacingS">
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({ message: 'Toast added!', type: 'success' });
          }}
        >
          {'Create success toast'}
        </Button>
      </Box>
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({
              message: 'New version available.',
              type: 'info',
              duration: null,
              action: {
                label: 'Reload',
                onAction: () => {}
              },
              isClosable: true
            });
          }}
        >
          {'Create info toast'}
        </Button>
      </Box>
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({
              message: 'Market will close in 10 minutes.',
              type: 'warning',
              isClosable: true
            });
          }}
        >
          {'Create warning toast'}
        </Button>
      </Box>
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({
              message: 'Failed to fetch data!',
              type: 'error',
              duration: null,
              isClosable: true
            });
          }}
        >
          {'Create error toast'}
        </Button>
      </Box>
    </Flex>
  );
};
```

<Callout variant="tip">

Auto-close timer will pause when you hover on a toast.

You can disable this
behavior by setting `shouldPauseOnHover` to `false` on `Toaster`.

</Callout>

<Callout variant="tip">

You can prevent essential toasts from disappearing automatically, by setting `duration` prop to `null`.

</Callout>

### Toaster position

You can change the position of all toasts by supplying `position` prop.

```jsx
() => {
  const toastManager = createToastManager();

  const ConsumerComponent = () => {
    const toastManager = useToastManager();

    return (
      <Button
        variant="outline"
        onClick={() => {
          toastManager.addToast({
            message: toastId => (
              <Box>
                {'Toast'} <b>{toastId}</b> {'created!'}
              </Box>
            ),
            type: 'success'
          });
        }}
      >
        {'Stack toast on top'}
      </Button>
    );
  };

  return (
    <Toaster
      position="topCenter"
      manager={toastManager}
      style={{ '--toaster-top-offset': 0 }}
    >
      <ConsumerComponent />
    </Toaster>
  );
};
```

### Size

You can change the size of all toasts by supplying `size` prop. Toasts come in two sizes: `medium` (default) and `small`.

```jsx
() => {
  const toastManager = createToastManager();

  const ConsumerComponent = () => {
    const toastManager = useToastManager();

    return (
      <Button
        variant="outline"
        onClick={() => {
          toastManager.addToast({
            message: toastId => (
              <Box>
                {'Toast'} <b>{toastId}</b> {'created!'}
              </Box>
            ),
            type: 'success'
          });
        }}
      >
        {'Create small toast'}
      </Button>
    );
  };

  return (
    <Toaster
      size="small"
      manager={toastManager}
      style={{ '--toaster-top-offset': 0 }}
    >
      <ConsumerComponent />
    </Toaster>
  );
};
```

### Action

You can allow users to perform a single associated action via the `action` prop.

<Callout variant="important">

Do not include actions such as “Cancel”, for dismissing toast. The dismiss button is already included in the component.

</Callout>

<Callout variant="important">

An actionable notification should persist until user dismisses it or have a time-out of at least 10 seconds, allowing users time to interact with it.

</Callout>

```jsx
() => {
  const toastManager = useToastManager();

  return (
    <Flex flow="column" gap="spacingS">
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({
              message: 'Image deleted!',
              type: 'success',
              duration: 10000,
              isClosable: true,
              action: {
                label: 'Undo',
                onAction: toastId => {
                  alert('Undo!');

                  toastManager.removeToast(toastId);
                }
              }
            });
          }}
        >
          {'Create success toast with action'}
        </Button>
      </Box>
      <Box>
        <Button
          variant="outline"
          onClick={() => {
            toastManager.addToast({
              message: 'Request failed!',
              type: 'error',
              duration: null,
              action: {
                label: 'Try again',
                onAction: toastId => {
                  alert('New attempt!');

                  toastManager.removeToast(toastId);
                }
              }
            });
          }}
        >
          {'Create error toast with action'}
        </Button>
      </Box>
    </Flex>
  );
};
```

### Limit number of toasts

By default Toaster will show at most 5 latest toasts.

You can change this limit by supplying `limit` prop. Setting `limit` to `null` will result in no limit.

```jsx
() => {
  const toastManager = createToastManager();

  const ConsumerComponent = () => {
    const toastManager = useToastManager();

    return (
      <Button
        variant="outline"
        onClick={() => {
          toastManager.addToast({
            message: toastId => (
              <Box>
                {'Toast'} <b>{toastId}</b> {'created!'}
              </Box>
            ),
            type: 'success'
          });
        }}
      >
        {'Add to limited stack'}
      </Button>
    );
  };

  return (
    <Toaster limit={3} position="bottomLeft" manager={toastManager}>
      <ConsumerComponent />
    </Toaster>
  );
};
```

---

## API Reference

| Name                 | Type                                                                                        | Default      | Description                                                                                                                                                                                                                                   | Required |
| -------------------- | ------------------------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `manager`            | `ToastManager`                                                                              |              | `toastManager` created with `createToastManager()`.                                                                                                                                                                                           | Yes      |
| `position`           | `"topCenter" \| "topLeft" \| "topRight" \| "bottomCenter" \| "bottomLeft" \| "bottomRight"` | `"topRight"` | Position of the toasts container.                                                                                                                                                                                                             |          |
| `size`               | `"medium" \| "small"`                                                                       | `"medium"`   | The size of toasts.                                                                                                                                                                                                                           |          |
| `limit`              | `number \| null`                                                                            |              | Limit the number of displayed toasts.                                                                                                                                                                                                         |          |
| `shouldPauseOnHover` | `boolean`                                                                                   | `true`       | When `true`, the auto-close timer will pause on toasts hover.                                                                                                                                                                                 |          |
| `shouldFadeLast`     | `boolean`                                                                                   | `true`       | When `true`, the last two toasts (counting downwards from the stack limit) will display in gradually weaker opacity to reflect newer/older relationship.                                                                                      |          |
| `css`                | `StitchesCss`                                                                               |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

---

## Guidelines

Notifications should inform users about any updates or changes to the application.

Toasts provide limited space for content, and therefore the content must be short and concise, providing immediate feedback in response to a user action or informing users of a process that the app has performed or will perform.

Toasts are usually time-based but can also be shown until the user decides to dismiss them manually.

<Callout variant="important">

Toast notifications serve as an essential part of visual feedback, yet, they can't be overused since this may annoy the user.

</Callout>
