@htmlbricks/hb-messages-topics-card
v0.73.7
Published
Lists chat or channel previews from `chats`: avatar, title, last message snippet, derived time label, and unread `counter` badge. Clicking a row marks it selected (`_selected`) and dispatches `select` with that chat payload for opening a thread or switchi
Downloads
10,853
Readme
hb-messages-topics-card
Category: messaging · Tags: messaging, chat · Package: @htmlbricks/hb-messages-topics-card
Description
Renders a vertical list of chat or channel previews from a chats collection. Each row shows a rounded avatar, a title, a short message preview, a time label, and an unread counter rendered as a Bulma tag. Clicking a row updates internal selection state (_selected), highlights the row, and dispatches a select custom event with the clicked chat object so the host can open a thread or switch context.
Styling (Bulma)
The component bundles Bulma 1.x inside the shadow root: layout/media, layout/level, elements/image, elements/tag, and typography / spacing helpers, with the light theme applied on :host. Public --bulma-* variables can be set on body, :root, or the host so they cascade consistently with the rest of the app — see Bulma CSS variables and the styleSetup.vars entries in extra/docs.ts.
| Variable | Purpose |
|----------|---------|
| --bulma-text | Title and preview snippet text. |
| --bulma-text-strong | Strong title weight color (falls back to --bulma-text). |
| --bulma-text-weak | Muted time label beside each preview. |
| --bulma-border | Divider between rows. |
| --bulma-scheme-main-bis | Hover background for rows that are not selected. |
| --bulma-scheme-main-ter | Selected row background. |
| --bulma-radius-rounded | Pill shape for the unread counter tag. |
Shadow markup (simplified):
article.media.hb-topics-item— clickable row;hb-topics-item--selectedwhen that chat is selected.figure.media-left+p.image.is-64x64+img.is-rounded— avatar fromimg_uri.div.media-content— Bulmalevelrows for title + time, then preview + counter tag.
CSS parts
None.
HTML slots
None.
Custom element
hb-messages-topics-card
Attributes (snake_case; string values in HTML)
Per the web component contract, attributes are strings. The primary payload is JSON on chats.
| Attribute | Required | Description |
|-----------|----------|-------------|
| id | No | Optional host identifier. |
| style | No | Optional inline host styles (typed on the component surface). |
| chats | No* | JSON string: array of chat objects (IChat[]). Defaults to an empty list if omitted. |
* In markup you may omit chats until you set the attribute; the component defaults to an empty list.
chats JSON shape (IChat)
Fields used for layout and labels in the current implementation:
| Field | Role |
|-------|------|
| chat_id | Stable key for each row (also used in {#each} keyed updates). |
| title | Primary line (semibold). |
| text | Preview line under the title. |
| img_uri | Avatar URL (img src). |
| time | Source for the time label when localeTimeString is not set; use an ISO 8601 string in JSON so it parses as a date. |
| localeTimeString | If set, shown as-is instead of deriving HH:MM from time. |
| counter | Unread count; rendered in the tag (missing or falsy shows 0). |
| _selected | When true, that row starts selected and receives the selected background. |
Additional optional fields (is_group, chat_name, chat_img, last_message_*, and so on) are part of the IChat type so you can carry richer metadata; they are not read by the template today but are still present on objects emitted by select.
If the chats prop arrives as a string (for example from an HTML attribute), the component parses it with JSON.parse; invalid JSON is logged to the console and parsing is skipped.
Events
| Event | detail |
|-------|----------|
| select | The clicked IChat object (same reference the list uses after selection is updated). |
Listen in plain JavaScript:
const el = document.querySelector("hb-messages-topics-card");
el.addEventListener("select", (e) => {
const chat = e.detail;
console.log(chat.chat_id, chat.title);
});Usage notes
- Initial selection: set
_selectedon at most one item in the JSON if you want a default active row. - Time display: without
localeTimeString, the component fills it fromtimeusing the local hours and minutes (HH:MM). ProvidelocaleTimeStringyourself for relative times or locale-specific formatting. - Unread badge: the tag always shows a value;
0is shown when there is no positive counter. - Avatars: the template sets
alt=""on images; if you need accessible names, extend your integration (for example wrapping context or contributing upstream) because the component does not derive labels fromtitletoday.
Types
export type IChat = {
time: Date;
title: string;
text: string;
img_uri: string;
is_group?: boolean;
chat_name?: string;
chat_img?: string;
chat_id: string;
last_message_author?: string;
last_message_author_img?: string;
last_message_time?: Date;
last_message_text?: string;
counter?: number;
localeTimeString?: string;
_selected?: boolean;
};
export type Component = {
id?: string;
style?: string;
chats?: IChat[];
};
export type Events = {
select: IChat;
};Minimal HTML example
<hb-messages-topics-card
chats='[{"chat_id":"1","title":"Team","text":"Hello","time":"2026-01-01T12:00:00.000Z","img_uri":"https://example.com/a.png","counter":2}]'
></hb-messages-topics-card>Storybook / metadata
Argument controls and additional named examples (selected row, unread badges, single chat) live in extra/docs.ts.
