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

@bbki.ng/bb-msg-history

v1.0.0

Published

A chat-style message history web component

Readme

bb-msg-history

Chat-style message history web component. Render conversations from plain text, with avatars, bubbles, and smooth animations.

Install

npm install @bbki.ng/bb-msg-history

CDN:

<script type="module" src="https://cdn.jsdelivr.net/npm/@bbki.ng/bb-msg-history@latest/dist/index.js"></script>

Usage

Place messages inside the element using the author: text format, one per line:

<bb-msg-history>
  alice: Hey, are you free this weekend?
  bob: Sounds good! When?
  alice: Saturday morning, around 10?
  bob: Perfect. See you then!
</bb-msg-history>

Message Format

Each message is a line with the author name, a colon, and the message text:

<author>: <message text>

Blank lines and lines without a colon are ignored.

Author Avatars

By default, every author gets a letter avatar (first character of their name) and appears on the left side.

Use the setAuthor() method to customize avatar, side, bubble color, and text color:

const el = document.querySelector('bb-msg-history');

// Emoji avatar, right side
el.setAuthor('me', { avatar: '🐱', side: 'right' });

// Image avatar, custom bubble color
el.setAuthor('bot', {
  avatar: '<img src="bot.png" width="28" height="28" />',
  side: 'left',
  bubbleColor: '#e0f2fe',
});

// SVG avatar
el.setAuthor('alice', {
  avatar: '<svg viewBox="0 0 48 48">...</svg>',
  side: 'left',
});

setAuthor(name, options)

| Option | Type | Default | Description | |--------|------|---------|-------------| | avatar | string | letter avatar | HTML string: emoji, <img>, <svg>, or text | | side | 'left' \| 'right' | 'left' | Which side the bubbles appear on | | bubbleColor | string | '#f9fafb' | Bubble background color | | textColor | string | '#111827' | Text color inside bubble |

Returns this for chaining:

el.setAuthor('me', { avatar: '🐱', side: 'right' })
  .setAuthor('you', { avatar: '🐶', side: 'left' });

Fuzzy matching: if an author name contains a configured key (e.g. you configured "alice" and the message is from "alice(phone)"), the config is reused.

Use removeAuthor(name) to remove a custom config.

appendMessage(message)

Append a message programmatically with smooth scroll to the new message.

| Parameter | Type | Description | |-----------|------|-------------| | message.author | string | The author name | | message.text | string | The message text |

el.appendMessage({ author: 'alice', text: 'Hello!' });
el.appendMessage({ author: 'bob', text: 'How are you?' });

Returns this for chaining. This is ideal for chat applications where messages arrive in real-time.

Note: Unlike modifying textContent directly, appendMessage() scrolls smoothly to the newly added message.

setLoading(isLoading)

Show or hide a loading animation overlay. Useful when fetching messages from an API.

| Parameter | Type | Description | |-----------|------|-------------| | isLoading | boolean | true to show loading, false to hide |

const el = document.querySelector('bb-msg-history');

// Show loading
el.setLoading(true);

// Fetch messages
fetchMessages().then(messages => {
  // Hide loading and display messages
  el.setLoading(false);
});

You can also use the HTML attribute:

<bb-msg-history loading>
  alice: Loading previous messages...
</bb-msg-history>

infinite Attribute

Remove the height constraint and disable scrolling on the component. The container expands to fit all messages.

Use this when:

  • The parent container handles scrolling
  • You want to display an entire conversation without height limits
  • You need the component to be part of a larger scrollable area
<bb-msg-history infinite>
  alice: First message
  bob: Second message
  alice: Third message
  <!-- Container keeps expanding to fit all messages -->
</bb-msg-history>

In infinite mode:

  • No max-height constraint is applied
  • No scrollbar appears on the component
  • The scroll-to-bottom button is hidden (not needed)

Customization

CSS Custom Properties

| Property | Default | Description | |----------|---------|-------------| | --bb-max-height | 600px | Maximum height of the message container |

bb-msg-history {
  --bb-max-height: 400px;
}

Manual Registration

By default, the component auto-registers as <bb-msg-history>. You can also register manually with a custom tag name:

import { BBMsgHistory, define } from '@bbki.ng/bb-msg-history';

// Register with default tag name
define();

// Or use a custom tag name
define('my-chat-history');

