# Theming

Customizing Widgets Using `StreamTheme`

### Background

Stream's UI SDK makes it easy for developers to add custom styles and attributes to widgets. Starting with the design-refresh release, Stream uses `StreamTheme` — a Flutter `ThemeExtension` — instead of a dedicated wrapper widget.

`StreamTheme` is passed via `MaterialApp.theme.extensions` (or `MaterialApp.darkTheme.extensions`) and is resolved from `Theme.of(context)` anywhere in the widget tree.

### Setting Up StreamTheme

Add `StreamTheme` as a theme extension to your `MaterialApp`:

```dart
MaterialApp(
  theme: ThemeData(
    extensions: [
      StreamTheme.light(), // or StreamTheme.dark() for dark mode
    ],
  ),
  home: StreamChat(
    client: client,
    child: const MyHomePage(),
  ),
)
```

If no `StreamTheme` is provided, a default theme is automatically created based on `Theme.of(context).brightness` (light or dark mode).

### Customizing StreamTheme

Use the `StreamTheme` constructor (or `StreamTheme.light()` / `StreamTheme.dark()` factories) with `copyWith` to customize only the properties you need:

```dart
MaterialApp(
  theme: ThemeData(
    extensions: [
      StreamTheme(
        brightness: Brightness.light,
        colorScheme: StreamColorScheme.light().copyWith(
          primary: Colors.indigo,
          secondary: Colors.indigoAccent,
        ),
        avatarTheme: const StreamAvatarThemeData(
          // Customize avatar defaults...
        ),
      ),
    ],
  ),
  home: ...,
)
```

### Reading the Theme in Widgets

Access the current `StreamTheme` anywhere in the widget tree:

```dart
final streamTheme = StreamTheme.of(context);
final colorScheme = streamTheme.colorScheme;
final avatarTheme = streamTheme.avatarTheme;
```

### Two-Layer Theme Architecture

Stream Chat uses two complementary theme layers:

- **`StreamTheme`** (design-system tokens) — shared across all Stream products. Controls color scheme, typography, avatar sizing, badges, reaction picker appearance, and other low-level primitives. Provided as a `ThemeExtension` on `MaterialApp.theme`.
- **`StreamChatThemeData`** (chat-specific themes) — controls styling for chat components like message bubbles, channel list items, message input, polls, and galleries. Passed to `StreamChat.streamChatThemeData`.

Both are optional — sensible defaults are applied automatically.

### Per-Component Theme Objects

Each component has its own theme data class. Depending on which layer it belongs to, you configure it differently:

**Design-system themes (via `StreamTheme`):**

| Component       | Theme Class                        |
| --------------- | ---------------------------------- |
| Message items   | `StreamMessageItemThemeData`       |
| Reaction picker | `StreamReactionPickerThemeData`    |
| Avatars         | `StreamAvatarThemeData`            |
| Badges          | `StreamBadgeNotificationThemeData` |

**Chat-specific themes (via `StreamChatThemeData`):**

| Component          | Theme Class                                                   |
| ------------------ | ------------------------------------------------------------- |
| Channel list items | `StreamChannelListItemThemeData`                              |
| Own messages       | `StreamMessageThemeData`                                      |
| Other messages     | `StreamMessageThemeData`                                      |
| Message input      | `StreamMessageInputThemeData`                                 |
| Channel header     | `StreamChannelHeaderThemeData`                                |
| Polls              | `StreamPollCreatorThemeData`, `StreamPollInteractorThemeData` |
| Thread list        | `StreamThreadListTileThemeData`                               |
| Drafts list        | `StreamDraftListTileThemeData`                                |
| Voice recording    | `StreamVoiceRecordingAttachmentThemeData`                     |

Example — customizing channel list items globally:

