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

<Overview group="forms">

# WriteBar [tag:component]

Компонент для создания поля ввода сообщений с поддержкой иконок действий.
Аналог строки ввода в мессенджерах и соцсетях. Принимает все свойства нативного `<textarea>`.

</Overview>

{/* @example-description: Базовый `WriteBar` с иконкой вложений в слоте `before`. */}
<Playground>
  ```jsx
  <WriteBar before={<WriteBarIcon mode="attach" />} placeholder="Введите сообщение..." />
  ```
</Playground>

## Режим работы

Компонент поддерживает работу как в неконтролируемом режиме, так и контролируемом. Это стандартное поведение
React-компонентов, прочитать про это можно в [документации React](https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable).

Для использования неконтролируемого режима достаточно просто _не_ передавать `value` или передавать `defaultValue`, если
требуется задать значение по умолчанию.
Для контролируемого режима используйте связку свойств `value`/`onChange` для задания значения и его изменения.

```jsx
// Неконтролируемое состояние
<WriteBar defaultValue="Текст" />;

// Контролируемое состояние
const [text, setText] = React.useState('Текст');

<WriteBar value={text} onChange={(event) => setText(event.target.value)} />;
```

## Основные элементы

- `before` — элементы слева от поля ввода.
- `after` — элементы справа.
- `inlineAfter` — элементы поверх поля (актуально для iOS).

{/* @example-description: Пример `WriteBar` с элементами в `before`, `after` и `inlineAfter`. */}
<Playground>
  ```jsx
  <WriteBar
    before={<WriteBarIcon mode="attach" />}
    after={
      <WriteBarIcon label="Записать голосовое сообщение">
        <Icon24VoiceOutline />
      </WriteBarIcon>
    }
    inlineAfter={
      <WriteBarIcon label="Смайлы и стикеры">
        <Icon24SmileOutline />
      </WriteBarIcon>
    }
    placeholder="Введите сообщение..."
  />
  ```
</Playground>

## Использование иконок [#icons]

Все боковые элементы рекомендуется оборачивать в `WriteBarIcon`.
Также для адаптирования размеров иконок стоит использовать компонент [`AdaptiveIconRenderer`](/components/adaptive-icon-renderer).

По правилам дизайн-системы в `"regular"`-режиме используются кнопки размером `28px`, в `"compact"`-режиме — `24px`.
Исключение: на платформе `iOS` допускается использование иконок размером `28px` в `"compact"`-режиме.

{/* @example-description: Адаптивные иконки и динамические действия в `WriteBar` в зависимости от введённого текста. */}
<Playground style={{ width: 290 }}>

```jsx
const [text, setText] = React.useState('');
const platform = usePlatform();

const SmileOutlineIcon = (
  <AdaptiveIconRenderer
    IconCompact={platform === 'ios' ? Icon28SmileOutline : Icon24SmileOutline}
    IconRegular={Icon28SmileOutline}
  />
);

const VoiceOutlineIcon = (
  <AdaptiveIconRenderer
    IconCompact={platform === 'ios' ? Icon28VoiceOutline : Icon24VoiceOutline}
    IconRegular={Icon28VoiceOutline}
  />
);

const KeyboardBotsOutlineIcon = (
  <AdaptiveIconRenderer
    IconCompact={platform === 'ios' ? Icon28KeyboardBotsOutline : Icon24KeyboardBotsOutline}
    IconRegular={Icon28KeyboardBotsOutline}
  />
);

return (
  <WriteBar
    value={text}
    onChange={(e) => setText(e.target.value)}
    before={<WriteBarIcon mode="attach" />}
    inlineAfter={
      <>
        {text.length === 0 && (
          <WriteBarIcon label="Открыть меню бота">{KeyboardBotsOutlineIcon}</WriteBarIcon>
        )}
        {text.length > 0 && (
          <WriteBarIcon label="Эмоджи и стикеры">{SmileOutlineIcon}</WriteBarIcon>
        )}
      </>
    }
    after={
      <>
        {text.length === 0 && (
          <WriteBarIcon label="Эмоджи и стикеры">{SmileOutlineIcon}</WriteBarIcon>
        )}
        {text.length === 0 && (
          <WriteBarIcon label="Записать голосовое сообщение">{VoiceOutlineIcon}</WriteBarIcon>
        )}
        {text.length > 0 && <WriteBarIcon mode="send" />}
      </>
    }
    placeholder="Сообщение"
  />
);
```

</Playground>

## WriteBarIcon [tag:component]

Компонент для создания иконок-кнопок внутри `WriteBar`. Обеспечивает стандартное поведение и доступность
для элементов управления в поле ввода сообщений.

### Особенности поведения

- Наследует все свойства `<button>`.
- Автоматически адаптируется под платформы Android и iOS при использовании готовых пресетов.

### Предустановленные режимы

Предустановленные типы кнопок в `WriteBar` для отрисовки иконки и установки текста кнопки в зависимости от платформы.
Если передать валидное значение для этого свойства, `children` игнорируются,
а для `label` по умолчанию используется текст на "ru_RU".

- `attach` — иконка прикрепления с текстом "Прикрепить файл".
- `send` — иконка отправки с текстом "Отправить".
- `done` — иконка подтверждения с текстом "Готово".

{/* @example-description: Предустановленные режимы `WriteBarIcon`: `attach`, `send`, `done`. */}
<Playground>
  ```jsx
  <WriteBarIcon mode="attach" />
  <WriteBarIcon mode="send" />
  <WriteBarIcon mode="done" />
  ```
</Playground>

### Использование кастомных иконки

{/* @example-description: Пример `WriteBarIcon` с пользовательской иконкой и подписью. */}
<Playground>

