Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

Global variables

Global variables set the colors, fonts, corner radius, shadows and spacing of the whole chat UI. Each one has a role, and many components use it. For example, --str-chat__text-primary colors message text, titles and most labels. Change it once and every component that uses it follows.

Global variables point at the palette. Component variables point at global variables, so a change here also reaches the components that build on it.

The variables fall into two groups:

  • Theme: colors, typography, corner radius and shadows.
  • Layout: spacing and sizes.

Overriding global variables

Set the light value on .str-chat and the dark value on .str-chat__theme-dark, in a CSS layer after the SDK's:

@layer stream, stream-overrides;
@import "stream-chat-react/dist/css/index.css" layer(stream);

@layer stream-overrides {
  .str-chat {
    --str-chat__accent-primary: #6d28d9;
    --str-chat__text-link: #6d28d9;
  }

  .str-chat__theme-dark {
    --str-chat__accent-primary: #a78bfa;
    --str-chat__text-link: #c4b5fd;
  }
}

Primary buttons, switches, checkboxes, mentions and the read status turn purple, and so do links. The user's own message bubbles stay blue: they use the brand scale, not the accent. To change them too, set the outgoing message variables.

Three things to know:

  • Put overrides on .str-chat. The SDK declares every variable on .str-chat, so a value set on :root or on a wrapper element never reaches the UI.
  • Put the dark rule after the light one. Both selectors have the same specificity, so the later rule wins. A value set only on .str-chat applies to both themes.
  • Override on .str-chat, not on an element inside it. A variable that points at another one gets its value on .str-chat. For example, --str-chat__chat-text-incoming points at --str-chat__text-primary. Changing --str-chat__text-primary on an element inside .str-chat doesn't change --str-chat__chat-text-incoming there.

Reading the tables

  • Light is the default value. When it points at another variable, the value that resolves to is in brackets.
  • Dark is the value inside .str-chat__theme-dark. It shows only the resolved value when the variable points at the same variable as in the light theme, and "same" when nothing changes.
  • The tables list the variables a built-in rule reads. The stylesheet declares a few more, such as --str-chat__accent-warning and --str-chat__border-utility-success, that no rule reads, so changing them has no effect.

Theme

Accent colors