```dart
MaterialApp(
  theme: ThemeData(
    extensions: [
      StreamTheme.light(),
    ],
  ),
  home: StreamChat(
    client: client,
    streamChatThemeData: StreamChatThemeData(
      channelListItemTheme: StreamChannelListItemThemeData(
        titleStyle: const TextStyle(fontWeight: FontWeight.bold),
        subtitleStyle: const TextStyle(color: Colors.grey),
        timestampStyle: const TextStyle(fontSize: 12),
      ),
    ),
    child: const MyHomePage(),
  ),
)
```

### Subtree Theme Overrides

You can override the theme for a subtree using the `StreamChannelListItemTheme`, `StreamMessageItemTheme`, or other inherited widgets:

```dart
StreamChannelListItemTheme(
  data: StreamChannelListItemThemeData(
    titleStyle: const TextStyle(color: Colors.blue),
  ),
  child: StreamChannelListView(controller: controller),
)
```

### Light and Dark Mode

Pass different `StreamTheme` instances to `MaterialApp.theme` and `MaterialApp.darkTheme` to support both modes:

```dart
MaterialApp(
  theme: ThemeData(
    extensions: [StreamTheme.light()],
  ),
  darkTheme: ThemeData(
    brightness: Brightness.dark,
    extensions: [StreamTheme.dark()],
  ),
  themeMode: ThemeMode.system,
  home: ...,
)
```

### Migration from StreamChatTheme Widget

In previous versions, theming used a `StreamChatTheme` wrapper widget:

```dart
// Old approach (v9 and earlier)
StreamChatTheme(
  data: StreamChatThemeData(...),
  child: MaterialApp(...),
)
```

In v10 with the design refresh, `StreamTheme` is passed as a theme extension:

```dart
// New approach
MaterialApp(
  theme: ThemeData(
    extensions: [StreamTheme.light()],
  ),
  home: StreamChat(client: client, child: ...),
)
```

The `StreamChatThemeData` class still exists for configuring Stream-Chat-specific component themes (passed to `StreamChat`). `StreamTheme` handles the design-system visual tokens (colors, typography, avatar sizes, etc.).

### Global Configuration

For global configuration options, use `StreamChatConfigurationData` passed to `StreamChat.streamChatConfigData`. This controls behavioral and structural settings that are independent of theming:

```dart
StreamChat(
  client: client,
  streamChatConfigData: StreamChatConfigurationData(
    reactionIconResolver: const MyReactionIconResolver(),
    enforceUniqueReactions: true,
    draftMessagesEnabled: true,
    imageCDN: const StreamImageCDN(),
    attachmentBuilders: [MyCustomAttachmentBuilder(), ...defaultAttachmentBuilders],
  ),
  child: ...,
)
```

| Property                  | Description                                                                                 |
| ------------------------- | ------------------------------------------------------------------------------------------- |
| `reactionIconResolver`    | Maps reaction types to emoji/widgets. Defaults to `DefaultReactionIconResolver`             |
| `enforceUniqueReactions`  | Whether a new reaction replaces the existing one. Defaults to `true`                        |
| `draftMessagesEnabled`    | Enables draft message support. Defaults to `false`                                          |
| `imageCDN`                | Image CDN for generating resized URLs and cache keys. Defaults to `StreamImageCDN`          |
| `attachmentBuilders`      | Custom attachment renderers prepended to the defaults                                       |
| `reactionType`            | Visual style of reactions display (`StreamReactionsType.segmented` by default)              |
| `reactionPosition`        | Where reactions appear relative to the bubble (`StreamReactionsPosition.header` by default) |
| `messagePreviewFormatter` | Formatter for message previews in channel lists                                             |
| `defaultUserImage`        | Widget shown when a user has no avatar image                                                |
| `placeholderUserImage`    | Widget shown while a user's avatar is loading                                               |


---

This page was last updated at 2026-04-23T18:43:03.405Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/flutter/v10/stream_chat_flutter/stream_chat_and_theming/](https://getstream.io/chat/docs/sdk/flutter/v10/stream_chat_flutter/stream_chat_and_theming/).