```jsx
const platform = usePlatform();

return (
  <WriteBarIcon label="Голосовое сообщение">
    <AdaptiveIconRenderer
      IconCompact={platform === 'ios' ? Icon28VoiceOutline : Icon24VoiceOutline}
      IconRegular={Icon28VoiceOutline}
    />
  </WriteBarIcon>
);
```

</Playground>

### Отображение счётчика

Значение счётчика для кнопки. Например, для количества прикреплённых файлов.

{/* @example-description: Пример `WriteBarIcon` со счётчиком через свойство `count`. */}
<Playground>
  ```jsx
  <WriteBarIcon mode="attach" count={3} label="Прикреплённые файлы" />
  ```
</Playground>

## Кастомизация

Компонент поддерживает свойство `slotProps`, которое даёт возможность прокинуть свойство в некоторые внутренние элементы.
Это удобно для добавления кастомных классов, data-атрибутов, aria-атрибутов, обработчиков событий, доступов к элементам через `getRootRef` и других расширений, не влияя на внешний API компонента.

{/* @example-description: Кастомизация `WriteBar` через `slotProps` для корня и поля ввода. */}
<Playground style={{ maxWidth: 270 }}>
  ```jsx
  const textareaRef = React.useRef();

  return (
    <WriteBar
      before={<WriteBarIcon mode="attach" />}
      placeholder="Введите сообщение..."
      className="my-root-class"
      data-testid="write-bar-root"
      id="write-bar-textarea-id"
      slotProps={{
        root: {
          id: 'write-bar-root-id',
        },
        input: {
          className: 'my-textarea-class',
          'aria-label': 'Пример slotProps',
          getRootRef: textareaRef,
        },
      }}
    />
  )
  ```
</Playground>

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

Укажите текстовое описание одним из способов:

- Через свойство `label`:

  ```jsx
  <WriteBarIcon label="Прикрепить файл">
    <Icon24Attachment />
  </WriteBarIcon>
  ```

- Через ARIA-атрибуты:

  ```jsx
  <WriteBarIcon aria-label="Отправить сообщение">
    <Icon24Send />
  </WriteBarIcon>
  ```

- С использованием VisuallyHidden:

  ```jsx
  <WriteBarIcon>
    <Icon24SmileOutline />
    <VisuallyHidden>Эмодзи</VisuallyHidden>
  </WriteBarIcon>
  ```

- С использованием `id` в `aria-labelledby`

  ```jsx
  <VisuallyHidden id="write_bar_icon_voice">Записать голосовое сообщение</VisuallyHidden>
    <WriteBarIcon aria-labelledby="write_bar_icon_voice">
    <Icon28VoiceOutline />
  </WriteBarIcon>
  ```

## Подкомпоненты

<Playground>
  ```jsx
  <WriteBar.Root>
    <WriteBar.Before>
      <WriteBarIcon mode="attach" />
    </WriteBar.Before>
    <WriteBar.FormField>
      <WriteBar.Textarea placeholder="Введите сообщение..." />
      <WriteBar.FormField.InlineAfter>
        <WriteBarIcon label="Смайлы и стикеры">
          <Icon24SmileOutline />
        </WriteBarIcon>
      </WriteBar.FormField.InlineAfter>
    </WriteBar.FormField>
    <WriteBar.After>
      <WriteBarIcon mode="attach" />
    </WriteBar.After>
  </WriteBar.Root>
  ```
</Playground>

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

### WriteBar

| Свойство | Тип | По умолчанию | Описание |
| --- | --- | --- | --- |
| `after` | `ReactNode` | `-` | Содержимое, отображаемое справа от поля ввода. |
| `before` | `ReactNode` | `-` | Содержимое, отображаемое слева от поля ввода. |
| `getRef` | `Ref<HTMLTextAreaElement>` | `-` | **Deprecated**: Since 7.9.0. Вместо этого используйте `slotProps={ textArea: { getRootRef: ... } }`. |
| `getRootRef` | `Ref<HTMLDivElement>` | `-` |  |
| `inlineAfter` | `ReactNode` | `-` | Содержимое, отображаемое поверх поля ввода (актуально для iOS). |
| `onHeightChange` | `VoidFunction` | `-` | Вызывается при смене высоты поля ввода. |
| `shadow` | `boolean` | `false` | Добавляет тень вокруг поля ввода. |
| `slotProps` | `{ root?: (Omit<HTMLAttributes<HTMLDivElement>, "children"> & HasRootRef<HTMLDivElement> & HasDataAttribute); textArea?: (TextareaHTMLAttributes<...> & ... 1 more ... & HasDataAttribute) \| undefined; } \| undefined` | `-` | Свойства, которые можно прокинуть внутрь компонента: - `root`: свойства для прокидывания в корень компонента; - `textArea`: свойства для прокидывания в поле ввода. |

### WriteBarIcon

| Свойство | Тип | По умолчанию | Описание |
| --- | --- | --- | --- |
| `count` | `number` | `-` | Значение счётчика для кнопки. Например, для количества прикреплённых файлов. |
| `label` | `string` | `-` | Текст кнопки. Необходим для ассистивных технологий. |
| `mode` | `"done" \| "send" \| "attach"` | `-` | Предустановленные типы кнопок в WriteBar для отрисовки иконки и установки текста кнопки в зависимости от платформы. Если передать валидное значение для этого свойства, `children` игнорируются, а для `label` по умолчанию используется текст на "ru_RU".  Валидные значения: - `attach` – иконка прикрепления, текст по умолчанию — "Прикрепить файл"; - `send` – иконка отправки, текст по умолчанию — "Отправить"; - `done` – иконка отправки в режиме редактирования, текст по умолчанию — "Готово". |

