FieldChat
Поле чата поверх FieldTextArea. Многострочный ввод с автоматическим ростом высоты (1–4 строки), футером действий (прикрепление файлов и отправка) и списком прикреплённых вложений. Enter отправляет сообщение, Shift+Enter переносит строку. Прикреплённые файлы на desktop показываются под полем, на mobile — над ним.
Когда использовать
- Поле ввода сообщения в чате или диалоге с ассистентом.
- Нужно прикрепление файлов рядом с вводом и отправка по Enter.
Когда не нужен FieldChat:
- Многострочное описание сущности без отправки/вложений —
FieldDescription. - Произвольный многострочный текст —
FieldTextArea.
Анатомия
Ввод
FieldTextArea с minRows=1 и maxRows=4: поле растёт по мере набора текста и дальше скроллится. Плейсхолдер берётся из локали.
Футер действий
- Скрепка (
FileUpload) — прикрепление файлов; видна только при переданномattachment. Тип допустимых файлов задаётся черезattachment.accept. - Кнопка отправки — активна, когда есть непустой текст или хотя бы один файл; иначе disabled.
Вложения
attachment.files рендерятся карточками: AttachmentSquare на desktop, полноширинный Attachment на mobile. Удаление — через attachment.onFileDelete.
Клавиатура
- Enter — отправка (вызывает
handleSubmit(value)), если ввод валиден. - Shift+Enter — перенос строки без отправки.
Примеры использования
Базовый
import { FieldChat } from '@cloud-ru/ds-uikit-product-fields-predefined';
import { useState } from 'react';
export function FieldChatBasic() {
const [value, setValue] = useState('');
return <FieldChat value={value} onChange={setValue} handleSubmit={() => setValue('')} />;
}С вложениями
import { FieldChat } from '@cloud-ru/ds-uikit-product-fields-predefined';
import { useState } from 'react';
export function FieldChatWithAttachments() {
const [value, setValue] = useState('');
const [files, setFiles] = useState<File[]>([]);
return (
<FieldChat
value={value}
onChange={setValue}
handleSubmit={() => {
setValue('');
setFiles([]);
}}
attachment={{
files,
accept: 'image/*,.pdf',
onFilesUpload: uploaded => setFiles(prev => [...prev, ...uploaded]),
onFileDelete: file => setFiles(prev => prev.filter(item => item !== file)),
}}
/>
);
}Props
Types
FieldChatProps| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
allowMoreThanMaxLength | boolean | true | no | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
attachment | (Pick<FileUploadProps, "accept" | "onFilesUpload"> & { files?: File[]; onFileDelete: ((file?: File) => void) | undefined; }) | undefined | — | no | Прикрепление файлов |
autoFocus | boolean | — | no | Автофокус. На mobile выключается адаптивно (см. `layoutPresets`) |
background | boolean | true | no | Фон поля (acrylic) |
caption | string | — | no | Вторичная подпись справа |
className | string | — | no | CSS-класс CSS-класс корня `FieldDecorator` |
data-test-id | string | — | no | |
defaultValue | string | — | no | Начальное значение (uncontrolled-режим) |
disabled | boolean | — | no | Поле выключено |
error | string | — | no | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
fieldClassName | string | — | no | CSS-класс оболочки поля |
handleSubmit | (value: string) => void | — | yes | Колбек действия при отправке |
header | ReactNode | — | no | Нода над textarea — ряд элементов до контента (Figma `elementWrapperBefore` / `slotBeforeContent`): тулбар с кнопками, чипами и т.п. |
id | string | — | no | HTML id |
innerRef | Ref<HTMLDivElement> | — | no | Ref на корневой DOM-элемент |
inputMode | "decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | — | no | Режим виртуальной клавиатуры (`inputmode` нативного `<textarea>`) |
labelFor | string | — | no | HTML-атрибут `for` для `<label>` |
labelTooltip | QuestionTooltipProps | — | no | Подсказка (question-tooltip) у заголовка |
layoutPresets | Partial<Record<LayoutType, Partial<{ autoFocus: boolean; }>>> | — | no | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
length | FieldLength | — | no | Счётчик длины `current/max` |
maxLength | number | — | no | Максимальное количество символов |
name | string | — | no | HTML name |
onBlur | ((event: FocusEvent<HTMLTextAreaElement, Element>) => void) | — | no | Колбек блюра |
onChange | ((value: string, event?: ChangeEvent<HTMLTextAreaElement>) => void) | — | no | Колбек смены значения |
onCopyButtonClick | (() => void) | — | no | Колбек после копирования |
onFocus | ((event: FocusEvent<HTMLTextAreaElement, Element>) => void) | — | no | Колбек фокуса |
readonly | boolean | — | no | Только для чтения |
resizable | boolean | false | no | Можно ли менять высоту мышкой за нижний угол. Игнорируется при `disabled` или `readonly`. |
showClearButton | boolean | true | no | Кнопка очистки (видна при value && !readonly) |
showHintIcon | boolean | — | no | Отображение статус-иконки у подсказки (по умолчанию `true`) |
validationState | "default" | "error" | "success" | "warning" | — | no | Состояние валидации |
value | string | — | no | Значение (controlled-режим) |
Types
FieldChatProps
Related props
AttachmentSquareProps
FieldLayoutPresets
FieldLength
FileUploadProps
NativeInputProps
QuestionTooltipProps
ValidationState
Адаптивность
Раскладку компонент берёт из AdaptiveProvider (@cloud-ru/ds-adaptive) — отдельного пропа layoutType нет. На mobile прикреплённые файлы показываются над полем полноширинными карточками Attachment (на desktop — под полем, AttachmentSquare). Размер поля от раскладки не зависит.
autoFocus на mobile выключается (наследуется из @cloud-ru/ds-fields) — он открывает экранную клавиатуру без действия пользователя. Вернуть на mobile — через layoutPresets:
<FieldChat autoFocus layoutPresets={{ mobile: { autoFocus: true } }} />
Mobile включается автоматически при одном <AdaptiveProvider> в корне приложения (desktop-first).