cnc-chat
A conversation view with a channel header, message bubbles made of text, markdown, code, image
and file parts, a reply still being written, and a message box that reports what was typed as a
prompt event.
Quick start
Bind the messages and participants, and name the reader with
user: their messages sit on the right, everyone else's on the left. Give the chat a
height — the conversation scrolls inside it.
-
joe
Morning! Did the build go out last night?
09:12 -
doris
It did.
The styles are rebuilt with this:
09:14 -
tailwindcss --config ./tailwind.config.cjs --minify -i ./src/style.css -o ./static/style.css 09:14 -
joe
Great, thanks.
09:15
// the block's controller
export default {
localUser: 'doris',
participants: [
{ id: 'doris', displayName: 'Doris Lane', avatarUrl: '/doris.jpg' },
{ id: 'joe', displayName: 'Joe Mo', avatarUrl: '/joe.jpg' },
],
messages: [
{ user: 'joe', parts: [{ type: 'text', content: 'Morning!' }], date: '09:12' },
{ user: 'doris', parts: [{ type: 'text', content: 'Hi Joe.' }], date: '09:14' },
],
}
<cnc-chat
:messages="messages"
:participants="participants"
:user="localUser"
channel-name="release"
class="h-[460px]"
></cnc-chat>
Message shape
A message is who sent it, when, and a list of parts drawn one under another in a single bubble.
| Field | Purpose |
|---|---|
| user |
Who sent it. Equal to the chat's user puts the bubble on the right in the
primary colour; anything else puts it on the left.
|
| parts |
The bubble's content, in order. Each part is { type, content }, where
type is text, markdown, code,
image or file.
|
| date | Shown under the bubble as it is given — never parsed, so format it before binding. |
Part types
| Type | Content | Drawn as |
|---|---|---|
| text | Plain text. | A paragraph that keeps its line breaks. |
| markdown | Markdown source. | Rendered through cnc-markdown. |
| code | Source code, with language beside it. |
A highlighted block through cnc-code. |
| image | The image's URL. | The image, with a Copy / Save / Forward / Delete menu. |
| file | The file's name, with size beside it. |
A file card with a Download / Forward / Delete menu. |
Things to know
-
Sending is the page's job.
Enter or the Submit button dispatches
promptwith{ prompt }. The widget does not add the message tomessages— push it there yourself, or send it to a server and wait. -
A participant needs a
displayName. The header's avatar group builds each avatar's initials from it, so a participant without one stops the header from drawing. -
Consecutive messages are grouped.
The avatar and, in a group chat, the sender's name appear once per run of messages from the
same
user, not on every bubble. - The menus only look. Copy, Save, Forward, Delete and Download on a message are drawn but report nothing; they are placeholders for actions the page will own.
-
The header reports, it does not act.
Its buttons dispatch
sidebar,favorite,channel-menu,header-actionandcall; only the sidebar and the star change anything inside the widget.
Usage guidance
Use cnc-chat where the conversation is the page — a support thread, a channel, an
assistant. Keep messages as the record of what was said and
new-message
for the one reply still arriving, so a streamed answer can grow without being written into the
history until it is complete. Replace the channel header through the header slot
when the chat sits inside something that already names it.