Skip to content

Bubble Customization

The bubble's appearance is fully customizable through HTML attributes, CSS custom properties, and custom launcher elements.

CSS Custom Properties

Override these properties on the <saytv-chat-bubble> element to fine-tune the appearance beyond what attributes offer.

PropertyDefaultDescription
--stv-bubble-size60pxLauncher button diameter. Prefer the bubble-size attribute.
--stv-bubble-color#7e171cLauncher background color. Prefer the bubble-color attribute.
--stv-bubble-offset-x24pxHorizontal offset from viewport edge.
--stv-bubble-offset-y24pxVertical offset from viewport edge.
--stv-bubble-z-index999999Stacking order.
--stv-bubble-panel-width350pxChat panel width.
--stv-bubble-panel-height600pxChat panel height.
--stv-bubble-panel-radius16pxChat panel border radius.
--stv-bubble-gap16pxSpace between the launcher and the panel/greeting.

Example

css
saytv-chat-bubble {
  --stv-bubble-panel-radius: 24px;
  --stv-bubble-gap: 20px;
  --stv-bubble-z-index: 500;
}

TIP

Attributes like bubble-size, bubble-color, offset-x, offset-y, chat-width, and chat-height set these CSS properties automatically. Use custom properties directly only when you need values not covered by attributes (like --stv-bubble-panel-radius or --stv-bubble-gap).

Custom Launcher

Replace the built-in circular button with any element on your page using the custom-launcher attribute:

html
<button id="my-chat-button" class="my-custom-launcher">
  💬 Chat with us
</button>

<saytv-chat-bubble
  app-id="your-app-id"
  custom-launcher="#my-chat-button"
></saytv-chat-bubble>

When custom-launcher is set:

  • The built-in launcher button is hidden
  • Click events on the referenced element toggle the chat panel
  • You have full control over the trigger's appearance, position, and behavior
  • The chat panel still appears at the bubble element's position

Positioning the panel with a custom launcher

The panel is positioned relative to the bubble element, not the custom launcher. If your custom launcher is in a different location, adjust the bubble's offset to align the panel:

html
<saytv-chat-bubble
  app-id="your-app-id"
  custom-launcher="#my-header-button"
  position="bottom-right"
  offset-x="20"
  offset-y="20"
></saytv-chat-bubble>

Custom Launcher Icon

Replace the default chat icon with a custom image while keeping the built-in launcher button:

html
<saytv-chat-bubble
  app-id="your-app-id"
  bubble-icon="https://cdn.example.com/my-icon.png"
></saytv-chat-bubble>

The image is displayed as a 32px circle inside the launcher. When the panel is open, the icon morphs to a close (X) icon.

Theming the Inner Widget

The inner <saytv-chat> widget inherits the theme attribute from the bubble. You can also pass CSS custom properties to style the widget through the bubble:

html
<saytv-chat-bubble
  app-id="your-app-id"
  theme="dark"
  style="--stv-color-primary: #0066cc; --stv-color-accent: #00cc66;"
></saytv-chat-bubble>

All <saytv-chat> theming variables work. See the Theming guide for the full list.

Animations

The bubble uses CSS transitions for all animations:

AnimationDurationEasing
Launcher hover scale150msease
Launcher active press150msease
Icon morph (chat ↔ close)300mscubic-bezier(0.4, 0, 0.2, 1)
Panel open (slide up + scale)300mscubic-bezier(0.4, 0, 0.2, 1)
Panel close (slide down + scale)200mscubic-bezier(0.4, 0, 0.2, 1)
Greeting tooltip appear300mscubic-bezier(0.4, 0, 0.2, 1)
Unread badge scale200mscubic-bezier(0.4, 0, 0.2, 1)

All animations respect prefers-reduced-motion: reduce. When the user has motion reduction enabled, transition durations are set to 0ms.

Mobile Behavior

On viewports narrower than 768px:

  • The chat panel goes full-screen (100% width and height) instead of floating
  • The panel slides up from the bottom
  • The greeting tooltip is hidden (not useful on small screens)
  • The launcher button remains visible for opening/closing

To hide the bubble entirely on mobile, add the hide-on-mobile attribute:

html
<saytv-chat-bubble
  app-id="your-app-id"
  hide-on-mobile
></saytv-chat-bubble>

Accessibility

The bubble follows WAI-ARIA patterns for disclosure widgets:

  • The launcher has role="button" and aria-expanded reflecting the panel state
  • The launcher's aria-label updates between "Open chat" and "Close chat"
  • The panel has role="dialog" with aria-label="Chat"
  • The unread badge uses aria-live="polite" for screen reader announcements
  • Focus returns to the launcher when the panel closes
  • The launcher supports :focus-visible styling
  • Keyboard: Escape closes the panel

Bundle Size

The bubble is a separate entry point from the main widget, keeping its own footprint small:

FormatSize (gzip)
ESM (bubble.mjs)~5 kB
IIFE (bubble.iife.js)~4 kB

The inner <saytv-chat> widget is loaded lazily when the user first opens the panel.

SayTV Chat SDK Documentation