@versini/ui-bubble
TypeScript icon, indicating that this package has built-in type declarations

5.0.0 • Public • Published

@versini/ui-bubble

npm version

A flexible and feature-rich React bubble component built with TypeScript and TailwindCSS.

The Bubble component provides chat-style message bubbles with support for footers, copy-to-clipboard functionality, and customizable positioning. Perfect for building chat interfaces, notifications, or callout sections.

Table of Contents

Features

  • 🎯 Chat Bubbles: Left and right-aligned message bubbles with optional tails
  • 📋 Copy Functionality: Built-in copy-to-clipboard with custom copy handling
  • 📊 Footer Support: Structured footer with key-value pairs or raw JSX
  • ♿ Accessible: Keyboard navigation and screen reader support
  • 🎨 Customizable: Multiple styling options and theme support
  • 🌲 Tree-shakeable: Lightweight and optimized for bundle size
  • 🔧 TypeScript: Fully typed with comprehensive prop definitions

Installation

npm install @versini/ui-bubble

Note: This component requires TailwindCSS and the @versini/ui-styles plugin for proper styling. See the root README for complete setup instructions.

Usage

Basic Bubbles

import { Bubble } from "@versini/ui-bubble";

function App() {
  return (
    <div className="space-y-4">
      <Bubble kind="left" tail>
        Hello! This is a left-aligned message.
      </Bubble>

      <Bubble kind="right" tail>
        And this is a right-aligned reply.
      </Bubble>
    </div>
  );
}

Bubble with Footer

import { Bubble } from "@versini/ui-bubble";

function App() {
  return (
    <Bubble
      kind="right"
      tail
      footer={{
        Sent: "12:00 PM",
        Delivered: "12:01 PM",
        Read: "12:02 PM"
      }}
    >
      Message with delivery status footer.
    </Bubble>
  );
}

Copy to Clipboard

import { Bubble } from "@versini/ui-bubble";

function App() {
  return (
    <div className="space-y-4">
      {/* Simple copy - copies the bubble content */}
      <Bubble kind="left" copyToClipboard>
        Click the copy icon to copy this message.
      </Bubble>

      {/* Custom copy text */}
      <Bubble kind="left" copyToClipboard="Custom text to copy">
        This will copy custom text instead of the bubble content.
      </Bubble>

      {/* Custom copy function */}
      <Bubble
        kind="left"
        copyToClipboard={(text) => {
          navigator.clipboard.writeText(`Copied: ${text}`);
        }}
      >
        This uses a custom copy function.
      </Bubble>
    </div>
  );
}

Chat Interface

import { Bubble } from "@versini/ui-bubble";

function ChatExample() {
  const messages = [
    { id: 1, text: "Hey, how are you?", kind: "left", time: "10:30 AM" },
    {
      id: 2,
      text: "I'm good, thanks! How about you?",
      kind: "right",
      time: "10:32 AM"
    },
    {
      id: 3,
      text: "Doing great! Want to grab lunch?",
      kind: "left",
      time: "10:35 AM"
    }
  ];

  return (
    <div className="max-w-md mx-auto space-y-3 p-4 bg-gray-50 rounded-lg">
      {messages.map((message) => (
        <Bubble
          key={message.id}
          kind={message.kind}
          tail
          footer={{ Time: message.time }}
          copyToClipboard
        >
          {message.text}
        </Bubble>
      ))}
    </div>
  );
}

Advanced Footer Usage

import { Bubble } from "@versini/ui-bubble";

function AdvancedFooterExample() {
  return (
    <div className="space-y-4">
      {/* Structured footer with empty row */}
      <Bubble
        kind="right"
        tail
        footer={{
          "Message ID": "msg-123",
          Sent: "2:30 PM",
          Status: Bubble.FOOTER_EMPTY, // Empty row that maintains height
          Delivered: "2:31 PM",
          Read: "2:35 PM"
        }}
      >
        Message with detailed tracking information.
      </Bubble>

      {/* Raw JSX footer */}
      <Bubble
        kind="left"
        rawFooter={
          <div className="flex justify-between items-center text-xs">
            <span className="text-green-600">✓ Verified</span>
            <span>3:45 PM</span>
          </div>
        }
      >
        Message with custom JSX footer.
      </Bubble>
    </div>
  );
}

Custom Width Control

import { Bubble } from "@versini/ui-bubble";

function CustomWidthExample() {
  return (
    <div className="space-y-4">
      {/* Default responsive width */}
      <Bubble kind="left" tail>
        This bubble has default responsive width behavior.
      </Bubble>

      {/* Custom width with container queries */}
      <div style={{ containerType: "inline-size" }} className="w-96">
        <Bubble kind="left" tail noMaxWidth className="max-w-[95cqw]">
          This bubble uses container query width (95% of container width).
        </Bubble>
      </div>

      {/* Fixed width */}
      <Bubble kind="right" tail noMaxWidth className="w-64">
        This bubble has a fixed width of 256px.
      </Bubble>
    </div>
  );
}

Copy Functionality Variations

import { Bubble } from "@versini/ui-bubble";

function CopyFunctionalityExample() {
  const handleCustomCopy = (text: any) => {
    // Custom copy logic
    const copyText = `Shared message: "${text}"`;
    navigator.clipboard.writeText(copyText);
    console.log("Copied with custom format:", copyText);
  };

  return (
    <div className="space-y-4">
      {/* Boolean - copies bubble content */}
      <Bubble kind="left" copyToClipboard={true}>
        Basic copy functionality
      </Bubble>

      {/* String - copies specific text */}
      <Bubble kind="left" copyToClipboard="contact@example.com">
        Click to copy: contact@example.com
      </Bubble>

      {/* Function - custom copy behavior */}
      <Bubble kind="left" copyToClipboard={handleCustomCopy}>
        Custom copy behavior with formatting
      </Bubble>

      {/* With custom copy button styling */}
      <Bubble
        kind="right"
        copyToClipboard
        copyToClipboardMode="dark"
        copyToClipboardFocusMode="light"
      >
        Copy button with custom theme
      </Bubble>
    </div>
  );
}

API

Bubble Props

Prop Type Default Description
children React.ReactNode - The text to render in the bubble
kind "left" | "right" "left" The type of Bubble (changes color and chevron location)
tail boolean false Whether or not the Bubble should have a tail
copyToClipboard boolean | string | ((text: any) => void) - Copy functionality configuration
footer { [key: string]: string | number | undefined | null } - Object depicting the extra rows for the Bubble footer
rawFooter React.ReactNode - Same as "footer" but accepts raw JSX
noMaxWidth boolean false Whether to disable default responsive max-width
className string - CSS class(es) to add to the main component wrapper
contentClassName string - CSS class(es) to add to the content wrapper
copyToClipboardMode "dark" | "light" | "system" | "alt-system" "system" The mode of Copy Button
copyToClipboardFocusMode "dark" | "light" | "system" | "alt-system" "system" The focus mode for the Copy Button

Special Values

  • Bubble.FOOTER_EMPTY - Use in footer to create an empty row that maintains height

Readme

Keywords

none

Package Sidebar

Install

npm i @versini/ui-bubble

Weekly Downloads

55

Version

5.0.0

License

MIT

Unpacked Size

38.9 kB

Total Files

6

Last publish

Collaborators

  • aversini