﻿---
description: Компонент окна оповещения, для отображения важных сообщений и подтверждения действий пользователя.
tags: notification
---

<Overview group="feedback">

# Alert [tag:component]

Компонент окна оповещения, для отображения важных сообщений и подтверждения действий пользователя.
Например, уведомление о том, что выполнение операции ведёт к удалению данных.
Внешний вид компонента зависит от платформы и имитирует поведение [нативного элемента](https://developer.apple.com/design/human-interface-guidelines/alerts).

</Overview>

<Playground hide>

```jsx
<Alert
  onClosed={() => {}}
  dismissLabel="Отмена"
  actions={[
    { title: 'Отмена', mode: 'cancel' },
    { title: 'Удалить', mode: 'destructive' },
  ]}
  title="Удаление документа"
  description="Вы уверены, что хотите удалить этот документ?"
/>
```

</Playground>

{/* @example-description: Базовый пример вызова `Alert` с подтверждением и отменой деструктивного действия. */}
<Playground>

```jsx
const [alert, setAlert] = React.useState(null);

const showAlert = () => {
  if (alert) return;
  setAlert(
    <Alert
      onClosed={() => setAlert(null)}
      dismissLabel="Отмена"
      actions={[
        { title: 'Отмена', mode: 'cancel' },
        { title: 'Удалить', mode: 'destructive' },
      ]}
      title="Удаление документа"
      description="Вы уверены, что хотите удалить этот документ?"
    />,
  );
};

return (
  <>
    <Button onClick={showAlert}>Показать оповещение</Button>
    {alert}
  </>
);
```

</Playground>

## Обязательные свойства

### `onClosed`

Свойство `onClosed` принимает функцию, которая вызовется после завершения анимации закрытия компонента.
Обязательно удаляйте из `DOM`-дерева компонент `Alert` в обработчике `onClosed`, иначе это будет мешать
дальнейшему взаимодействию с элементами и повторному открытию компонента.

## Шапка

В компоненте есть возможность задать заголовок и описание для уведомления с помощью свойств `title` и `description` соответственно:

```jsx
<Alert title="Удаление документа" description="Вы уверены что хотите удалить этот документ?" />
```

## Кнопки действий

Через свойство `actions` можно задать набор кнопок, который будет отрисован:

```jsx
const actions = [
  { title: 'Отмена', mode: 'cancel' },
  {
    title: 'Удалить',
    mode: 'destructive',
    action: () => console.log('Документ удален.'),
  },
];

<Alert
  actions={actions}
  dismissLabel="Отмена"
  onClosed={closePopout}
  title="Удаление документа"
  description="Вы уверены, что хотите удалить этот документ?"
/>;
```

Каждая кнопка описывается объектом, позволяя задать текст кнопки, её тип и дополнительные параметры.
Кнопки могут быть ссылками (передайте `href`) или другим компонентом (передайте `Component`).

Свойство `mode` отвечает за внешний вид кнопки:

- `"default"` — стандартный стиль отображения текста;
- `"destructive"` — стиль критических действий (чаще всего красный);
- `"cancel"` — стиль действия отмены.

Стиль `"cancel"` используется для действия, возвращающего пользователя к состоянию на момент открытия компонента,
без выполнения каких-либо операций. Кнопка с таким стилем должна быть одна на `Alert` и располагаться либо слева, либо снизу.
ССЫЛКА

Стиль `"destructive"` используется в случае, когда выполнение действия влечёт за собой какие-то деструктивные последствия,
которые пользователь намеренно не выбирал.

Во всех остальных случаях используйте стиль `"default"`.

Свойство `title` позволяет задать текст кнопке. Старайтесь указывать конкретное действие (глагол), описывающее что произойдет при нажатии.
Например, "Удалить", "Отменить подписку". Избегайте формулировок "Да" и "Нет", потому что они могут путать пользователя.
Если необходимо подчеркнуть разницу между подтверждением действия и его отменой, допускается кнопку со стилем `"cancel"` переименовать
в похожее по смыслу действие:

```jsx
const actions = [
  { title: 'Не сейчас', mode: 'cancel' },
  {
    title: 'Отменить подписку',
    mode: 'destructive',
    action: () => console.log('Подписка отменена.'),
  },
];

<Alert
  actions={actions}
  dismissLabel="Не сейчас"
  onClosed={closePopout}
  title="Отмена подписки"
  description="Вы уверены, что хотите отменить подписку?"
/>;
```

Свойство `action` принимает обработчик нажатия на кнопку. Если свойство `autoCloseDisabled` включено,
то в аргументы `action` передаётся объект с функцией `close`, вызвав которую можно закрыть `Alert` вручную.

По умолчанию нажатие на опцию вызывает переданную в `Alert` функцию `onClosed`, свойство `autoCloseDisabled` позволяет отключить такое поведение.

Свойство `actionsAlign` позволяет поменять тип выравнивания кнопок:

- `"left"` — выравнивание по левому краю;
- `"center"` — выравнивание по центру;
- `"right"` — выравнивание по правому краю (по умолчанию).

> Свойство недоступно на платформе iOS.

Свойство `actionsLayout` отвечает за вертикально или горизонтально расположение действий:

- `"horizontal"` — горизональное расположение (по умолчанию).
- `"vertical"` — вертикальное расположение;

> На платформе `vkcom` возможно только горизональное расположение.

### Пользовательские кнопки

У вас есть возможность самостоятельно управлять отрисовкой кнопок, для это воспользуйтесь свойством `renderAction`.
Это может быть полезно, когда вы хотите поддержать одинаковый внешний вид вне зависимости от платформы.

```jsx
const renderAction = ({ mode, ...restProps }) => {
  return <Button mode={mode === 'cancel' ? 'secondary' : 'primary'} size="m" {...restProps} />;
};

<Alert
  actions={[
    { title: 'Лишить права', mode: 'destructive' },
    { title: 'Отмена', mode: 'cancel' },
  ]}
  dismissLabel="Отмена"
  renderAction={renderAction}
  title="Подтвердите действие"
  description="Вы уверены, что хотите лишить пользователя права на модерацию контента?"
/>;
```

## Кнопка закрытия

Благодаря свойству `dismissButtonMode` можно управлять положением кнопки закрытия.

- `"outside"` — кнопка закрытия располагается снаружи элемента (по умолчанию);
- `"inside"` — кнопка закрытия располагается внутри элемента;
- `"none"` — кнопка закрытия не отображается.

> **Обратите внимание**
>
> Кнопка закрытия не отображается на платформе iOS и в мобильном представлении (`regular`-режиме)

Дополнительно [ознакомьтесь](#a11y-buttons) в информацией по поддержке доступности кнопки.

## Управление фокусом

### `autoFocus`

Данное свойство позволяет автоматически устанавливать фокус на первом интерактивном элементе при открытии всплывающего элемента.
По умолчанию это поведение включено, но можно его отключить, передав `autoFocus={false}`.

Также есть возможность установить фокус на контейнере всплывающего меню, передав `autoFocus="root"`. Это может быть полезно,
когда первый интерактивный элемент имеет подсказку, которая активируется при фокусе. В таком случае появление подсказки сразу
после открытия всплывающего меню может быть нежелательным. Значение `"root"` позволяет поддержать данный сценарий, не ломая доступность.

### `restoreFocus`

Данное свойство позволяет восстанавливать фокус после закрытия всплывающего меню на последний активный элемент.
По умолчанию данное поведение включено, но можно его отключить, передав `restoreFocus={false}`.

Также есть возможность передать в `restoreFocus` функцию, которая возвращает `HTMLElement` или `boolean`.
Если возвращается `HTMLElement`, то фокус будет возвращен на этот элемент, при `false` — фокус не восстанавливается,
при `true` — поведение по умолчанию.

## Управление порталами

VKUI использует [порталы](https://react.dev/reference/react-dom/createPortal) для рендеринга `Alert`.

Свойство `usePortal` позволяет настраивать порталы:

- `true` — использует свойство `portalRoot`, указанное в компоненте `AppRoot`, , если не указано, то `document.body` (по умолчанию);
- `false`/`null` — отключает рендер компонента в отдельном контейнере, он будет рендериться непосредственно по месту определения;

Также можно указать конкретный `DOM`-элемент (полученный, например, через `document.getElementById`)
или ссылку на `DOM`-элемент ([`ref`-объект](https://react.dev/learn/manipulating-the-dom-with-refs)).

## Браузерные события

### Click Event

По умолчанию событие `click` не всплывает, что позволяет изолировать компонент от остального приложения.
Если вам необходимо данное событие обрабатывать (например, у вас есть глобальный обработчик клика для сбора аналитики),
воспользуйтесь свойством `allowClickPropagation`.

## Тестирование (e2e) [#e2e]

Для возможности тестирования доступны свойства с постфиксом `*TestId`, которые вы можете использовать,
чтобы находить необходимые части компонента:

- `titleTestId` — `id` для заголовка;
- `descriptionTestId` — `id` для описания;
- `dismissButtonTestId` — `id` для кнопки закрытия.

## Доступность (a11y) [#a11y]

`Alert` является модальным окном (`role="dialog"`), а значит у него обязательно должно быть имя — его краткое название.
Благодаря этому пользователи ассистивных технологий знают, что это за элемент и какое у него содержимое.

Задать имя можно с помощью следующих способов:

- используя свойство `title`;
- используя свойство `aria-label`;
- используя свойство `aria-labelledby`;

### Доступные имена кнопок [#a11y-buttons]

Если две кнопки находятся в разных местах, но выполняют одну функцию, то лучше дать им одинаковые имена.
Это относится, например, к кнопке закрытия, имя которой можно задать через свойство `dismissLabel`.
Если у вас среди кнопок действия есть кнопка `Отмена`, которая без дополнительного действия просто закрывает `Alert`, ровно
как и кнопка закрытия, то кнопке закрытия следует дать то же имя `Отмена` через свойство `dismissLabel`.

```jsx
<Alert
  dismissLabel="Отмена"
  actions={[
    { title: 'Отмена', mode: 'cancel' },
    { title: 'Удалить', mode: 'destructive', action: () => addActionLogItem('Документ удален.') },
  ]}
  title="Удаление документа"
  description="Вы уверены, что хотите удалить этот документ?"
/>
```

## Свойства и методы [#api]

| Свойство | Тип | По умолчанию | Описание |
| --- | --- | --- | --- |
| `actions` | `AlertActionInterface[]` | `-` | Список действий. |
| `actionsAlign` | `AlignType` | `-` | Тип выравнивания действий. |
| `actionsLayout` | `"horizontal" \| "vertical"` | `-` | Расположение действий - вертикально или горизонтально. |
| `allowClickPropagation` | `boolean` | `-` | По умолчанию событие onClick не всплывает. |
| `autoFocus` | `boolean \| "root"` | `true` | Управление поведением автофокуса при появлении всплывающего окна. При прокидывании `true` фокус будет установлен на первый элемент. При прокидывании `root` фокус будет установлен в корень. |
| `description` | `ReactNode` | `-` | Описание модального окна. |
| `descriptionTestId` | `string` | `-` | Передает атрибут `data-testid` для описания. |
| `dismissButtonMode` | `"none" \| "inside" \| "outside"` | `-` | Расположение кнопки закрытия (внутри и вне `popout'a`) Доступно только в `compact`-режиме, не отображается на `iOS`.  ⚠️ ВНИМАНИЕ: использование `none` скрывает крестик, это негативно сказывается на пользовательском опыте. |
| `dismissButtonTestId` | `string` | `-` | Передает атрибут `data-testid` для кнопки закрытия. |
| `dismissLabel` | `string` | `-` | Текст кнопки закрытия. Делает ее доступной для ассистивных технологий. |
| `getRootRef` | `Ref<HTMLDivElement>` | `-` |  |
| `onClose` | `((reason: AlertCloseReason) => void)` | `-` | Обработчик закрытия модального окна. |
| `**onClosed** \*` | `VoidFunction` | `-` | Обработчик закрытия модального окна, срабатывающий после окончания анимации. |
| `renderAction` | `((props: AlertActionProps) => ReactNode)` | `-` | Функция для отрисовки действия. |
| `restoreFocus` | `boolean \| (() => boolean \| HTMLElement)` | `true` | Управление поведением возврата фокуса при закрытии всплывающего окна. |
| `title` | `ReactNode` | `-` | Заголовок модального окна. |
| `titleTestId` | `string` | `-` | Передает атрибут `data-testid` для заголовка. |
| `usePortal` | `boolean \| HTMLElement \| RefObject<HTMLElement \| null> \| null` | `true (использует `document.body` как портал по умолчанию)` | Настройка портала для рендеринга компонента.  `true` - использует `portalRoot` из контекста `AppRoot` (если доступен) или `document.body`; `false` - отключает использование портала; `HTMLElement` - указывает конкретный DOM-элемент для использования в качестве портала; `React.RefObject<HTMLElement \| null>` - ссылка на DOM-элемент для использования в качестве портала; `null` - эквивалентно `false`, отключает использование портала. |

