Customizing Your Stream Chat Web App With Our New Theming API

...

Customizing your chat UI is essential to the integration process because it converts a generic chat screen to one that conforms with your app’s identity. Our new web (React and Angular) theming API makes this process more straightforward.

Follow this coding tutorial to learn about the new Stream Chat theming API and understand how to customize your Stream chat web app with CSS.

Customizing Your Chat Application

Creating a chat UI that seamlessly integrates with the rest of your application's design can elevate your user experience. An extensive theming system that allows you to inject your brand’s appearance into the chat UI and lets you do small UI tweaks can significantly speed up this process.

New Theming API

We’ve rebuilt our theming API focusing on customization. That meant creating a well-designed CSS variable system that lets you customize the chat UI without writing custom CSS code, but we also restructured all of the components, so if you have to write custom code, it’s easier.

Apart from the improved customization, the new version also comes with a refreshed design (light and dark themes) and right-to-left layout support.

Chat UI - light theme

Chat UI - light theme

Chat UI - dark theme

Chat UI - dark theme

Chat UI - right-to-left layout

Chat UI - right-to-left layout

The new API is available from stream-chat-angular version 4 and stream-chat-react version 10.

Setup

To follow along with the coding examples, start with our Angular tutorial or React tutorial but don’t create any custom components.

Coding

In this tutorial, we will start with an out-of-the-box chat UI that comes standard with our React and Angular SDK. We will then customize it by writing only CSS code. Note that the tutorial will use SCSS, but you can follow along using CSS as well.

This is what we start with:

Channel list and message list components - before

Channel list and message list components - before

Message component - before

Message component - before

And this is the end result:

Channel list and message list component - after

Channel list and message list component - after

Message component - after

Message component - after

Global Variables

Every app and brand has certain styles and colors that help customers easily identify and associate the product with the company. These styles usually include colors, fonts, shapes, etc., and would be rather difficult to hardcode for every single element.

Global variables come in here and allow us to define a single style that can be reused by components throughout the app.

Global variables are CSS variables that can be grouped into the following categories:

  • Colors
  • Typography
  • Spacing and sizing (these variables allow you to change the whitespace inside chat UI)
  • Border radiuses

The full list of these variables can be found on the Angular global variables page and React global variables page inside the SDK documentation.

In this part of the tutorial, we’ll use global variables to change the application's color palette and typography.

Colors

Using the color global variables will make creating our custom color palette for the chat UI really straightforward. This tutorial will use the Radix UI color system to find harmonious color combinations. You can use your own colors, but if you’re using Radix UI make sure to install it:

npm install @radix-ui/colors

or

yarn add @radix-ui/colors

Import the selected color combination into your stylesheet:

@import "~@radix-ui/colors/sage.css";
@import "~@radix-ui/colors/mint.css";

Once that’s done, we can override the default theme colors using the .str-chat selector:

.str-chat {
  // Neutral colors for backgrounds, borders, texts
  --str-chat__background-color: var(--sage1);
  --str-chat__secondary-background-color: var(--sage2);
  --str-chat__surface-color: var(--sage5);
  --str-chat__secondary-surface-color: var(--sage4);
  --str-chat__tertiary-surface-color: var(--sage3);
  --str-chat__text-color: var(--sage12);
  --str-chat__text-low-emphasis-color: var(--sage11);
  --str-chat__disabled-color: var(--sage8);
  --str-chat__on-primary-color: var(--sage12);

  // Vibrant colors to emphasize UI elements
  --str-chat__primary-color: var(--mint7);
  --str-chat__primary-color-low-emphasis: var(--mint5);
  --str-chat__active-primary-color: var(--mint10);
  --str-chat__primary-surface-color: var(--mint4);
  --str-chat__primary-surface-color-low-emphasis: var(--mint2);
}

The documentation contains a description for each variable and lists the components that use it, so it’s easier to find the variables we want to override.

For example, the --str-chat__primary-color variable sets the color of the avatar component and links inside messages (among others). You can see that these components have been updated. It’s also possible to set the colors of these components separately, as we’ll see in the component variables section later.

Let’s see the result:

Color scheme - before

Color scheme - before

Color scheme - after

Color scheme - after

Typography

In this step, we’ll customize the font of the chat UI.

For this example, we’ll use Roboto font. Here is the import for that:

@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap");

Next, set the --str-chat__font-family CSS variable to change the font throughout the chat UI:

--str-chat__font-family: "Roboto", sans-serif;

If you want to customize the typography further, there are CSS variables for all the different typography configurations (font family, size, and weight) used by the chat components.

Component Variables

Global variables are a great way to inject your brand design and customize the overall appearance of the chat UI. However, sometimes, we want to have more fine-grained control over parts of the chat application - that’s when component variables can help.

In this part of the tutorial, we’ll customize the avatar, channel preview, and message input components.

Avatar Customization

Let’s update the shape and colors of the avatar component:

--str-chat__avatar-border-radius: 20%;
--str-chat__avatar-background-color: var(--mint11);
--str-chat__avatar-color: var(--sage2);
Avatar - before

Avatar - before

Avatar - after

Avatar - after

The full list of these variables can be found on the Angular component variables page and React component variables page inside the SDK documentation.

In general, components have the following variables:

  • Background color
  • Text color
  • Border and border radius
  • Box shadow

Channel Preview customization

Let’s see another example and customize the borders of the channel preview component:

--str-chat__channel-preview-border-block-end: 1px solid var(--sage5);
Channel preview - before (left), channel preview - after (right)

