Компоненты
Все компоненты авто-импортируются (pathPrefix отключён). Компоненты используют Nuxt UI 4 с темой @qor/ui.
Основные компоненты
ChatMessages
Область отображения сообщений с виртуальным скроллом (DynamicScroller).
<ChatMessages
:messages="messages"
:loading="loading"
:has-more="hasMore"
:current-user-id="currentUserId"
:participants="participantsMap"
:typing-users="typingUserNames"
:unread-count="unreadCount"
@load-more="loadMore"
@reply="handleReply"
@copy="handleCopy"
@delete="handleDelete"
@edit="handleEdit"
@forward="handleForward"
@react="handleReact"
@retry="handleRetry"
@pin="handlePin"
/>
| Prop | Тип | Описание |
|---|---|---|
messages | ChatMessage[] | Массив сообщений |
loading | boolean | Индикатор загрузки |
hasMore | boolean | Есть ли ещё история |
currentUserId | string | ID текущего пользователя |
participants | Map<string, { name, avatar? }> | Карта участников |
typingUsers | string[] | Имена пользователей, которые печатают |
unreadCount | number | Количество непрочитанных |
ChatInput
Поле ввода сообщения с поддержкой вложений, эмодзи и голосовых сообщений.
<ChatInput
ref="chatInputRef"
:reply-to="replyTo"
:editing-message="editingMessage"
:chat-id="chatId"
@send="handleSend"
@cancel-reply="replyTo = null"
@cancel-edit="editingMessage = null"
/>
| Prop | Тип | Описание |
|---|---|---|
replyTo | ChatMessage | null | Сообщение, на которое отвечают |
editingMessage | ChatMessage | null | Редактируемое сообщение |
chatId | string | ID текущего чата |
| Emit | Payload | Описание |
|---|---|---|
send | [body, attachments?, files?] | Отправка сообщения |
cancel-reply | — | Отмена ответа |
cancel-edit | — | Отмена редактирования |
ChatHeader
Шапка диалога с именем, аватаром, статусом и действиями.
<ChatHeader
:conversation="conversation"
:show-back="isMobile"
@back="navigateTo('/chats')"
@search="searchOpen = !searchOpen"
@info="infoOpen = true"
@mute="handleMute"
@clear-chat="handleClearChat"
@leave-group="handleLeaveGroup"
/>
ChatListItem
Элемент списка чатов с аватаром, превью, временем и счётчиком непрочитанных.
<ChatListItem
:conversation="conv"
:active="conv.id === activeChatId"
@click="selectChat(conv)"
/>
ChatMessageBubble
Пузырь сообщения с контекстным меню (reply, edit, delete, forward, react, pin).
<ChatMessageBubble
:message="msg"
:is-own="isOwn"
:show-avatar="showAvatar"
:show-name="showName"
:sender-name="senderName"
:current-user-id="currentUserId"
@reply="$emit('reply', msg)"
@edit="$emit('edit', msg)"
@delete="$emit('delete', msg)"
@copy="$emit('copy', msg)"
@forward="$emit('forward', msg)"
@react="$emit('react', { messageId: msg.id, emoji })"
@retry="$emit('retry', msg)"
@pin="$emit('pin', msg)"
/>
Вспомогательные компоненты
Область ввода
| Компонент | Описание |
|---|---|
ChatEmojiPicker | Панель выбора эмодзи |
ChatVoiceRecorder | Запись голосовых сообщений |
ChatFilePreview | Превью прикреплённого файла перед отправкой |
ChatInputPreviewBar | Панель превью (reply-to / editing) над полем ввода |
Контент сообщений
| Компонент | Описание |
|---|---|
ChatBubbleContent | Содержимое сообщения (текст, изображение, файл, аудио, видео) |
ChatAudioPlayer | Плеер для аудио/голосовых сообщений |
ChatImageLightbox | Полноэкранный просмотр изображений |
Навигация и статус
| Компонент | Описание |
|---|---|
ChatConnectionStatus | Баннер статуса подключения (reconnecting/error) |
ChatTypingIndicator | Анимация "печатает..." |
ChatSearchBar | Панель поиска по сообщениям |
ChatSearch | Поиск по списку чатов |
ChatPinnedBar | Закреплённое сообщение |
ChatScrollButton | Кнопка "вниз" со счётчиком непрочитанных |
ChatDropOverlay | Оверлей при drag & drop файлов |
ChatEmpty | Пустое состояние (нет чатов / чат не найден) |
Информация о чате
| Компонент | Описание |
|---|---|
ChatInfo | Боковая панель информации о диалоге (slideOver) |
ChatInfoProfile | Профиль пользователя/группы |
ChatInfoParticipants | Список участников группы |
ChatInfoMedia | Медиа-файлы чата |
ChatInfoActions | Действия (mute, clear, leave) |
Диалоги
| Компонент | Описание |
|---|---|
ChatForwardDialog | Модальное окно пересылки сообщения |
ChatList | Список всех диалогов (RecycleScroller) |
ChatNewConversation | Модальный пикер «новый чат» (single/group) |
Встраиваемые компоненты (0.5.0)
Эти компоненты построены на чистом @nuxt/ui v4 (без Nuxt UI Pro UDashboard*) и заполняют родителя (h-full), поэтому их можно монтировать внутри shell приложения, а не на весь экран. Они переиспользуют те же Chat*-компоненты, что и роутовые страницы.
ChatShell
Самодостаточный двухпанельный surface чата (inbox слева + диалог справа). Управляет активным диалогом сам.
<!-- Внутренний выбор (без роутинга) -->
<ChatShell v-model:active-chat-id="activeId" title="Сообщения" />
<!-- Синхронизация с маршрутом chatRouteBase/:id (deep-link, reload) -->
<ChatShell route-sync />
<!-- Встроенный пикер «новый чат» со списком пользователей приложения -->
<ChatShell show-new :users="contacts" @select="onSelect" />
| Prop | Тип | По умолчанию | Описание |
|---|---|---|---|
activeChatId | string | null | null | Активный диалог (v-model). Игнорируется при routeSync |
routeSync | boolean | false | Читать/писать активный id из chatRouteBase/:id |
title | string | 'Чаты' | Заголовок inbox |
showNew | boolean | false | Кнопка + встроенный пикер «новый чат» |
users | ChatPickerUser[] | [] | Кандидаты для пикера нового чата |
| Emit | Payload | Описание |
|---|---|---|
update:activeChatId | string | null | Изменился активный диалог |
select | ChatConversation | Выбран диалог |
new | — | Нажата кнопка «новый чат» |
ChatInbox
Готовый inbox: заголовок + поиск + фильтры + список (на useConversations). Левая панель ChatShell, но используется и отдельно.
<ChatInbox
:active-chat-id="activeId"
title="Сообщения"
show-new
@select="open"
@new="openPicker"
/>
| Prop | Тип | По умолчанию | Описание |
|---|---|---|---|
activeChatId | string | null | null | Подсвеченный диалог (desktop) |
title | string | 'Чаты' | Заголовок |
showHeader | boolean | true | Показывать заголовок |
showNew | boolean | false | Кнопка «новый чат» |
ChatConversation
Вид одного диалога, отвязанный от роутинга — встраивается в ChatShell, drawer, модалку или используется роутовой страницей chats/[id].vue. История подгружается на mount через REST (useChatMessages().loadHistory()), поэтому прямой reload /chats/:id показывает сообщения до подключения сокета. Realtime не затрагивается.
<ChatConversation :chat-id="id" @back="navigateTo(listPath())" />
| Prop | Тип | По умолчанию | Описание |
|---|---|---|---|
chatId | string | — | Внешний id диалога |
showBack | boolean | isMobile | Кнопка «назад» в шапке |
Страницы
Layer предоставляет готовые страницы:
| Страница | Путь | Описание |
|---|---|---|
chats.vue | /chats | Layout: dual-panel (desktop) / single (mobile) |
chats/index.vue | /chats | Пустое состояние "Выберите чат" |
chats/[id].vue | /chats/:id | Диалог с конкретным чатом |
Desktop layout
┌──────────────┬───────────────────────────────┐
│ Chat List │ Chat Conversation │
│ (resizable) │ │
│ │ ┌─────────────────────────┐ │
│ ┌────────┐ │ │ ChatHeader │ │
│ │ Search │ │ ├─────────────────────────┤ │
│ ├────────┤ │ │ │ │
│ │ Filter │ │ │ ChatMessages │ │
│ ├────────┤ │ │ (virtual scroll) │ │
│ │ │ │ │ │ │
│ │ Items │ │ ├─────────────────────────┤ │
│ │ │ │ │ ChatInput │ │
│ └────────┘ │ └─────────────────────────┘ │
└──────────────┴───────────────────────────────┘
Mobile layout
Полноэкранная навигация: список чатов → диалог (кнопка "назад").