BranderChatWidget

Floating chat widget with customizable trigger button

Import

import { BranderChatWidget, sseStream } from '@brander/sdk';

// Or with specific adapters
import { BranderChatWidget, anthropicStream, openaiStream, geminiStream } from '@brander/sdk';

Overview

BranderChatWidget is a floating chat interface that appears on top of your application. It includes:

  • Custom Trigger Button: You provide any React element as the trigger
  • Floating Popup: Widget appears above your content with optional backdrop
  • Flexible Positioning: Choose from 4 corner positions
  • Smooth Animations: Configurable fade and slide effects
  • Mobile Responsive: Optimized for all screen sizes

Basic Usage (Streaming)

App.tsx
import { BranderChatWidget, sseStream } from '@brander/sdk';

function App() {
  return (
    <div className="app">
      <h1>My Application</h1>
      <p>Your main content here...</p>

      <BranderChatWidget
        betaKey="bux_your_token"
        projectId="my-project-id"
        onQueryStream={(params) => sseStream("/api/agent", { params })}
        position="bottom-right"
      >
        {/* Custom trigger button */}
        <button style={{
          padding: '12px 24px',
          borderRadius: '50px',
          backgroundColor: '#0066FF',
          color: 'white',
          border: 'none',
          cursor: 'pointer'
        }}>
          Chat with AI
        </button>
      </BranderChatWidget>
    </div>
  );
}

Props

Required Props
  • betaKey: string - Your BranderUX API token
  • projectId: string - Your BranderUX project ID
  • AI Handler (ONE of the following):
    • onQueryStream: StreamingCallback - Streaming handler (Recommended)
    • onQuery: OnQueryCallback - Non-streaming handler (Alternative)
  • children: React.ReactElement - Custom trigger button/element
Widget Configuration
  • position?: "bottom-right" | "bottom-left" | "top-right" | "top-left"
    Widget position on screen (default: "bottom-right")
  • offset?: { top?: number; bottom?: number; left?: number; right?: number }
    Offset from edges in pixels (default: { bottom: 24, right: 24 })
  • widgetSize?: { width?: string; height?: string }
    Widget popup dimensions (default: { width: "400px", height: "650px" })
Behavior
  • defaultOpen?: boolean - Initially open state (default: false)
  • onOpen?: () => void - Callback when widget opens
  • onClose?: () => void - Callback when widget closes
  • showBackdrop?: boolean - Show backdrop overlay when open (default: true)
  • backdropOpacity?: number - Backdrop opacity 0-1 (default: 0.2)
  • closeOnBackdropClick?: boolean - Close when clicking backdrop (default: true)
Styling
  • zIndex?: number - z-index for widget elements (default: 9999)
  • widgetClassName?: string - CSS class for popup container
  • animationDuration?: number - Animation duration in ms (default: 200)
AI Configuration
  • variant?: "hybrid" | "classic" | "chat" - Display variant (default: "classic")
    • "hybrid": Full playground with scroll-snapping and query badges
    • "classic": Clean site-focused view with conversation sidebar
    • "chat": Chat-style scrolling with inline messages
Conversation History
  • conversations?: Conversation[] - Initial conversations to load
  • activeConversationId?: string - Currently active conversation ID
  • onConversationsChange?: (state: ConversationsState) => void - Callback for conversation state changes

Positioning Examples

Bottom Right (Default)
<BranderChatWidget
  {...props}
  onQueryStream={(params) => sseStream("/api/agent", { params })}
  position="bottom-right"
  offset={{ bottom: 24, right: 24 }}
>
  <button>Chat</button>
</BranderChatWidget>
Top Left
<BranderChatWidget
  {...props}
  onQueryStream={(params) => sseStream("/api/agent", { params })}
  position="top-left"
  offset={{ top: 80, left: 24 }}
>
  <button>Support</button>
</BranderChatWidget>
Bottom Left with Custom Size
<BranderChatWidget
  {...props}
  onQueryStream={(params) => sseStream("/api/agent", { params })}
  position="bottom-left"
  offset={{ bottom: 20, left: 20 }}
  widgetSize={{ width: "500px", height: "800px" }}
>
  <button>Help</button>
</BranderChatWidget>

Full Configuration Example

App.tsx
import { BranderChatWidget, sseStream } from '@brander/sdk';
import { MessageCircle } from 'lucide-react';

