Перейти к основному содержимому
Версия: 5.9.0

Компоненты

Компоненты — общие строительные блоки темы (панель навигации, поле ввода, плеер и т.д.). Один компонент переиспользуется на разных экранах и настраивается централизованно через ChatComponents; в отдельных пользовательских сценариях стиль можно переопределить точечно.

Пример настройки:

// Создание компонентов с кастомными цветами
let components = ChatComponents(colors: myColors, typography: myTypography)

// Переопределение параметров общих для SDK компонентов
components.navigationBarStyle.titleTextStyle.color = .white
// Cancel-кнопка в search-баре — это UIKit-овый UISearchBar.cancelButton; из-за
// ограничений UISearchBar API применяется только `color.normal`.
// `tintColor` и другие свойства ButtonStyle для этого элемента игнорируются —
// см. design-system/known_issues.md.
components.searchBarStyle.cancelButtonStyle.color.normal = .white

// Создание темы из компонентов
let theme = ChatTheme(components: components)

или через конструктор build:

let components = ChatComponents.build { components in
components.searchBarStyle.cancelButtonStyle.color.normal = .black
components.loadingChatStyle.indicatorStyle.backgroundColor = .systemGray3
components.loadingChatStyle.indicatorStyle.cornerRadius = 20.0
components.audioPlayerStyle.playButtonStyle.image = ChatImage(system: "play.fill", tintColor: .red)
components.audioPlayerStyle.pauseButtonStyle.image = ChatImage(system: "pause.fill", tintColor: .green)
components.audioPlayerStyle.progressViewStyle.color = .black
components.audioPlayerStyle.progressViewStyle.backgroundColor = .yellow
}

Параметры конструктора (все опциональные, имеют значения по умолчанию):

  • images: ChatImages — изображения, используемые в теме.
  • colors: ChatColors — цветовая палитра.
  • typography: ChatTypography — настройки шрифтов.

Стили компонентов чата

НазваниеОписание
navigationBarStyleПанель навигации: заголовок, кнопки, фон.
searchBarStyleПанель поиска внутри navigationBarStyle.
loadingIndicatorStyleИндикатор загрузки (спиннер).
loadingChatStyleЭкран загрузки при открытии чата.
chatPlaceholderStyleЗаглушка для пустого чата.
errorPlaceholderStyleЭкран ошибки с кнопкой «Повторить».
inputTextStyleТекстовое поле ввода сообщения.
inputSearchTextStyleТекстовое поле в панели поиска.
audioPlayerStyleПлеер голосовых сообщений.
inputViewStyleНижняя панель чата: поле ввода, кнопки отправки и прикрепления.
chatMenuStyleМеню выбора файла/фото/камеры.
photoPickerStyle устарел

photoPickerStyle — deprecated, используйте chatMenuStyle.

Анатомия экранов

Скриншоты ниже сопоставляют визуальные зоны iOS-чата с полями ChatComponents, chatFlow и searchFlow. Снято с демо-приложения (светлая тема по умолчанию). Структура полей одинакова для любой темы.

Где задать стиль

Стиль задаётся глобально через components.X (все flow) или точечно через theme.flows.chatFlow.X / theme.flows.searchFlow.X (один экран). Подробнее о приоритете — в Дизайн-системе.

Главный экран чата