Features

  • Plain-text message format — no JSON or attributes needed
  • Left/right bubble layout based on author
  • Customizable avatars: emoji, <img>, <svg>, or letter avatars
  • Hover tooltip showing the author name
  • Consecutive messages from the same author are grouped (avatar hidden)
  • Auto-scroll to the latest message on render
  • appendMessage() API — programmatically add messages with smooth scroll
  • setLoading() API — show loading animation while fetching messages
  • Long text word-wrap and overflow handling
  • Empty state when no messages are provided
  • Dark mode support via prefers-color-scheme
  • Mobile responsive layout
  • prefers-reduced-motion support
  • Reactive: automatically re-renders when content changes
  • Customizable max-height via --bb-max-height CSS custom property
  • infinite attribute — remove height constraints for parent-controlled scrolling
  • Graceful degradation to <pre> when Custom Elements are unsupported

Examples

Basic

<bb-msg-history>
  alice: Hey, are you free this weekend?
  bob: Sounds good! When?
  alice: Saturday morning, around 10?
  bob: Perfect. See you then!
</bb-msg-history>

Custom avatars

<bb-msg-history id="chat">
  me: Hey there!
  friend: What's up?
</bb-msg-history>

<script>
  const el = document.getElementById('chat');
  el.setAuthor('me', { avatar: '🐱', side: 'right', bubbleColor: '#f3f4f6' });
  el.setAuthor('friend', { avatar: '🐶', side: 'left', bubbleColor: '#e0f2fe' });
</script>

Consecutive messages — avatar grouping

When the same author sends multiple messages in a row, the avatar is only shown on the first one:

<bb-msg-history>
  alice: First message
  alice: Second message, avatar hidden
  alice: Third, still hidden
  bob: Got it!
  bob: I'll send two as well
</bb-msg-history>

Unknown authors — letter avatars

Authors without custom config receive a letter avatar and appear on the left:

<bb-msg-history>
  alice: Hello!
  bob: Hi there!
  charlie: Hey everyone!
</bb-msg-history>

Empty state

When no messages are provided, a "No messages" placeholder is shown:

<bb-msg-history></bb-msg-history>

Dynamic message appending

Use appendMessage() to add messages programmatically with smooth scrolling:

<bb-msg-history id="chat" style="--bb-max-height: 300px;">
  alice: Hey there!
</bb-msg-history>

<script>
  const el = document.getElementById('chat');
  el.setAuthor('alice', { avatar: '👩', side: 'right' });
  el.setAuthor('bob', { avatar: '👨', side: 'left' });

  // Add messages dynamically with smooth scroll
  el.appendMessage({ author: 'bob', text: 'Hello! How are you?' });
  el.appendMessage({ author: 'alice', text: 'I\'m doing great!' });
  
  // Simulate receiving a message after 2 seconds
  setTimeout(() => {
    el.appendMessage({ author: 'bob', text: 'Nice to hear that!' });
  }, 2000);
</script>

Loading state

Show a loading animation while fetching messages from an API:

<bb-msg-history id="chat" loading>
  <!-- Messages will be loaded -->
</bb-msg-history>

<script>
  const el = document.getElementById('chat');

  // Show loading (already set via HTML attribute above)
  // el.setLoading(true);

  // Fetch messages from API
  fetch('/api/messages')
    .then(res => res.json())
    .then(messages => {
      // Hide loading and populate messages
      el.setLoading(false);
      messages.forEach(msg => {
        el.appendMessage({ author: msg.author, text: msg.text });
      });
    });
</script>

Full page example

<!DOCTYPE html>
<html>
<head>
  <script type="module" src="https://cdn.jsdelivr.net/npm/@bbki.ng/bb-msg-history@latest/dist/index.js"></script>
</head>
<body>
  <bb-msg-history id="chat">
    alice: Hey, are you free this weekend?
    bob: Yeah, what's up?
    alice: Want to grab coffee?
    bob: Sounds good! Saturday morning?
    alice: Perfect, see you then!
  </bb-msg-history>

  <script>
    const el = document.getElementById('chat');
    el.setAuthor('alice', { avatar: '👩', side: 'right' });
    el.setAuthor('bob', { avatar: '👨', side: 'left', bubbleColor: '#ecfdf5' });
  </script>
</body>
</html>

See example/ directory for a full demo.

Development

npm install
npm run prepare

License

MIT