Skip to main content
Version: 5.9.0

Design system

The SDK uses a design system built around the ChatTheme class to configure its user interface.

The SDK supports a light and a dark theme — they are set through the theme and darkTheme properties on the ChatCenterUISDK instance. If darkTheme is not set explicitly, values from theme are used in dark mode.

Assigning theme resets darkTheme — assign darkTheme after theme.

Design system in Figma

A visual representation of the design system is available as a UIKit in Figma.

The file contains the following pages:

  • Foundation — colors, typography, icons (light and dark themes)
  • Message Type — all message types in the context of a chat
  • Components — Navigation, Status, Button, Bubbles, Input Field, OS UI, Content, Illustration
  • User Flow — 40+ screens covering the full user scenario
Where to start

Start with the Quickstart — a ready-to-use example you can copy and adapt.

The terms "token", "component", and "flow" are described in the Glossary.

Quick example

// Create a theme with custom colors
let colors = ChatColors()
colors.main = .black
colors.link = .systemBlue

let theme = ChatTheme(colors: colors)

// Apply
chatCenterSDK.theme = theme
// chatCenterSDK.darkTheme = darkTheme // optional, if a separate dark theme is set

ChatTheme can be created in two ways:

// From base tokens (colors, fonts, images) — any argument can be omitted
ChatTheme(colors: myColors, typography: myTypography)

// From configured components (for more detailed customization)
ChatTheme(components: myComponents)

What and when to customize

How to choose a customization level?

The design system has three customization levels. Pick the one that fits:

TaskLevelWhat to change
Change the brand color across the SDKTokenChatColors
Change fonts across the SDKTokenChatTypography
Replace iconsTokenChatImages
Configure a button, panel, or widget across the SDKComponentChatComponents
Configure an element only on the chat screenFlowChatFlow
Configure an element only on the search screenFlowSearchFlow

All parameters are optional — defaults are used when nothing is set.

Architecture

ChatTheme contains ChatComponents (shared styles reused across all SDK screens) and ChatFlows (per-screen overrides). Components rely on three sets of tokens: ChatColors, ChatTypography, ChatImages.

The full list of ChatComponents fields is in Components. Fine-grained customization through chatFlow / searchFlow is in Flows.

Application priority

ChatFlows (per-screen) > ChatComponents (global) > ChatColors / ChatTypography / ChatImages (default tokens).

The apply method and the Applicable protocol

All design system objects (ChatTheme, ChatColors, ChatTypography, ChatImages, ChatComponents, styles, and flows) support the apply(_ configure:) method through the Applicable protocol.

theme.flows.chatFlow.apply {
$0.incomeMessages.showAvatar = true
$0.outcomeMessages.showAvatar = false
$0.inputViewStyle.sendButtonStyle.tintColor = .white
}

The apply method returns Self, which lets you configure a freshly created object in a single expression:

let theme = ChatTheme().apply { $0.flows.chatFlow.incomeMessages.bubbleTintColor = .red }

To create a style with a custom configuration, use the build factory method.

The ChatStyle base class

All styles in the SDK inherit from the ChatStyle base class. It implements the Applicable protocol and provides the static build(with:configure:) method for creating subclasses.

Base class properties:

PropertyTypeDescription
backgroundColorUIColorElement background color
tintColorUIColorElement color (button, icon, etc.)
cornerRadiusCGFloatCorner radius (where applicable)
componentsChatComponentsReference to the core components for the style

Each subclass (for example, ChatInputTextStyle, NavigationBarStyle, QuickReplyStyle) inherits these properties and adds its own specific parameters. ChatStyle is not instantiated directly — use a concrete subclass through its constructor with components or through the static build method:

let customStyle = ChatInputTextStyle.build(with: components) { style in
style.backgroundColor = .white
style.cursorColor = .systemBlue
}

Advanced configuration

For fine-grained customization of individual elements, use styles through flows. For example, you can change a button color only on a specific screen without affecting the rest.

Performance recommendations

  • Create ChatTheme once — at SDK initialization (in AppDelegate / SceneDelegate), not before every chat opening or in a loop
  • SF Symbols for button icons — they scale without losing quality and are lighter than raster images. Raster PNG/PDF is better for complex custom illustrations
  • For adaptive colors, a single UIColor(dynamicProvider:) is preferable to two ChatColors objects with theme/darkTheme — if only colors differ
  • Do not reuse a single ChatComponents across different ChatTheme instances when using ChatTheme(components:) — both themes will reference the same object, and changes in one will affect the other (more in the Quickstart)
  • iPad and large screens: the SDK adapts to iPad automatically. With fixed font sizes, verify readability — on a large screen the size may need to be increased
  • Dynamic Type: if your app supports Dynamic Type, pass scalable fonts through UIFontMetrics:
    let baseFont = UIFont.systemFont(ofSize: 15, weight: .regular)
    typography.message = UIFontMetrics.default.scaledFont(for: baseFont)

Quick lookup: where to go

I want to...FileClass / property
Apply the brand colorColorsChatColors.link
Replace the font in bubblesTypographyChatTypography.message
Replace the send iconImagesChatImages.sendButtonImage
Configure the navigation barComponentsChatComponents.navigationBarStyle
Hide the avatar on outgoing messagesFlowschatFlow.outcomeMessages.showAvatar
Change the highlight color in searchFlowssearchFlow.searchMessageStyle.matchTextStyle.color
Configure the audio playerComponentsChatComponents.audioPlayerStyle
Set a dark themeQuickstartchatCenterSDK.darkTheme
Find all style classesStyles
Something doesn't workTroubleshooting
Change the send button color (everywhere)Componentscomponents.inputViewStyle.sendButtonStyle.tintColor
Change the send button color (chat only)FlowschatFlow.inputViewStyle.sendButtonStyle.tintColor
Configure the empty chat screenComponentscomponents.chatPlaceholderStyle