Skip to content

Theming

The widget uses CSS custom properties (variables) for all visual styling. It provides full style isolation - your page styles won't leak in, and the widget styles won't leak out.

Interactive Playground

Preview all theme customizations in real time using the playground. Adjust colors, fonts, spacing, and border radius, then copy the generated code.

Share Config copies a link that reproduces your exact setup, so you can send a look to a colleague for review. Access tokens you enter yourself are never included in the link.

How It Works

The theming system has three layers, applied in order of priority:

  1. CSS Defaults - Base values defined in the widget's :host styles
  2. Backend Theme API - Runtime overrides fetched from the SayTV API
  3. Consumer Overrides - Inline style attribute on the <saytv-chat> element (highest priority)

Dark Mode

Set the theme attribute to switch between light and dark:

html
<saytv-chat app-id="your-app-id" theme="dark"></saytv-chat>

The dark theme automatically overrides backgrounds, text colors, borders, and shadows.

Custom Colors

Override any CSS variable via inline styles:

html
<saytv-chat
  app-id="your-app-id"
  theme="light"
  style="
    --stv-color-primary: #4f46e5;
    --stv-color-accent: #10b981;
    --stv-bg-primary: #fafafa;
    --stv-text-primary: #111827;
  "
></saytv-chat>

CSS Custom Properties Reference

Style the chat header and the bottom tab-bar independently of your brand color. Each variable defaults to the current brand-derived look, so nothing changes until you set one.

PropertyDefaultDescription
--stv-header-bgprimary gradientHeader background — a solid color or your own gradient
--stv-header-text--stv-text-lightHeader title text
--stv-header-icon--stv-header-textHeader icons (back, search, etc.)
--stv-footer-bg--stv-bg-primaryTab-bar background
--stv-footer-border--stv-border-lightTab-bar top border
--stv-footer-text--stv-text-mutedInactive tab label
--stv-footer-text-active--stv-color-primaryActive tab label
--stv-footer-icon--stv-footer-textInactive tab icon
--stv-footer-icon-active--stv-footer-text-activeActive tab icon
--stv-footer-indicator--stv-color-primaryActive-tab indicator pill
html
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-header-bg: #0b1020;
    --stv-header-text: #ffffff;
    --stv-footer-bg: #0b1020;
    --stv-footer-text: #8a8f9c;
    --stv-footer-text-active: #4da3ff;
    --stv-footer-indicator: #4da3ff;
  "
></saytv-chat>

Floating Navigation

When you set hide-header, a floating back button takes over so users can still leave a hashtag room or a profile. It sits directly on top of the chat, so it has its own surface colors rather than the header's.

PropertyDefaultDescription
--stv-floating-nav-bg--stv-bg-primaryButton background
--stv-floating-nav-icon--stv-text-primaryBack arrow color
--stv-floating-nav-shadow--stv-shadow-mdDrop shadow that lifts it off the content
--stv-floating-nav-size36pxButton diameter
--stv-floating-nav-offset10pxDistance from the top and side edges
html
<saytv-chat
  app-id="your-app-id"
  hide-header="true"
  style="
    --stv-floating-nav-bg: rgba(0, 0, 0, 0.6);
    --stv-floating-nav-icon: #ffffff;
    --stv-floating-nav-size: 40px;
  "
></saytv-chat>

Quiz & Poll Panels

The panel that drops in over the message list when a quiz or poll starts. Both follow your brand primary color out of the box, so setting --stv-color-primary is usually enough.

Check the text color if your brand color is light. The panels put text directly on the brand color and default to white, which needs a dark background to stay readable. WCAG AA wants a contrast ratio of at least 4.5:1 — white on a light blue such as #2faee0 is only 2.5:1. Set --stv-quiz-text / --stv-poll-text to a dark color in that case. The Playground's Style → Quiz & Poll section previews both panels and reports the ratio as you pick colors.