Главный экран чата с сообщениями и быстрыми ответами
ЭлементПуть в темахКласс стиля
Кнопка «Назад» в навигацииchatFlow.navigationBarStyle.backButtonColorNavigationBarStyle
Заголовок чата (имя оператора)chatFlow.navigationBarStyle.titleTextStyleNavigationBarStyle, ChatTextStyle
Подзаголовок (роль оператора)chatFlow.navigationBarStyle.subtitleTextStyleNavigationBarStyle, ChatTextStyle
Иконка поиска в навигацииchatFlow.navigationBarStyle.searchButtonStyleNavigationBarStyle, NavigationBarButtonStyle
Фон экрана чатаchatFlow.backgroundColorChatFlow
Дата-разделитель («сегодня»)chatFlow.systemMessages.dateMessageStyleChatSystemMessagesStyles, ChatTextStyle
Цвет пузыря исходящего сообщенияchatFlow.outcomeMessages.bubbleTintColorChatMessagesStyles
Текст исходящего сообщенияchatFlow.outcomeMessages.textMessageStyle.textStyleTextChatMessageStyle, ChatTextStyle
Иконки статуса (отправлено / доставлено / прочитано)ChatMessageStyle.pendingStatusImage / deliveredStatusImage / readStatusImageChatMessageStyle
Системное сообщение («Вам ответит…»)chatFlow.systemMessagesChatSystemMessagesStyles
Кнопки быстрого ответаСм. QuickReplyStyle (Стили)QuickReplyStyle
Поле ввода сообщенияchatFlow.inputViewStyle.inputTextStyleChatInputStyle, ChatInputTextStyle
Кнопка прикрепления (clip)chatFlow.inputViewStyle.attachButtonStyleChatInputStyle, IconButtonStyle
Кнопка микрофона (в неактивном состоянии)chatFlow.inputViewStyle.voiceButtonStyleChatInputStyle, IconButtonStyle
Кнопка отправкиchatFlow.inputViewStyle.sendButtonStyleChatInputStyle, IconButtonStyle
Кнопки быстрого ответаchatFlow.quickRepliesStyleQuickReplyStyle

Контекстное меню сообщения

Контекстное меню по долгому нажатию на сообщение

Меню появляется при длительном нажатии на сообщение; набор действий («Цитировать», «Копировать», «Удалить») определяется состоянием сообщения и серверной конфигурацией.

ЭлементПуть в темахКласс стиля
Выделенный пузырь сообщенияchatFlow.outcomeMessages / incomeMessagesChatMessagesStyles
Действия меню («Цитировать» и т.п.)Не настраивается через SDK — отрисовка через системный UIKit (UIMenu/UIMenuController)

Поиск сообщений

Открытие экрана поиска
ЭлементПуть в темахКласс стиля
Поисковая строкаsearchFlow.navigationBarStyle.searchBarStyleSearchBarStyle
Текст и курсор в поле поискаcomponents.inputSearchTextStyleChatInputTextStyle
Кнопка «Отмена»searchFlow.navigationBarStyle.searchBarStyle.cancelButtonStyle.color.normalChatButtonColor
Фон экрана поискаsearchFlow.backgroundColorChatUserFlow
Иллюстрация «ничего не найдено»ChatImages.searchNotFoundPlaceholderImageChatImages
Текст «ничего не найдено»searchFlow.notFoundTextStyleChatTextStyle

Результаты поиска

Список найденных сообщений с выделением совпадений
ЭлементПуть в темахКласс стиля
Подсветка совпадений в текстеsearchFlow.searchMessageStyle.matchTextStyleSearchChatMessageStyle, ChatTextStyle
Стиль строки результата (имя, дата, превью)searchFlow.searchMessageStyleSearchChatMessageStyle
Кнопка очистки поля поиска (×)searchFlow.navigationBarStyle.searchBarStyleSearchBarStyle

Пустое состояние чата

Чат без сообщений — приветственный экран
ЭлементПуть в темахКласс стиля
Иллюстрация приветствияChatImages.emptyChatPlaceholderImageChatImages
Заголовок «Добро пожаловать…»components.chatPlaceholderStyle.titleTextStyleChatPlaceholderStyle, ChatTextStyle
Подзаголовок (описание)components.chatPlaceholderStyle.subtitleTextStyleChatPlaceholderStyle, ChatTextStyle
Иллюстрация (через ChatPlaceholderStyle)components.chatPlaceholderStyle.imageChatPlaceholderStyle, ChatImage
Фон экранаchatFlow.backgroundColorChatFlow

Загрузка чата

Полноэкранный лоадер при инициализации чата
ЭлементПуть в темахКласс стиля
Индикатор-спиннерcomponents.loadingChatStyle.indicatorStyleChatLoadingStyle, LoadingIndicatorStyle
Текст «Загрузка»components.loadingChatStyle.textStyleChatLoadingStyle, ChatTextStyle
Фон лоадераcomponents.loadingChatStyle.indicatorStyle.backgroundColorLoadingIndicatorStyle

