@qor/chat-layer

Компоненты

Vue-компоненты чат-мессенджера — 27 компонентов для полнофункционального интерфейса.

Все компоненты авто-импортируются (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ТипОписание
messagesChatMessage[]Массив сообщений
loadingbooleanИндикатор загрузки
hasMorebooleanЕсть ли ещё история
currentUserIdstringID текущего пользователя
participantsMap<string, { name, avatar? }>Карта участников
typingUsersstring[]Имена пользователей, которые печатают
unreadCountnumberКоличество непрочитанных

ChatInput

Поле ввода сообщения с поддержкой вложений, эмодзи и голосовых сообщений.

<ChatInput
  ref="chatInputRef"
  :reply-to="replyTo"
  :editing-message="editingMessage"
  :chat-id="chatId"
  @send="handleSend"
  @cancel-reply="replyTo = null"
  @cancel-edit="editingMessage = null"
/>
PropТипОписание
replyToChatMessage | nullСообщение, на которое отвечают
editingMessageChatMessage | nullРедактируемое сообщение
chatIdstringID текущего чата
EmitPayloadОписание
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ТипПо умолчаниюОписание
activeChatIdstring | nullnullАктивный диалог (v-model). Игнорируется при routeSync
routeSyncbooleanfalseЧитать/писать активный id из chatRouteBase/:id
titlestring'Чаты'Заголовок inbox
showNewbooleanfalseКнопка + встроенный пикер «новый чат»
usersChatPickerUser[][]Кандидаты для пикера нового чата
EmitPayloadОписание
update:activeChatIdstring | nullИзменился активный диалог
selectChatConversationВыбран диалог
new—Нажата кнопка «новый чат»

ChatInbox

Готовый inbox: заголовок + поиск + фильтры + список (на useConversations). Левая панель ChatShell, но используется и отдельно.

<ChatInbox
  :active-chat-id="activeId"
  title="Сообщения"
  show-new
  @select="open"
  @new="openPicker"
/>
PropТипПо умолчаниюОписание
activeChatIdstring | nullnullПодсвеченный диалог (desktop)
titlestring'Чаты'Заголовок
showHeaderbooleantrueПоказывать заголовок
showNewbooleanfalseКнопка «новый чат»

ChatConversation

Вид одного диалога, отвязанный от роутинга — встраивается в ChatShell, drawer, модалку или используется роутовой страницей chats/[id].vue. История подгружается на mount через REST (useChatMessages().loadHistory()), поэтому прямой reload /chats/:id показывает сообщения до подключения сокета. Realtime не затрагивается.

<ChatConversation :chat-id="id" @back="navigateTo(listPath())" />
PropТипПо умолчаниюОписание
chatIdstring—Внешний id диалога
showBackbooleanisMobileКнопка «назад» в шапке

Страницы

Layer предоставляет готовые страницы:

СтраницаПутьОписание
chats.vue/chatsLayout: 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

Полноэкранная навигация: список чатов → диалог (кнопка "назад").