npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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--selected when that chat is selected.
  • figure.media-left + p.image.is-64x64 + img.is-rounded — avatar from img_uri.
  • div.media-content — Bulma level rows 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 _selected on at most one item in the JSON if you want a default active row.
  • Time display: without localeTimeString, the component fills it from time using the local hours and minutes (HH:MM). Provide localeTimeString yourself for relative times or locale-specific formatting.
  • Unread badge: the tag always shows a value; 0 is 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 from title today.

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.