PropertyDefaultDescription
--stv-quiz-bgprimary gradientQuiz panel background — a solid color or your own gradient
--stv-quiz-text--stv-text-lightQuestion, options and header text
--stv-quiz-option-bgrgba(255,255,255,0.08)Answer chip background
--stv-quiz-option-bg-selectedrgba(255,255,255,0.2)Answer chip background once picked
--stv-quiz-option-borderrgba(255,255,255,0.3)Answer chip border
--stv-quiz-option-border-selected--stv-quiz-textAnswer chip border once picked
--stv-quiz-option-barrgba(255,255,255,0.15)Result bar fill behind each chip
--stv-quiz-icon-bgrgba(255,255,255,0.15)Close-button circle
--stv-quiz-submit-bgrgba(255,255,255,0.95)Submit-answer button
--stv-quiz-submit-text--stv-color-primary-darkSubmit-answer label
--stv-poll-bg--stv-quiz-bgPoll panel background
--stv-poll-text--stv-quiz-textPoll question and option text
--stv-poll-option-bg--stv-quiz-option-bgPoll option background
--stv-poll-option-border--stv-quiz-option-borderPoll option border
--stv-poll-option-bar--stv-quiz-option-barPoll result bar fill
--stv-poll-icon-bg--stv-quiz-icon-bgPoll close-button circle

Polls inherit every quiz value, so one override covers both. Set the --stv-poll-* variables only to make a poll deliberately different from a quiz.

html
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-color-primary: #2faee0;
    --stv-quiz-text: #0b2b3a;
    --stv-quiz-option-bg: rgba(0, 0, 0, 0.06);
    --stv-quiz-option-border: rgba(0, 0, 0, 0.15);
    --stv-quiz-submit-bg: #0b2b3a;
    --stv-quiz-submit-text: #ffffff;
  "
></saytv-chat>

Brand Colors

PropertyLight DefaultDescription
--stv-color-primary#7e171cPrimary brand color
--stv-color-primary-dark#5d1014Darker primary variant
--stv-color-accent#0143d9Accent / interactive color
--stv-color-accent-yellow#f8dc22Secondary accent
--stv-color-danger#e03333Error / destructive actions
--stv-color-success#1fa84aSuccess indicators
--stv-color-info#3b82f6Informational elements
--stv-color-warning#f59e0bWarning indicators

Backgrounds

PropertyLightDarkDescription
--stv-bg-primary#fafaf8#0e0e12Main background
--stv-bg-secondary#f2f0ec#161619Secondary surfaces
--stv-bg-light#f5f3ef#1c1c22Elevated surfaces
--stv-bg-hover#efede8#212128Hover state
--stv-bg-input#ffffff#1a1a20Input fields
--stv-bg-disabled#eae8e3#252530Disabled elements
--stv-bg-overlayrgba(0,0,0,0.5)-Modal overlays

Text

PropertyLightDarkDescription
--stv-text-primary#0d0d0f#f0eff5Primary text
--stv-text-secondary#4a4852#b0aebeSecondary text
--stv-text-muted#8b8a96#706e80Muted / hint text
--stv-text-light#ffffff-Text on dark backgrounds
--stv-text-hashtag#1d4ed8-Hashtag text
--stv-text-link#0143d9-Link text
--stv-text-danger#e03333-Error text

Borders

PropertyLightDarkDescription
--stv-border-color#e5e2db#2a2932Default borders
--stv-border-light#edebe5#252430Subtle borders
--stv-border-focus#0143d9-Focus ring color
--stv-border-error#e03333-Validation error

Border Radius

PropertyDefaultDescription
--stv-border-radius-xs0.25remExtra small (4px)
--stv-border-radius-sm0.375remSmall (6px)
--stv-border-radius-md0.625remMedium (10px)
--stv-border-radius-lg1remLarge (16px)
--stv-border-radius-xl1.5remExtra large (24px)
--stv-border-radius-full50%Circle

Typography

PropertyDefaultDescription
--stv-font-primarySystem sans-serif stackBody font family
--stv-font-headingSystem rounded stackHeading font family
--stv-font-mono"SF Mono", "Fira Code", monospaceMonospace font
--stv-font-size-xs0.6875rem11px
--stv-font-size-sm0.8125rem13px
--stv-font-size-base0.875rem14px
--stv-font-size-md1rem16px
--stv-font-size-lg1.25rem20px
--stv-font-size-xl1.5rem24px
--stv-font-weight-normal400Normal weight
--stv-font-weight-medium500Medium weight
--stv-font-weight-semibold600Semibold weight
--stv-font-weight-bold700Bold weight
--stv-line-height-tight1.25Compact line height
--stv-line-height-normal1.5Default line height

Custom Fonts

To use custom fonts, override the font family variables:

html
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">

<saytv-chat
  app-id="your-app-id"
  style="--stv-font-primary: 'Inter', sans-serif;"
></saytv-chat>

The font @import or <link> must be on the host page since the Shadow DOM can inherit font-face declarations from the parent document.

Spacing

