Chat Message

Surface сообщения в чате 1:1 с живым стримом — пузырь пользователя, serif-тело ассистента, ряд действий (копировать / редактировать / перегенерировать), инлайн-редактор, навигация по веткам, scroll-to-bottom FAB и тулбар «Ответить» над выделением.

Установка

Использование

Базовое сообщение

Пузырь пользователя — secondary-плитка (15px sans, leading-relaxed). Тело ассистента — без пузыря, serif 16px / lh 1.65, и помечено data-assistant-message, чтобы тулбар выделения цеплялся только к нему. Роли system (приглушённый пузырь) и tool (карточка с обводкой) сохранены.

Ряд действий

ChatMessageActions рисует hover-ряд. variant="user" даёт gap-2, variant="assistant" — gap-1; visibility="always" закрепляет ряд (последний ответ), visibility="hover" (по умолчанию) показывает его на ховере сообщения.

ChatMessageAction — это 32px / r8 ghost-квадрат с тонкими (strokeWidth 1) иконками 20px, приглушённый по умолчанию, foreground-on-accent на ховере. ChatMessageTime рендерит относительное время (только что, 5м назад, …) и ничего не рисует, пока now не станет числом после гидрации.

Инлайн-редактор

ChatMessageEdit — рукописная textarea (не базовый Input): r18 на bg-card, 14px / leading-snug, фокус-кольцо ring-2/30. Enter сохраняет, Shift+Enter — перенос строки, Escape — отмена. ChatMessageEditActions — правый ряд Отмена (outline) / Сохранить (primary).

Ветки (альтернативные ответы)

Управление контекстное: ChatMessageBranchControls рендерит null, когда вариант один (totalBranches <= 1). ChatMessageBranchPage показывает текущий / всего (tabular-nums).

Scroll-to-bottom FAB

ChatMessageScrollButton — круглый 36px FAB c прохладной рамкой 0.5px, frosted-панелью и двухслойной тенью (1:1 с живым стримом). Позиционирование, монтирование и анимацию владеет потребитель.

Тулбар «Ответить» над выделением

ChatMessageSelectionReply слушает выделение внутри [data-assistant-message="true"] и портит fixed тёмную пилюлю над выделением. Клик передаёт обрезанный фрагмент в onReply и снимает выделение.

Видимость действий

Вложения

ChatMessageAttachments — ряд плиток над пузырём (выровнен вправо, перенос, gap-3). ChatMessageAttachment — плитка 120×120: вариант image рисует cover-миниатюру (на ховере подсвечивается), вариант file — имя (обрезка в 3 строки), мета-строку и чип-расширение ChatMessageFileBadge. Обе плитки — кнопки с onClick. Геометрия (120px, рамка 0.5px, тень) — bespoke; цвета — токены DS (bg-muted/bg-card, border, text-foreground/text-muted-foreground).

Цитаты и вставленный текст

ChatMessageQuote рисует два вида карточек. variant="pasted" повторяет геометрию плитки 120px и ставит чип ChatMessageFileBadge («Вставлено»). variant="excerpt" — авто-ширина r12 bg-secondary блок-цитата: вертикальная акцент-черта (bg-foreground/25) + обрезанный текст в 6 строк, на ховере bg-secondary/80. ChatMessageFileBadge — uppercase-чип h-18 / r4 на bg-muted (semibold 11px muted).

API

Состояния

  • role=user — пузырь secondary справа, 15px sans / leading-relaxed.
  • role=assistant — без пузыря, serif 16px / lh 1.65, data-assistant-message.
  • role=system / tool — приглушённый пузырь / карточка с обводкой (примитив).
  • actions hover / pinnedopacity-0 group-hover/msg:opacity-100 против opacity-100.
  • edit idle / active — пузырь + действия против textarea + Отмена/Сохранить (Enter сохраняет, Shift+Enter — перенос, Escape — отмена).
  • branch single / multi — управление скрыто при одном варианте, иначе prev/next + N / M.
  • scroll at-bottom / away — FAB скрыт / показан (потребитель анимирует).
  • selection active / collapsed — пилюля «Ответить» над выделением / удалена при сбросе.
  • attachment image idle / hover — cover-миниатюра 120px / hover:brightness-95.
  • attachment file idle / hover — имя + мета + чип-расширение / hover:border-foreground/30.
  • quote pasted — плитка 120px превью + бейдж «Вставлено».
  • quote excerpt idle / hover — блок-цитата с акцент-чертой / hover:bg-secondary/80.
  • file-badge — uppercase-чип h-18 / r4 на bg-muted.

Стили роли применяются через [data-role=user], [data-role=assistant] и т.д. — можно переопределить классами. Текст и подписи интернационализируемы через пропсы (label, cancelLabel, saveLabel, format).

Oracul DS

Built for the future of AI-driven interfaces.