Variable Light Dark Used for
--str-chat__accent-primary --str-chat__brand-500 (#005fff) --str-chat__brand-400 (#4586ff) The brand color of controls and indicators: primary buttons, selected checkboxes and switches, mentions, the read status, the played part of a waveform, poll results, upload progress
--str-chat__accent-success --str-chat__green-400 (#00a46e) --str-chat__green-300 (#00c384) Success messages under form fields; the online indicator builds on it
--str-chat__accent-error --str-chat__red-500 (#d90d10) --str-chat__red-400 (#fc526a) Errors and destructive actions: failed uploads, field errors, delete buttons
--str-chat__accent-neutral --str-chat__chrome-500 (#687385) #ababab De-emphasized indicators: the offline indicator, neutral badges, progress bars, a switch that is off

Text colors

Variable Light Dark Used for
--str-chat__text-primary --str-chat__chrome-900 (#1a1b25) #f8f8f8 Main text: message text, titles and most labels
--str-chat__text-secondary --str-chat__chrome-700 (#414552) #d8d8d8 Supporting text: subtitles, timestamps in lists, secondary labels
--str-chat__text-tertiary --str-chat__chrome-500 (#687385) #ababab Lowest-emphasis text: hints, placeholders, empty states
--str-chat__text-disabled --str-chat__chrome-300 (#a3acba) #6a6a6a Text and icons of disabled controls
--str-chat__text-link --str-chat__brand-500 (#005fff) --str-chat__brand-600 (#a5c5ff) Links and inline actions, such as the replies button and "also sent in channel"
--str-chat__text-on-accent --str-chat__chrome-0 (#ffffff) --str-chat__chrome-1000 (#ffffff) Text on an accent-colored surface; tooltips
--str-chat__text-on-inverse --str-chat__chrome-0 (#ffffff) #000000 Text on an inverse surface: notifications, the command chip

Background colors

Variable Light Dark Used for
--str-chat__background-core-app --str-chat__chrome-0 (#ffffff) #000000 The outermost background, behind the message list
--str-chat__background-core-elevation-0 --str-chat__chrome-0 (#ffffff) #000000 The base layer: text inputs and upload progress overlays
--str-chat__background-core-elevation-1 --str-chat__chrome-0 (#ffffff) --str-chat__chrome-50 (#1c1c1c) Panels: the channel list, headers, the composer, modals
--str-chat__background-core-elevation-2 --str-chat__chrome-0 (#ffffff) --str-chat__chrome-100 (#323232) Floating surfaces: menus, popovers, the reaction picker
--str-chat__background-core-elevation-3 --str-chat__chrome-0 (#ffffff) --str-chat__chrome-200 (#565656) Badges and reactions that sit above other UI
--str-chat__background-core-surface-default --str-chat__chrome-100 (#ebeef1) #323232 Grouped areas; incoming bubbles and secondary buttons build on it
--str-chat__background-core-surface-subtle --str-chat__chrome-50 (#f6f8fa) #1c1c1c Receded areas: date separators, system messages, the suggestion list
--str-chat__background-core-surface-card --str-chat__chrome-50 (#f6f8fa) --str-chat__chrome-100 (#323232) Cards: polls and switch fields
--str-chat__background-core-surface-strong --str-chat__chrome-150 (#d5dbe1) #464646 Areas that stand out, such as attachment cards in incoming bubbles
--str-chat__background-core-inverse --str-chat__chrome-1000 (#000000) #ffffff High-contrast surfaces: notifications, tooltips, the command chip
--str-chat__background-core-on-accent --str-chat__chrome-0 (#ffffff) --str-chat__chrome-1000 (#ffffff) Elements on an accent color, such as the playback thumb
--str-chat__background-core-highlight --str-chat__yellow-50 (#fef9da) --str-chat__yellow-800 (#5f1a05) Highlighted and pinned messages
--str-chat__background-core-overlay-light rgba(255, 255, 255, 0.75) rgba(0, 0, 0, 0.75) A light translucent layer: the drop zone, image placeholders
--str-chat__background-core-scrim rgba(26, 27, 37, 0.5) rgba(0, 0, 0, 0.75) The layer behind modals
--str-chat__background-utility-hover rgba(26, 27, 37, 0.1) rgba(255, 255, 255, 0.15) Hover state of interactive elements
--str-chat__background-utility-pressed rgba(26, 27, 37, 0.15) rgba(255, 255, 255, 0.2) Pressed state of interactive elements
--str-chat__background-utility-selected rgba(26, 27, 37, 0.2) rgba(255, 255, 255, 0.25) Selected state: the active channel or thread, a selected reaction
--str-chat__background-utility-disabled --str-chat__chrome-100 (#ebeef1) #323232 Disabled buttons and composer
--str-chat__skeleton-loading-base --str-chat__base-transparent-0 (rgba(255, 255, 255, 0)) same Base tone of loading placeholders
--str-chat__skeleton-loading-highlight --str-chat__background-core-overlay-light (rgba(255, 255, 255, 0.75)) rgba(0, 0, 0, 0.75) The moving shimmer of loading placeholders

Border colors

Variable Light Dark Used for
--str-chat__border-core-default --str-chat__chrome-150 (#d5dbe1) --str-chat__chrome-200 (#565656) Standard borders: panels, inputs, cards, dividers
--str-chat__border-core-subtle --str-chat__chrome-100 (#ebeef1) #323232 Lighter separators, such as between list items
--str-chat__border-core-strong --str-chat__chrome-300 (#a3acba) #6a6a6a Emphatic borders; borders inside incoming bubbles build on it
--str-chat__border-core-inverse --str-chat__chrome-0 (#ffffff) #000000 The ring around the online indicator
--str-chat__border-core-on-inverse --str-chat__chrome-0 (#ffffff) #000000 Borders on inverse surfaces, such as badges
--str-chat__border-core-opacity-strong rgba(26, 27, 37, 0.25) rgba(255, 255, 255, 0.25) Translucent borders: waveform bars, the playback thumb
--str-chat__border-utility-focused --str-chat__brand-150 (#c3d9ff) #19418d The keyboard focus ring
--str-chat__border-utility-error --str-chat__accent-error (#d90d10) #fc526a Inputs with an error
--str-chat__border-utility-disabled --str-chat__chrome-100 (#ebeef1) #323232 Disabled buttons and inputs

Focus outline

Every focusable element inside .str-chat draws this outline when the browser shows its focus, as with keyboard navigation.

Variable Light Dark Used for
--str-chat__focus-outline-color --str-chat__border-utility-focused (#c3d9ff) #19418d Color of the focus ring
--str-chat__focus-outline 2px solid var(--str-chat__focus-outline-color) same The outline drawn on a focused element
--str-chat__focus-outline-offset 2px same Gap between the element and its focus ring

Typography

Font family

The SDK doesn't load the Geist font. If your app doesn't load it either, text falls back to the system fonts in the stack.

Variable Default Used for
--str-chat__font-family var(--str-chat__typography-font-family-sans), -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, Adwaita Sans, Cantarell, Ubuntu, roboto, noto, helvetica, arial, sans-serif The font stack of every text style
--str-chat__typography-font-family-sans var(--str-chat__font-family-geist) The first font in the stack
--str-chat__font-family-geist 'Geist' The design system font

Text styles

Each text style is a font shorthand, used as font: var(--str-chat__font-body-default). It combines a weight, a size and a line height from the tables below, with --str-chat__font-family.

Variable Weight Size Line height
--str-chat__font-heading-xs --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-sm (14px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-heading-sm --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-md (16px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-heading-md --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-lg (18px) --str-chat__typography-line-height-relaxed (24px)
--str-chat__font-heading-lg --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-xl (20px) --str-chat__typography-line-height-relaxed (24px)
--str-chat__font-body-default --str-chat__typography-font-weight-regular (400) --str-chat__typography-font-size-md (16px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-body-emphasis --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-md (16px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-caption-default --str-chat__typography-font-weight-regular (400) --str-chat__typography-font-size-sm (14px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-caption-emphasis --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-sm (14px) --str-chat__typography-line-height-normal (20px)
--str-chat__font-metadata-default --str-chat__typography-font-weight-regular (400) --str-chat__typography-font-size-xs (12px) --str-chat__typography-line-height-tight (16px)
--str-chat__font-metadata-emphasis --str-chat__typography-font-weight-semi-bold (600) --str-chat__typography-font-size-xs (12px) --str-chat__typography-line-height-tight (16px)
--str-chat__font-numeric-md --str-chat__typography-font-weight-bold (700) --str-chat__typography-font-size-xxs (10px) 100%
--str-chat__font-numeric-xl --str-chat__typography-font-weight-bold (700) --str-chat__typography-font-size-sm (14px) 100%

Font sizes

Variable Default Used for
--str-chat__typography-font-size-xxs --str-chat__font-size-size-10 (10px) Smallest counts, such as badge numbers
--str-chat__typography-font-size-xs --str-chat__font-size-size-12 (12px) Metadata: timestamps, captions under attachments
--str-chat__typography-font-size-sm --str-chat__font-size-size-14 (14px) Captions and small labels
--str-chat__typography-font-size-md --str-chat__font-size-size-16 (16px) Body text
--str-chat__typography-font-size-lg --str-chat__font-size-size-18 (18px) Medium headings
--str-chat__typography-font-size-xl --str-chat__font-size-size-20 (20px) Large headings
--str-chat__typography-font-size-2xl --str-chat__font-size-size-24 (24px) Large emoji in the reaction picker and gallery

Line heights

Variable Default Used for
--str-chat__typography-line-height-tight --str-chat__line-height-line-height-16 (16px) Metadata and compact labels
--str-chat__typography-line-height-normal --str-chat__line-height-line-height-20 (20px) Body text and small headings
--str-chat__typography-line-height-relaxed --str-chat__line-height-line-height-24 (24px) Larger headings

Font weights

Variable Default Used for
--str-chat__typography-font-weight-regular 400 Regular text
--str-chat__typography-font-weight-medium 500 Medium-weight labels, such as in the gallery and number inputs
--str-chat__typography-font-weight-semi-bold 600 Headings and emphasized text
--str-chat__typography-font-weight-bold 700 Counts and numbers in badges

Corner radius

Variable Default Used for
--str-chat__radius-none --str-chat__radius-0 (0px) No rounding
--str-chat__radius-xs --str-chat__radius-4 (4px) Very small rounding
--str-chat__radius-sm --str-chat__radius-6 (6px) Small rounding
--str-chat__radius-md --str-chat__radius-8 (8px) Menus, list items, inline attachments
--str-chat__radius-lg --str-chat__radius-12 (12px) Cards and attachments
--str-chat__radius-xl --str-chat__radius-16 (16px) Modals and system messages
--str-chat__radius-2xl --str-chat__radius-20 (20px) Message bubbles
--str-chat__radius-3xl --str-chat__radius-24 (24px) The composer, notifications, the audio recorder
--str-chat__radius-4xl --str-chat__radius-32 (32px) The reaction picker
--str-chat__radius-max --str-chat__radius-full (9999px) Pill shapes and circles: avatars, badges, round buttons

Shadows

The shadows are layered box-shadow values. Each theme points them at its own elevation values.

Variable Light Dark Used for
--str-chat__box-shadow-2 --str-chat__light-elevation-2 --str-chat__dark-elevation-2 Raised elements: buttons, badges, channel list items
--str-chat__box-shadow-3 --str-chat__light-elevation-3 --str-chat__dark-elevation-3 Floating elements: menus, tooltips, the emoji and reaction pickers
Variable Value
--str-chat__light-elevation-2 0px 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 2px 4px 0px rgba(0, 0, 0, 0.12), 0px 6px 16px 0px rgba(0, 0, 0, 0.06)
--str-chat__light-elevation-3 0px 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 4px 8px 0px rgba(0, 0, 0, 0.14), 0px 12px 24px 0px rgba(0, 0, 0, 0.1)
--str-chat__dark-elevation-2 0px 0px 0px 1px rgba(255, 255, 255, 0.15), 0px 2px 4px 0px rgba(0, 0, 0, 0.22), 0px 6px 16px 0px rgba(0, 0, 0, 0.12)
--str-chat__dark-elevation-3 0px 0px 0px 1px rgba(255, 255, 255, 0.15), 0px 4px 8px 0px rgba(0, 0, 0, 0.24), 0px 12px 24px 0px rgba(0, 0, 0, 0.14)

Layout

Spacing

Variable Default Used for
--str-chat__spacing-none --str-chat__space-0 (0px) No space
--str-chat__spacing-xxxs --str-chat__space-2 (2px) Hairline gaps
--str-chat__spacing-xxs --str-chat__space-4 (4px) Minimal padding and tight gaps
--str-chat__spacing-xs --str-chat__space-8 (8px) Small padding and default gaps
--str-chat__spacing-sm --str-chat__space-12 (12px) Internal spacing in inputs and buttons
--str-chat__spacing-md --str-chat__space-16 (16px) Padding of sections, headers and the composer
--str-chat__spacing-lg --str-chat__space-20 (20px) Spacing between groups
--str-chat__spacing-xl --str-chat__space-24 (24px) Comfortable spacing in panels
--str-chat__spacing-2xl --str-chat__space-32 (32px) Large spacing in panels and modals
--str-chat__spacing-3xl --str-chat__space-40 (40px) Wide layout spacing, such as empty states

Sizes

Variable Default Used for
--str-chat__icon-size-xs --str-chat__size-12 (12px) Extra small icons
--str-chat__icon-size-sm --str-chat__size-16 (16px) Small icons
--str-chat__icon-size-md --str-chat__size-20 (20px) Medium icons
--str-chat__icon-size-lg --str-chat__size-32 (32px) Large icons, such as empty-state illustrations
--str-chat__icon-stroke-default --str-chat__w150 (1.5px) Default icon stroke width
--str-chat__icon-stroke-emphasis --str-chat__w200 (2px) Bold icon stroke width

Scale values

The spacing, radius, size and typography variables above point at these steps. The default theme uses only some of them; the rest are there for your own overrides.

Variables Values Steps for
--str-chat__size-<n> <n>px, for n = 2, 4, 6, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 128, 144, 208, 240, 320, 480, 560, 640, 760 Sizes
--str-chat__space-<n> <n>px, for n = 0, 2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80 Spacing steps
--str-chat__radius-<n> <n>px, for n = 0, 2, 4, 6, 8, 12, 16, 20, 24, 32; --str-chat__radius-full is 9999px Corner radius steps
--str-chat__font-size-size-<n> <n>px, for n = 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 28, 32, 40, 48, 64 Font sizes
--str-chat__line-height-line-height-<n> <n>px, for n = 8, 10, 12, 13, 14, 15, 16, 17, 18, 20, 24, 28, 32, 40, 48 Line heights
--str-chat__w<n> --str-chat__w100: 1px, --str-chat__w120: 1.2px, --str-chat__w150: 1.5px, --str-chat__w200: 2px, --str-chat__w300: 3px, --str-chat__w400: 4px Stroke widths

Best Practices

  • Use global variables for changes that should apply everywhere, such as the brand color or the font.
  • Keep one source of truth for colors and typography, so your tokens don't drift apart.
  • Change layout variables sparingly. Components are aligned to the spacing scale.
  • Check contrast and spacing in both the light and dark themes after a change.
  • Move to component variables only when a global change reaches too far.

The colors come from the generated light.scss and dark.scss. The text styles are in variables/fonts.scss, the shadows in variables/shadows.scss and the focus outline in base.scss.