Channel preview - before (left), channel preview - after (right)

Message Input Customization

Next, we’ll customize the message input component:

--str-chat__message-textarea-border-block-start: none;
--str-chat__message-textarea-border-block-end: none;
--str-chat__message-textarea-border-inline-start: none;
--str-chat__message-textarea-border-inline-end: none;
--str-chat__message-input-border-block-start: 1px solid var(--sage5);
--str-chat__message-input-background-color: var(--sage2);
Message input - before

Message input - before

Message input - after

Message input - after

Message Component - A Complex Example

Global and component variables are the easiest way to customize the chat components' typography, colors, borders, and shadows. However, more complex UI changes still require custom CSS code.

In this next section, we’ll customize the message component.

Writing Custom CSS Code - Message Layout

CSS cascade layers can make overriding CSS rules defined by the SDK significantly easier.

Let’s create a layer called defaults for the rules defined by the SDK.

Import for Angular:

@layer defaults {
  @import '~stream-chat-angular/src/assets/styles/v2/scss/index.scss';
}

Import for React (paste this import inside your root stylesheet, and remove any other stream-chat-react CSS import you might have):

@layer defaults {
  @import '~stream-chat-react/dist/scss/v2/index.scss';
}

We can add another layer, overrides, for our custom CSS code:

@layer overrides {
  // Custom CSS code
}

Since the overrides layer was defined later, it’ll automatically have a higher priority and overrides the rules inside the defaults layer regardless of selector specificity.

Now that we set up cascade layers, let’s list the changes necessary to implement the desired design:

Message component - currently

Message component - currently

Message component - desired design

Message component - desired design

  • Message is full-width
  • The message bubble is removed
  • The sender avatar is displayed at the top of the message
  • Message reactions moved to the bottom of the message text
  • GIFs and links have a border
  • Message reactions have different colors

Additionally, messages sent by the current user have these changes:

  • The message is aligned to the left
  • The sender avatar is displayed

At first, we’ll create the layout changes related to all messages:

@layer overrides {
  // Custom message layout
  .str-chat__message {
    // Display the avatar at the top of the message
    .str-chat__message-sender-avatar {
      align-self: flex-start;
    }

    .str-chat__message-inner {
      // Display reactions under the message
      grid-template-areas:
        "message-bubble options"
        "reactions reactions";

      // Make message bubble full width
      .str-chat__message-bubble {
        max-width: 100%;
        align-self: center;
        min-height: var(--str-chat__message-options-button-size);
        display: flex;
        align-items: center;

        // Padding added for the border displayed for links and GIFs
                // Quoted message padding for indentation
        .str-chat__message-attachment--card,
        .str-chat__quoted-message-preview {
          padding-inline-start: 0.5rem;
        }
      }
    }

    .str-chat__message-text,
    .str-chat__quoted-message-bubble {
      padding: 0;
    }
  }
}

Next, we’ll move on to the changes related to the messages sent by the current user:

@layer overrides {
  .str-chat__message.str-chat__message--me {
    // Align message to left
    grid-template-areas:
      "avatar message"
      ". replies"
      ". metadata";
    justify-items: start;
    grid-template-columns: auto 1fr;
    column-gap: 0.5rem;

    // Flip message options
    .str-chat__message-options {
      flex-direction: row-reverse;
    }

    // Don't hide the chat user's avatar
    .str-chat__message-sender-avatar {
      display: block;
    }

    // Align reactions selector to left
    .str-chat__message-reactions-container {
      justify-content: flex-start;
    }

    // Align message reactions to left
    .str-chat__message-reaction-selector {
      inset-inline-end: unset;
      inset-inline-start: 0;
    }

    // Align system messages center
    &.str-chat__message--system {
      grid-template-columns: 1fr;
    }
  }

  // Flip margins
  .str-chat__li:hover {
    .str-chat__message--me .str-chat__message-inner {
      margin-inline-end: 0;
    }
  }

  .str-chat__message--me .str-chat__message-inner {
    margin-inline-start: 0;
    margin-inline-end: calc(var(--str-chat__message-options-button-size) * 3);
  }
}

Component variables

Not all changes require custom code. Let’s adjust the theming of the message.

Remove the message bubble:

.str-chat {
    --str-chat__message-bubble-background-color: transparent;
  --str-chat__own-message-bubble-background-color: transparent;
  --str-chat__quoted-message-bubble-background-color: transparent;
  --str-chat__deleted-message-background-color: transparent;
}

Add the border to links and GIFs:

--str-chat__card-attachment-border-inline-start: 3px solid var(--sage4);

Message reactions color:

--str-chat__message-reaction-background-color: var(--sage4);
--str-chat__own-message-reaction-background-color: var(--mint5);

With these changes, we’ve completed the customization of the chat UI:

Message component - end result

Message component - end result

Chat UI - end result

Chat UI - end result

Interactive Playground

You can easily experiment with the new theming capabilities with our interactive examples. Below is the React example, and you can find the Angular version here.

Where To Go From Here?

If you want to know more about the new theming API, check out these cool features as well:

  • How to use and customize the dark and light themes for Anuglar and React.
  • How to create your own themes with the Angular and React SDKs.
  • For advanced customization, it’s possible to only use the layout rules from the SDK and apply your own look-and-feel. You can read more about this topic in our Angular and React advanced customization guides.

If you have an existing chat project, you can follow the Angular theme installation guide or React theme installation guide for more information.

If you’re interested in Stream chat, you can activate your free 30-day trial or check out our maker account.