Ошибка инициализации чата

Экран ошибки инициализации с кнопкой Повторить
ЭлементПуть в темахКласс стиля
Иллюстрация ошибки (по умолчанию)components.errorPlaceholderStyle.defaultErrorImageChatPlaceholderErrorStyle, ChatImage
Иллюстрация при ошибке сервера (HTTP 4xx/5xx)components.errorPlaceholderStyle.serverErrorImageChatPlaceholderErrorStyle, ChatImage
Заголовок ошибкиcomponents.errorPlaceholderStyle.titleTextStyleChatPlaceholderErrorStyle, ChatTextStyle
Подзаголовок ошибкиcomponents.errorPlaceholderStyle.subtitleTextStyleChatPlaceholderErrorStyle, ChatTextStyle
Кнопка «Повторить» — цвет фонаcomponents.errorPlaceholderStyle.repeatButtonStyle.color.normalTextButtonStyle, ChatButtonColor
Кнопка «Повторить» — цвет текстаcomponents.errorPlaceholderStyle.repeatButtonStyle.titleTextStyle.colorTextButtonStyle, ChatTextStyle

Запись голосового сообщения

Панель ввода в режиме записи голосового сообщения
ЭлементПуть в темахКласс стиля
Кнопка микрофона (триггер записи)chatFlow.inputViewStyle.voiceButtonStyleChatInputStyle, IconButtonStyle
Стиль записи целиком (отмена, таймер, прогресс)chatFlow.inputViewStyle.voiceRecordStyleChatInputStyle, ChatInputVoiceStyle
Кнопка отмены записи (×) — внутри voice-режимаchatFlow.inputViewStyle.voiceRecordStyle (см. Стили)ChatInputVoiceStyle

Завершение диалога и оценка

Финал д�иалога с приглашением оценить качество
ЭлементПуть в темахКласс стиля
Аватар оператора у входящего сообщенияchatFlow.incomeMessages.showAvatar (вкл/выкл)ChatMessagesStyles
Стиль системного сообщения «Диалог завершён…»chatFlow.systemMessages.dateMessageStyle (для нейтрального системного текста)ChatSystemMessagesStyles, ChatTextStyle
Заголовок приглашения оценитьchatFlow.systemMessages.surveyMessageStyle.questionTitleTextStyleSurveyChatMessageStyle, ChatTextStyle
Подзаголовок приглашенияchatFlow.systemMessages.surveyMessageStyle.questionSubtitleTextStyleSurveyChatMessageStyle, ChatTextStyle
Иконка звезды (выбранная / невыбранная)chatFlow.systemMessages.surveyMessageStyle.voteIconSurveyChatMessageStyle, ChatSurveyIcon
Цвет звёзд (выбранные / невыбранные)voteSelectedColor / voteUnselectedColorSurveyChatMessageStyle, UIColor
Иконки лайк/дизлайк (для бинарного опроса)voteLikeIcon / voteDislikeIconSurveyChatMessageStyle, ChatSurveyIcon
Не нашли элемент в анатомии?

Полный список свойств — в Стилях и в Сценариях (flows). Если поля нет в публичном API SDK, оно не настраивается — см. Известные ограничения.

Примеры кастомизации типичных элементов

Поле ввода текста

components.inputTextStyle.apply { style in
style.cursorColor = UIColor(named: "BrandColor") ?? .systemBlue // курсор
style.textStyle.color = .label // цвет текста
style.backgroundColor = .systemBackground
}

Или только в экране чата (не затрагивая поиск):

let customInput = ChatInputTextStyle.build(with: components) { style in
style.cursorColor = UIColor(named: "BrandColor") ?? .systemBlue
}
theme.flows.chatFlow.inputViewStyle.inputTextStyle = customInput

Навигационная панель

components.navigationBarStyle.apply { style in
style.titleTextStyle.font = .systemFont(ofSize: 17, weight: .semibold)
style.titleTextStyle.color = .white
style.backgroundColor = UIColor(named: "BrandColor") ?? .systemBlue
}
Условное применение свойств

