videorc/ui

Chat Message

One chat message in the Stream Manager, the big-text row. A click puts it on stream under the live chrome plate; members, paid messages, mentions, Buddy's marks and removals each read at a glance, and the rest waits in its ⋯ menu.

Installation

$ pnpm dlx shadcn@latest add @videorc/chat-message

Usage

import { ChatMessage } from "@/components/blocks/stream-manager/chat-message";
import type { ChatMessageData } from "@/components/blocks/stream-manager/chat-message";
const message: ChatMessageData = {
  id: "m1",
  platform: "youtube",
  authorName: "Maya Chen",
  text: "Which microphone are you using on stream today?",
  time: "8:41 PM",
};

<ol aria-label="Chat messages">
  <ChatMessage
    highlight={{ phase: onStream === message.id ? "live" : "idle" }}
    message={message}
    onHighlight={toggleOnStream}
    onReply={replyTo}
  />
</ol>;

A message is plain data. ChatMessage renders one <li>, so put the rows in an <ol>. With onHighlight the row is one button: a click puts the message on stream, and a click on the row that's on stream takes it off. Without it the row is plain text, as in History.

Format time yourself, once, so the server and the browser agree: formatChatTime(receivedAt) gives Videorc's "8:42 PM".

Examples

Every state

The row on stream wears the live chrome plate. A member's row is the quieter plate with a member-hue edge, a paid message is the warning fill with a hairline ring, and Buddy's "Talking about this" is the flat accent. A row paints one of them at most, and the row on stream beats them all. Chips sit after the name: roles, first chat, @you for a mention, the amount, Buddy's mark, the stream state and the removal. A failed show and an unusual removal say why on the row's own line.

  1. promo_bot_77Removedfree followers at a site you've never heard of
  2. TwitchModerationpromo_bot_77 was timed out for 10 minutes.

Compact

density="compact" sets 12 px text and a 32 px avatar, for a narrow rail beside the Studio. The Stream Manager keeps the 15 px rows.

  1. Maya ChenWhich microphone are you using on stream today?
  2. nightowl_jonasMemberThe new two-camera scene looks so clean.
  3. Priya RamanWatching from Lisbon.

Theming

Token or attributeMeaning
chrome-row-liveThe row on stream (CHROME_ROW_CLASS.live)
chrome-row-memberA member's row (CHROME_ROW_CLASS.member)
bg-warning/10 ring-warning/30A paid message
bg-accentThe message the streamer is talking about
Badge chrome, destructive, warning, plateOn stream, Failed, the amount, Member
group/chat-message, group/kebab-hostThe row the time and the ⋯ wait for
data-highlight-phaseidle, applying, live or failed
data-row-tintpaid, spotlight or member
data-mention, data-memberSet on a mention and on a member's row
data-slotchat-message, chat-message-author, chat-message-text, chat-message-reply, chat-message-problem, chat-message-outcome

Keyboard

KeyAction
Enter SpacePuts the message on stream, or takes it off
TabMoves to the row's ⋯ menu

Accessibility

A highlightable row is one button named by what it says: author, platform and words ("Maya Chen on YouTube: Which microphone…"). aria-pressed says it's on stream and the description says what a click does, then any outcome the row shows. A drag that selects words in the row copies them and never puts the message on stream. The time and the ⋯ wait for the pointer while live (timestamps="hover") and appear with keyboard focus. Every chip that stands for more says it in a tooltip, never a native title.

API reference

Prop

Type

ChatMessageData

Prop

Type

ChatMessageHighlight

Prop

Type

ChatMessageRemoval

Prop

Type

ChatMessageFlag

Prop

Type

Helpers

HighlightStatus and RemovalStatus are the row's two status chips, for rows of your own that share the slot (the Activity Feed does). chatMessageMenu(message, options) builds the ⋯ items; chatMessageMentions(message, names), chatMessageCanHighlight(message), chatMessageInitials(name) and formatChatTime(iso) are the rules the row follows.