PropertyDefaultDescription
--stv-spacing-xs0.25rem4px
--stv-spacing-sm0.5rem8px
--stv-spacing-md1rem16px
--stv-spacing-lg1.5rem24px
--stv-spacing-xl2rem32px
--stv-spacing-2xl3rem48px

Shadows

PropertyLightDark
--stv-shadow-sm0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)Stronger
--stv-shadow-md0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.05)Stronger
--stv-shadow-lg0 8px 24px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.06)Stronger
--stv-shadow-xl0 16px 48px rgba(0,0,0,0.14), 0 8px 16px rgba(0,0,0,0.08)Stronger

Transitions

PropertyDefaultDescription
--stv-transition-fast150ms easeHover, focus states
--stv-transition-normal250ms easeGeneral animations
--stv-transition-slow400ms easePage transitions

Extended Tokens

PropertyDefaultDescription
--stv-button-border-radiusvar(--stv-border-radius-md)Button corners
--stv-input-border-radiusvar(--stv-border-radius-lg)Input field corners
--stv-footer-label-size0.6875remFooter nav label size
--stv-skeleton-duration1.8sLoading skeleton animation

Message Appearance

Every message row can be styled with a background, a hover background, rounded corners, and a horizontal inset. A corner radius reads best paired with a background (or border) and a little side margin, which turns each row into a "card".

PropertyDefaultDescription
--stv-message-bgtransparentMessage row background
--stv-message-bg-hovervar(--stv-bg-hover)Message row background on hover
--stv-message-border-radius0Message row corner radius
--stv-message-inline-margin0Left/right inset of each message row
html
<!-- Card-style messages -->
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-message-bg: #f4f4f6;
    --stv-message-bg-hover: #ececf0;
    --stv-message-border-radius: 12px;
    --stv-message-inline-margin: 8px;
  "
></saytv-chat>

Moderator Messages

Moderator messages support the same appearance controls as regular messages, plus a customizable border. Each border side is set independently and accepts a full CSS border value (<width> <style> <color>); use the --stv-mod-border shorthand to set every side at once. Every appearance variable defaults to its --stv-message-* counterpart, so moderators inherit the base message look unless you override them here.

PropertyDefaultDescription
--stv-mod-bordernoneBorder shorthand applied to all four sides unless a side is overridden
--stv-mod-border-topvar(--stv-mod-border)Top border of moderator messages
--stv-mod-border-rightvar(--stv-mod-border)Right border of moderator messages
--stv-mod-border-bottomvar(--stv-mod-border)Bottom border of moderator messages
--stv-mod-border-leftvar(--stv-mod-border)Left border of moderator messages
--stv-mod-bgvar(--stv-message-bg)Background of moderator messages
--stv-mod-bg-hovervar(--stv-message-bg-hover)Background of moderator messages on hover
--stv-mod-border-radiusvar(--stv-message-border-radius)Corner radius of moderator messages
--stv-mod-inline-marginvar(--stv-message-inline-margin)Left/right inset of moderator messages
html
<!-- Accent bar on the left edge only -->
<saytv-chat
  app-id="your-app-id"
  style="--stv-mod-border-left: 3px solid #f8dc22;"
></saytv-chat>

<!-- Full card with a subtle tint -->
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-mod-border: 2px solid #f8dc22;
    --stv-mod-bg: rgba(248, 220, 34, 0.08);
    --stv-mod-border-radius: 12px;
    --stv-mod-inline-margin: 8px;
  "
></saytv-chat>

Examples

Brand Customization

html
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-color-primary: #7c3aed;
    --stv-color-primary-dark: #5b21b6;
    --stv-color-accent: #06b6d4;
    --stv-border-radius-md: 12px;
    --stv-border-radius-lg: 16px;
  "
></saytv-chat>

Rounded Theme

html
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-border-radius-xs: 0.5rem;
    --stv-border-radius-sm: 0.75rem;
    --stv-border-radius-md: 1rem;
    --stv-border-radius-lg: 1.5rem;
    --stv-border-radius-xl: 2rem;
    --stv-button-border-radius: 9999px;
    --stv-input-border-radius: 9999px;
  "
></saytv-chat>

Compact Spacing

html
<saytv-chat
  app-id="your-app-id"
  style="
    --stv-spacing-xs: 0.125rem;
    --stv-spacing-sm: 0.25rem;
    --stv-spacing-md: 0.5rem;
    --stv-spacing-lg: 0.75rem;
    --stv-spacing-xl: 1rem;
  "
></saytv-chat>

SayTV Chat SDK Documentation