Поведение зависит от флага isConfigurable в NavigationBarStyle:

  • isConfigurable=true — кастомный заголовок: применяются все свойства titleTextStyle (font + color) и subtitleTextStyle.
  • isConfigurable=false — стандартный нав-бар UIKit: применяется только titleTextStyle.color (через titleTextAttributes). Шрифт titleTextStyle.font и весь subtitleTextStyle игнорируются.

См. также Известные ограничения → Параметры с условиями применения.

Цвет пузырей сообщений

// Входящие (от оператора)
theme.flows.chatFlow.incomeMessages.bubbleTintColor = UIColor(named: "BubbleIncoming") ?? .systemGray5
// Исходящие (от клиента)
theme.flows.chatFlow.outcomeMessages.bubbleTintColor = UIColor(named: "BrandColor") ?? .systemBlue
// Цвет текста в пузырях
theme.flows.chatFlow.incomeMessages.textMessageStyle.textStyle.color = .label
theme.flows.chatFlow.outcomeMessages.textMessageStyle.textStyle.color = .white
Цвет ошибки применяется только к исходящим сообщениям

Свойство bubbleErrorColor в ChatMessagesStyles применяется только к исходящим сообщениям (от клиента). Входящие сообщения не отображают ошибку в цвете пузыря.

Кнопка отправки

let customInput = ChatInputStyle.build(with: components) { style in
// Цвет иконки задаётся в самом ChatImage, цвет фона/состояний — через color.
style.sendButtonStyle.image = ChatImage(system: "paperplane.fill", tintColor: .white)
style.sendButtonStyle.color.normal = UIColor(named: "BrandColor") ?? .systemBlue
style.sendButtonStyle.color.disabled = .systemGray3
}
theme.flows.chatFlow.inputViewStyle = customInput

Цвета кнопок (ChatButtonColor)

Задаёт цвет кнопки в трёх состояниях: normal, highlighted, disabled. Используется в ButtonStyle, IconButtonStyle, NavigationBarButtonStyle, TextButtonStyle.

let buttonColor = ChatButtonColor(
normal: .systemBlue, // обычное состояние
highlighted: .systemBlue.withAlphaComponent(0.7), // при нажатии
disabled: .systemGray3 // неактивная кнопка
)

Все три состояния обязательны. По умолчанию создаются из палитры ChatColors:

СостояниеЦвет по умолчанию
normalcolors.link
highlightedcolors.linkLight
disabledcolors.disabled

Можно применить кастомные цвета либо при создании экземпляра, либо через свойства:

buttonColor.normal = UIColor(named: "BrandColor") ?? .systemBlue

Панель поиска

components.searchBarStyle.apply { style in
// Для cancel-кнопки в search-баре применяется только color.normal,
// tintColor самого SearchBarStyle и другие свойства ButtonStyle для
// этого элемента игнорируются (см. known_issues.md).
style.cancelButtonStyle.color.normal = .white
// Курсор и текст поля поиска настраиваются через inputSearchTextStyle
// (см. секцию «Поисковое поле ввода» ниже).
}

Индикатор загрузки

components.loadingIndicatorStyle.apply { style in
style.indicatorColor = UIColor(named: "BrandColor") ?? .systemBlue
}

Экран загрузки чата

components.loadingChatStyle.apply { style in
style.indicatorStyle.backgroundColor = .systemGray6
style.indicatorStyle.cornerRadius = 16.0
}

Пустое состояние чата

// Текст при пустом чате
components.chatPlaceholderStyle.apply { style in
style.titleTextStyle.color = .secondaryLabel
style.titleTextStyle.font = .systemFont(ofSize: 15, weight: .regular)
}

// Заменить иллюстрацию (через токен изображений)
let images = ChatImages()
images.emptyChatPlaceholderImage = ChatImage(named: "EmptyChat", bundle: .main)

Ошибка загрузки