function App() {
  return (
    <div className="app">
      <header>
        <h1>My SaaS Application</h1>
      </header>

      <main>
        {/* Your main content */}
      </main>

      <BranderChatWidget
        // Required
        betaKey="bux_your_token"
        projectId="my-project-id"
        onQueryStream={(params) => sseStream("/api/agent", { params })}
        // Widget Configuration
        position="bottom-right"
        offset={{ bottom: 24, right: 24 }}
        widgetSize={{ width: "450px", height: "700px" }}
        // Behavior
        defaultOpen={false}
        onOpen={() => console.log('Chat opened')}
        onClose={() => console.log('Chat closed')}
        showBackdrop={true}
        backdropOpacity={0.3}
        closeOnBackdropClick={true}
        // Styling
        zIndex={9999}
        animationDuration={250}
        widgetClassName="custom-chat-widget"
      >
        {/* Custom trigger button with icon */}
        <button
          style={{
            display: 'flex',
            alignItems: 'center',
            gap: '8px',
            padding: '14px 28px',
            backgroundColor: '#0066FF',
            color: 'white',
            border: 'none',
            borderRadius: '50px',
            fontSize: '16px',
            fontWeight: 600,
            cursor: 'pointer',
            boxShadow: '0 4px 12px rgba(0, 102, 255, 0.3)',
            transition: 'all 0.2s ease'
          }}
          onMouseEnter={(e) => {
            e.currentTarget.style.transform = 'scale(1.05)';
            e.currentTarget.style.boxShadow = '0 6px 16px rgba(0, 102, 255, 0.4)';
          }}
          onMouseLeave={(e) => {
            e.currentTarget.style.transform = 'scale(1)';
            e.currentTarget.style.boxShadow = '0 4px 12px rgba(0, 102, 255, 0.3)';
          }}
        >
          <MessageCircle size={20} />
          Chat with AI
        </button>
      </BranderChatWidget>
    </div>
  );
}

Alternative: Non-Streaming

App.tsx
import { BranderChatWidget } from '@brander/sdk';

function App() {
  return (
    <BranderChatWidget
      betaKey="bux_your_token"
      projectId="my-project-id"
      onQuery={async (params) => {
        const response = await fetch('/api/ai', {
          method: 'POST',
          body: JSON.stringify(params)
        });
        return response.json();
      }}
      position="bottom-right"
    >
      <button>Chat</button>
    </BranderChatWidget>
  );
}

Custom Trigger Button Examples

Simple Button
<BranderChatWidget {...props}>
  <button className="chat-trigger">
    Chat
  </button>
</BranderChatWidget>
Floating Action Button (FAB)
<BranderChatWidget {...props}>
  <button style={{
    width: '60px',
    height: '60px',
    borderRadius: '50%',
    backgroundColor: '#1976d2',
    color: 'white',
    border: 'none',
    fontSize: '24px',
    cursor: 'pointer',
    boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)'
  }}>
    💬
  </button>
</BranderChatWidget>
With MUI Components
import { Fab } from '@mui/material';
import ChatIcon from '@mui/icons-material/Chat';

<BranderChatWidget {...props}>
  <Fab color="primary" aria-label="chat">
    <ChatIcon />
  </Fab>
</BranderChatWidget>
Custom Component
const CustomTrigger = () => (
  <div style={{
    display: 'flex',
    alignItems: 'center',
    gap: '8px',
    padding: '12px 20px',
    background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
    color: 'white',
    borderRadius: '12px',
    cursor: 'pointer',
    boxShadow: '0 4px 15px rgba(102, 126, 234, 0.4)'
  }}>
    <span>🤖</span>
    <span style={{ fontWeight: 600 }}>AI Assistant</span>
  </div>
);

<BranderChatWidget {...props}>
  <CustomTrigger />
</BranderChatWidget>

Use Cases

  • Customer Support: Add AI-powered chat support to any page
  • Help Centers: Provide instant answers without leaving the page
  • Sales Assistants: Guide users through product discovery
  • Documentation Helper: Answer questions about your product
  • Virtual Assistants: Provide personalized user assistance

BranderChatWidget vs Brander

FeatureBranderChatWidgetBrander
IntegrationFloating widgetInline embed
Trigger ButtonCustom (required)None
PositionConfigurable (4 corners)Fixed in layout
BackdropYes (optional)No
Best ForSupport, help centersDashboards, data tools
MobileOptimized overlayResponsive layout