components.errorPlaceholderStyle.apply { style in
style.titleTextStyle.color = .label
// Цвет фона кнопки «Повторить» — через ChatButtonColor (state-aware).
// Тип repeatButtonStyle — TextButtonStyle, и UI читает color.normal,
// а не tintColor.
style.repeatButtonStyle.color.normal = UIColor(named: "BrandColor") ?? .systemBlue
style.repeatButtonStyle.titleTextStyle.color = .white
}

// Заменить иллюстрацию ошибки (через токен)
images.errorPlaceholderImage = ChatImage(named: "ErrorIllustration", bundle: .main)

Аудиоплеер

components.audioPlayerStyle.apply { style in
style.playButtonStyle.image = ChatImage(system: "play.fill", tintColor: UIColor(named: "BrandColor") ?? .systemBlue)
style.pauseButtonStyle.image = ChatImage(system: "pause.fill", tintColor: UIColor(named: "BrandColor") ?? .systemBlue)
style.progressViewStyle.color = UIColor(named: "BrandColor") ?? .systemBlue
style.progressViewStyle.backgroundColor = .systemGray5
}

Поисковое поле ввода

components.inputSearchTextStyle.apply { style in
style.cursorColor = UIColor(named: "BrandColor") ?? .systemBlue
style.textStyle.color = .label
}

Соответствие Figma и SDK

На странице Components в Figma компоненты организованы в 8 секций. Ниже приведено соответствие между секциями Figma и стилями SDK:

Top Navigation компонент
Bottom Input состояния
Компонент FigmaВариантыСтиль SDK
Top NavigationiOS/Android × Light/DarknavigationBarStyle (NavigationBarStyle)
Bottom InputEmpty, Filled, Voice Record, Voice Recorded, Search NavigationinputViewStyle (ChatInputStyle)
Cite BottomMessage / Photo / Docs × Light/DarkchatFlow.inputViewStyle.quoteStyle (ChatInputQuoteStyle)
Scroll ButtonLight / DarkchatFlow.scrollToTopUnreadMessagesButtonStyle и chatFlow.scrollToBottomUnreadMessagesButtonStyle (ScrollToMessageButtonStyle)
BadgeSingle / Numerous × Light/DarkВизуальный стиль бейджа не настраивается публично в SDK; количество непрочитанных доступно через getUnreadMessagesCount и делегат

Status (Figma)

Message Status варианты
Компонент FigmaВариантыСтиль SDK
Message statusПрочитано, Доставлено, Доставляется, Ошибка, Отредактировано (Client/Agent, с подложкой/без)ChatMessageStyle: readStatusImage, deliveredStatusImage, pendingStatusImage, editedStatusImage, errorStatusColor

Button (Figma)

Button типы и состояния
Тип кнопки (Figma)СостоянияСтиль SDK
BotNormal, Active, Pressed, Disable, Loading, ErrorQuickReplyStyle
TextNormal, Active, Pressed, Disable, Loading, ErrorTextButtonStyle
IconNormal, Active, Pressed, Disable, Loading, ErrorIconButtonStyle
ImageNormal, Active, Pressed, Disable, Loading, ErrorButtonStyle
SelectionNormal, Pressed, DisableQuickReplyStyle

Bubbles (Figma)

Message Base анатомия (Agent и Client)
Компонент FigmaВариантыСтиль SDK
Message Base (Agent)Normal, MultiContent, Deleted, Search agent, ErrorchatFlow.incomeMessages (ChatMessagesStyles)
Message Base (Client)Normal, MultiContent, ErrorchatFlow.outcomeMessages (ChatMessagesStyles)
Системные сообщенияSnooze, дата, опрос, подключение оператораchatFlow.systemMessages (ChatSystemMessagesStyles)

Анатомия баббла в Figma: Avatar → Tail → Content (текст/медиа) → Status. Настраивается через:

  • ChatMessagesStyles.showAvatar — показывать аватар
  • ChatMessageStyle.messageBubbleEndMargin — отступ от края экрана
  • ChatMessageStyle.containerLeftOffset / containerRightOffset — отступы контейнера

Figma-состояния → SDK-свойства

Figma состояниеОписаниеСвойство SDK
NormalОбычное сообщениеtextMessageStyle, imageMessageStyle, bubbleTintColor
TypingИндикатор «печатает»Стиль публично не настраивается
SnoozeОператор временно недоступенchatFlow.systemMessages.scheduleMessageStyle (ScheduleChatMessageStyle)
Search agentРезультат поиска с выделениемsearchFlow.searchMessageStyle (SearchChatMessageStyle)
ErrorОшибка отправкиChatMessageStyle.errorStatusColor, errorTextStyle, errorInfoButton
DeletedУдалённое сообщениеChatMessagesStyles.deletedTextStyle (ChatTextStyle)

Input Field (Figma)

Компонент FigmaВариантыСтиль SDK
Input fieldПустое, частично заполненное, полностью заполненноеinputTextStyle (ChatInputTextStyle)

OS UI (Figma)

Компонент FigmaОписаниеСтиль SDK
iOS Select FileСистемный выбор файлаchatMenuStyle (ChatMenuStyle)
GalleryГалерея фотографийchatMenuStyle
Select ImageВыбор изображенияchatMenuStyle

Content (Figma)

Компонент FigmaОписаниеСтиль SDK
ContentТипы контента в сообщениях: текст, картинка, файл, аудио, опрос, цитата, OG-превью и др.TextChatMessageStyle, ImageChatMessageStyle, FileChatMessageStyle, AudioChatMessageStyle, SurveyChatMessageStyle, QuoteStyle, OpenGraphViewStyle

Illustration (Figma)

Компонент FigmaВариантыСтиль SDK
IllustrationПриветствие, Поиск, Ошибка и др.emptyChatPlaceholderImage, errorPlaceholderImage, searchNotFoundPlaceholderImageChatImages)

Меню вложений (chatMenuStyle)

chatMenuStyle управляет внешним видом меню выбора файлов, фотографий и камеры — всплывающего листа, который появляется при нажатии на кнопку прикрепления.

Доступные свойства

Меню реализовано через системный UIAlertController, поэтому визуально применяются только три свойства:

СвойствоТипОписаниеЗначение по умолчанию
backgroundColorUIColorФон листа менюcolors.background
titleTextStyle.colorUIColorЦвет текста и иконок кнопок (пробрасывается в alert.view.tintColor)colors.link
maximumImagesCountUInt8Максимум выбираемых изображений10
tintColor, cornerRadius, titleTextStyle.font

Эти поля присутствуют на ChatMenuStyle (унаследованы от ChatStyle / ChatTextStyle), но из-за системной реализации UIAlertController визуально игнорируются. Цвет задавайте через titleTextStyle.color, скруглением управляет система.

Пример настройки

// Глобально через ChatComponents (применяется ко всем экранам)
components.chatMenuStyle.apply { style in
style.backgroundColor = UIColor(named: "BackgroundPrimary") ?? .white
style.titleTextStyle.color = UIColor(named: "BrandColor") ?? .systemBlue
}

Или через build для точечного создания нового экземпляра:

let menuStyle = ChatMenuStyle.build(with: components) { style in
style.backgroundColor = .white
style.titleTextStyle.color = .systemBlue
style.maximumImagesCount = 5
}
components.chatMenuStyle = menuStyle

Только для экрана чата

Если нужно изменить стиль меню только в чате (не затрагивая другие экраны):

// Доступ через chatFlow (свойство называется addFileMenuStyle)
theme.flows.chatFlow.addFileMenuStyle.apply { style in
style.backgroundColor = UIColor(named: "BackgroundPrimary") ?? .white
style.titleTextStyle.color = UIColor(named: "BrandColor") ?? .systemBlue
}
Связь с глобальным chatMenuStyle

При создании ChatFlow свойство addFileMenuStyle инициализируется ссылкой на тот же экземпляр, что хранится в components.chatMenuStyle на момент инициализации темы. После этого они независимы: если позже выполнить components.chatMenuStyle = newStyle, на chatFlow.addFileMenuStyle это не повлияет — там останется прежний объект.

Чтобы изменить меню только в chatFlow без глобального эффекта, создайте новый экземпляр через build и присвойте его напрямую: theme.flows.chatFlow.addFileMenuStyle = myMenuStyle.