<!-- AI agents: this is the Markdown version of a Reception documentation page. Index: /llms.txt -->

# Appearance

Customize the native Support chat with your app’s colors, typography, welcome text, and dismissal controls. All 14 `Reception.Appearance` options accept matching values from your Swift variables, including your existing app theme.

## Use your app’s theme and variables {#app-themes-and-variables}

You can assign values from your own constants, variables, or theme objects to `Reception.shared.appearance`. Use a SwiftUI `Color` for a color property, a `String` for text or a registered font name, and the matching type for other options, such as `Bool` or `Font.Design`. The individual options below list their types and defaults.

For example, place this function in your app’s appearance setup code. Here, `AppTheme` represents your own app’s theme type, with `accentColor`, `onAccentColor`, and `backgroundColor` properties of type `Color`, and a `fontDesign` property of type `Font.Design?`. Replace these names with your existing theme’s names.

```swift
import SwiftUI
import ReceptionKit

@MainActor
func applySupportTheme(_ theme: AppTheme) {
    Reception.shared.appearance.accentColor = theme.accentColor
    Reception.shared.appearance.onAccentColor = theme.onAccentColor
    Reception.shared.appearance.chatBackground = theme.backgroundColor
    Reception.shared.appearance.fontDesign = theme.fontDesign
}
```

Call `applySupportTheme(yourCurrentTheme)` on the main actor after configuring Reception and whenever your app selects or changes a theme. Each assignment takes the current value; it does not bind ReceptionKit to the original variable or observe your theme object. Reassigning local appearance values updates the chat, including while it is open, unless a published remote override takes precedence.

Adaptive asset colors such as `Color("SupportAccent")` keep their light/dark variants and respond automatically to the chat’s color scheme. A light/dark switch alone does not require reassigning those colors. If your theme changes which color, font, or custom string to use, assign the new value again. Your app also owns [localizing custom text](#localization).

To keep these values controlled by your app, leave the corresponding dashboard overrides unset, or set `Reception.shared.usesRemoteAppearance = false` on the main actor to use only local settings. Swift variable names belong in your app’s code; the dashboard accepts explicit values. See [Precedence](#precedence).

## Defaults

Without customization, Reception uses your app’s accent color, white text on accent surfaces, system backgrounds, and the system font. It follows your app’s light or dark appearance. The chat title and welcome text use built-in translations. Sheets show a native drag indicator; the optional close button starts hidden.

These settings apply to Reception’s chat, not your app’s support entry button, unread badge, or dashboard interface. The public appearance API does not expose arbitrary layouts, bubble shapes, spacing, or avatars. Your app owns its entry point and surrounding navigation; see [Entry point](/docs/entry-point).

![Native chat using default light appearance](/docs/images/ios-chat-light.webp "Default light appearance with native iOS 26 Liquid Glass controls. Example messages.")

![Native chat using default dark appearance](/docs/images/ios-chat-dark.webp "Default dark appearance with native iOS 26 Liquid Glass controls. Example messages.")

### Native controls

On iOS 26 and later, the chat title, optional close button, photo button, and message field use native Liquid Glass. Earlier iOS versions use system materials. Message bubbles keep their own background colors. There is no separate appearance option to enable glass; its rendering adapts to the system and presentation.

![Native Liquid Glass chat title and optional close button](/docs/images/ios-glass-header.webp "Header detail: title and optional close control on iOS 26.")

![Native Liquid Glass photo button and message field beneath an outgoing message](/docs/images/ios-glass-composer.webp "Composer detail: native glass controls beneath a regular message bubble.")

## Set appearance in code

`Reception.shared.appearance` is a read/write `Reception.Appearance` value. Read and change it on the main actor, normally during app setup before presenting chat. `Reception.Appearance()` constructs a fresh set of local defaults.

Place this function in your app’s setup code and call it from a main-actor context. Add a `SupportAccent` color asset with light and dark variants first.

### Example: use your app’s accent {#examples}

```swift
import SwiftUI
import ReceptionKit

@MainActor
func configureSupportAppearance() {
    Reception.shared.appearance.accentColor = Color("SupportAccent")
}
```

All short assignment examples below belong inside this main-actor setup function. Named color assets are examples of resources supplied by your app. Every option is configurable in Swift; all except `fontFamily` are also available in the [dashboard](/docs/remote-appearance).

| Option | Local default |
| --- | --- |
| [accentColor](#accentcolor) | `.accentColor` |
| [onAccentColor](#onaccentcolor) | `nil` → white |
| [chatBackground](#chatbackground) | `nil` → system background |
| [incomingBackground](#incomingbackground) | `nil` → secondary system background |
| [incomingForeground](#incomingforeground) | `nil` → primary label color |
| [preferredColorScheme](#preferredcolorscheme) | `nil` → follows app |
| [title](#title) | Localized “Support” |
| [welcomeTitle](#welcometitle) | Localized “Questions, feedback, or a bug?” |
| [welcomeText](#welcometext) | Localized “You're chatting directly with our team.” |
| [fontDesign](#fontdesign) | `nil` → default system design |
| [fontFamily](#fontfamily) | `nil` → system font |
| [showsCloseButton](#showsclosebutton) | `false` |
| [closeIcon](#closeicon) | `.xmark` |
| [fadesOlderMessages](#fadesoldermessages) | `true` |

## Precedence

For each option, a valid value in the active published remote appearance overrides your local value. Your local value otherwise applies, using the SDK default when you have left it unset. `Reception.shared.usesRemoteAppearance` defaults to `true`.

- Remote colors inherit locally for each missing or invalid light/dark variant independently.
- Remote text applies only when a valid translation matches the selected app language or the SDK’s supported language match; otherwise the local text applies.
- Explicit remote defaults are overrides: “Follow app” clears a local forced color scheme, `false` can hide a locally enabled close button, and the default font design can replace a local rounded design.
- A non-`nil` local `fontFamily` takes precedence over both local and remote `fontDesign`.

Reading `Reception.shared.appearance` returns your local settings, not the merged appearance displayed by the chat. Remote appearance never rewrites that value.

To use only local settings, put this assignment in your main-actor setup function:

```swift
Reception.shared.usesRemoteAppearance = false
```

This ignores remote settings without deleting their cache. Newly fetched remote settings take effect on the next chat opening, rather than changing the currently open chat. See [Remote appearance](/docs/remote-appearance) for publishing and offline behavior.

The comparisons below show focused details from the native chat on iOS 26, using example messages.

## Colors and color scheme

All five local color properties accept SwiftUI `Color` values from your variables, theme objects, or adaptive color assets. See [Use your app’s theme and variables](#app-themes-and-variables) for an example and how to handle theme changes. The dashboard supports separate six-digit hex colors for light and dark mode. Test both modes with real messages; light accents may need a dark `onAccentColor` to keep text readable.

### accentColor

Signature: `public var accentColor: Color`. Default: `.accentColor`, using your app’s accent. Accepts any SwiftUI `Color`, including a [theme variable](#app-themes-and-variables).

Colors outgoing text bubble fills, the enabled send button, the review action, and accented controls such as Retry. Older outgoing fills may be lightened by [fadesOlderMessages](#fadesoldermessages).

![Outgoing message with the app’s blue accent color](/docs/images/ios-appearance-detail-accent-default.webp "Blue accent")

![The same outgoing message with a purple accent color](/docs/images/ios-appearance-detail-accent-purple.webp "Purple accent")

In your main-actor setup function:

```swift
Reception.shared.appearance.accentColor = Color("SupportAccent")
```

When you change the accent, check that [onAccentColor](#onaccentcolor) stays readable on it in light and dark mode, and set it too if not.

The dashboard calls this Accent & outgoing bubbles. Assign `.accentColor` to restore the local default.

### onAccentColor

Signature: `public var onAccentColor: Color?`. Default: `nil`, which uses white. Accepts any SwiftUI `Color`, including a [theme variable](#app-themes-and-variables), or `nil`.

Colors text and symbols on accent surfaces: outgoing message text, the enabled send arrow, and review and paywall button labels and symbols. It does not automatically choose a contrasting color for your accent.

![Outgoing message with the default white text on its accent background](/docs/images/ios-appearance-detail-onaccent-default.webp "White text")

![The same outgoing message with black text on its accent background](/docs/images/ios-appearance-detail-onaccent-black.webp "Black text")

In your main-actor setup function, after adding the named asset:

```swift
Reception.shared.appearance.onAccentColor = Color("SupportOnAccent")
```

The dashboard calls this Text on accent. Assign `nil` to restore white locally.

### chatBackground

Signature: `public var chatBackground: Color?`. Default: `nil`, which uses `Color(uiColor: .systemBackground)`. Accepts any SwiftUI `Color`, including a [theme variable](#app-themes-and-variables), or `nil`.

Sets the chat’s background surface. It does not recolor photos or the full-screen photo viewer’s black background.

![Chat messages on the default white system background in light mode](/docs/images/ios-appearance-detail-background-default.webp "White background")

![The same chat messages on a blue background](/docs/images/ios-appearance-detail-background-blue.webp "Blue background")

In your main-actor setup function, after adding the named asset:

```swift
Reception.shared.appearance.chatBackground = Color("SupportBackground")
```

The dashboard calls this Chat background. Assign `nil` to restore the adaptive system background locally.

### incomingBackground

Signature: `public var incomingBackground: Color?`. Default: `nil`, which uses `Color(uiColor: .secondarySystemBackground)`. Accepts any SwiftUI `Color`, including a [theme variable](#app-themes-and-variables), or `nil`.

Sets incoming text bubble, review card, and paywall card backgrounds. Pair it with an incoming text color that remains readable in both modes.

![Incoming message with the default gray bubble background in light mode](/docs/images/ios-appearance-detail-incoming-background-default.webp "Gray bubble")

![The same incoming message with a blue bubble background](/docs/images/ios-appearance-detail-incoming-background-blue.webp "Blue bubble")

In your main-actor setup function, after adding the named asset:

```swift
Reception.shared.appearance.incomingBackground = Color("SupportIncoming")
```

The dashboard calls this Incoming bubbles. Assign `nil` to restore the adaptive secondary system background locally.

### incomingForeground

Signature: `public var incomingForeground: Color?`. Default: `nil`, which uses `.primary`. Accepts any SwiftUI `Color`, including a [theme variable](#app-themes-and-variables), or `nil`.

Sets incoming message text and the body text of review and paywall cards. Card button labels use [onAccentColor](#onaccentcolor); secondary labels keep their own colors.

![Incoming message with the default black text in light mode](/docs/images/ios-appearance-detail-incoming-foreground-default.webp "Black text")

![The same incoming message with blue text](/docs/images/ios-appearance-detail-incoming-foreground-blue.webp "Blue text")

In your main-actor setup function, after adding the named asset:

```swift
Reception.shared.appearance.incomingForeground = Color("SupportIncomingText")
```

The dashboard calls this Incoming text. Assign `nil` to restore the adaptive primary label color locally.

### preferredColorScheme

Signature: `public var preferredColorScheme: ColorScheme?`. Default: `nil`. Allowed values: `nil`, `.light`, `.dark`.

`nil` follows the app’s inherited color scheme. `.light` or `.dark` forces the chat’s appearance, including the variant selected by adaptive colors. Presented chat applies a presentation preference; embedded chat applies the scheme to its content.

![Native chat messages using the light color scheme](/docs/images/ios-appearance-detail-scheme-light.webp ".light")

![The same native chat messages using the dark color scheme](/docs/images/ios-appearance-detail-scheme-dark.webp ".dark")

In your main-actor setup function:

```swift
Reception.shared.appearance.preferredColorScheme = .dark
```

The dashboard offers Follow app, Always light, or Always dark. Assign `nil` to follow the app locally. A published Follow app value overrides a local `.light` or `.dark`; clearing the remote override instead inherits the local choice.

## Title and welcome text

### title

Signature: `@MainActor public var title: String { get set }`. Default: the localized “Support” title. Accepts any local `String`; there is no local length validation. Dashboard translations are limited to 80 characters.

Sets the chat’s navigation title. Keep it short enough to fit the navigation bar.

![Native chat header displaying the default Support title](/docs/images/ios-appearance-detail-title-default.webp "Support · default")

![The same native chat header displaying Help](/docs/images/ios-appearance-detail-title-help.webp "Help")

In your main-actor setup function, using copy from your app’s string catalog:

```swift
Reception.shared.appearance.title = String(localized: "Help")
```

A custom string is displayed as supplied; see [Localization of texts](#localization) and [Return to defaults](#return-to-defaults) before replacing built-in copy.

### welcomeTitle

Signature: `@MainActor public var welcomeTitle: String { get set }`. Default: the localized “Questions, feedback, or a bug?” headline. Accepts any local `String`; there is no local length validation. Dashboard translations are limited to 160 characters.

Sets the heading in the empty chat. It is not an introductory message inserted into conversation history.

![Empty chat with the default Questions, feedback, or a bug heading](/docs/images/ios-appearance-detail-welcome-title-default.webp "Default heading")

![Empty chat with the custom How can we help heading](/docs/images/ios-appearance-detail-welcome-title-custom.webp "Custom heading")

In your main-actor setup function, using copy from your app’s string catalog:

```swift
Reception.shared.appearance.welcomeTitle = String(localized: "How can we help?")
```

Leave it unset to retain the built-in translated heading; resetting an assigned string requires the approach in [Return to defaults](#return-to-defaults).

### welcomeText

Signature: `@MainActor public var welcomeText: String { get set }`. Default: the localized “You're chatting directly with our team.” text. Accepts any local `String`; there is no local length validation. Dashboard translations are limited to 1,000 characters.

Sets the explanatory text below the empty chat’s welcome heading. It does not set an automatic reply or alter existing messages.

![Empty chat with the default You’re chatting directly with our team supporting text](/docs/images/ios-appearance-detail-welcome-text-default.webp "Default text")

![Empty chat with the custom Tell us what you need help with supporting text](/docs/images/ios-appearance-detail-welcome-text-custom.webp "Custom text")

In your main-actor setup function, using copy from your app’s string catalog:

```swift
Reception.shared.appearance.welcomeText = String(localized: "Tell us what you need help with.")
```

Leave it unset to retain the built-in translated text; see [Return to defaults](#return-to-defaults) after assigning custom copy.

## Typography

### fontDesign

Signature: `public var fontDesign: Font.Design?`. Default: `nil`, which uses the default system design. Allowed values: `nil`, `.default`, `.rounded`, `.serif`, `.monospaced`.

Selects the system font design used by chat text, including the title, message text, composer, and status labels. System symbols and native controls retain their own rendering. A non-`nil` `fontFamily` takes precedence.

![Native chat message using the default system font design](/docs/images/ios-appearance-detail-font-default.webp ".default")

![The same native chat message using the rounded system font design](/docs/images/ios-appearance-detail-font-rounded.webp ".rounded")

![The same native chat message using the serif system font design](/docs/images/ios-appearance-detail-font-serif.webp ".serif")

![The same native chat message using the monospaced system font design](/docs/images/ios-appearance-detail-font-monospaced.webp ".monospaced")

In your main-actor setup function:

```swift
Reception.shared.appearance.fontDesign = .rounded
```

Assign `nil` to restore the local default system design. Also clear `fontFamily` if you previously selected a custom font.

### fontFamily

Signature: `public var fontFamily: String?`. Default: `nil`, which uses the system font. Accepts a custom font name string or `nil`.

ReceptionKit passes this name to SwiftUI’s `Font.custom`. When your app uses a custom font for its main UI text, reuse the exact registered font/PostScript name already working in the host’s `Font.custom` or `UIFont(name:size:)` call, preferably through its existing font constant. Despite the property name, the value is a technical font name: its display label, `.ttf`/`.otf` filename, and family name can differ. Do not derive the value from those labels.

If you need to find the name, call `UIFont.fontNames(forFamilyName:)` in the running host app to list the registered names for its existing family, then confirm your chosen name returns a non-`nil` font from `UIFont(name:size:)`. Preserve the host’s existing font registration; do not add fonts or assets just for support chat. If the host uses the system font, leave `fontFamily` as `nil`; use `fontDesign` only to match an existing system design.

Custom fonts scale with Dynamic Type. This property overrides `fontDesign`, including a design published from the dashboard.

![Native chat message using the system font with no font family override](/docs/images/ios-appearance-detail-font-family-default.webp "System font · nil")

![The same native chat message using the registered Georgia font](/docs/images/ios-appearance-detail-font-family-georgia.webp "Georgia")

In your main-actor setup function, using Georgia, which is already registered on iOS:

```swift
Reception.shared.appearance.fontFamily = "Georgia"
```

Available only in Swift; the dashboard cannot upload or select a custom font. Assign `nil` to return to the resolved system `fontDesign`. An empty string is still a non-`nil` custom font name, not a reset.

## Dismissal and message behavior

### showsCloseButton

Signature: `public var showsCloseButton: Bool`. Default: `false`. Allowed values: `true`, `false`.

When `true`, a presented chat shows a trailing close button that dismisses its presentation. The SDK-owned sheet and a host-owned SwiftUI sheet supply this presentation context. The sheet’s native drag indicator stays visible regardless of this setting. Hiding the button does not disable swipe-to-dismiss.

![Presented chat header with the close button hidden and the drag indicator visible](/docs/images/ios-appearance-detail-close-hidden.webp "false · default")

![The same presented chat header with the close button shown](/docs/images/ios-appearance-detail-close-shown.webp "true")

In your main-actor setup function:

```swift
Reception.shared.appearance.showsCloseButton = true
```

Assign `false` to restore the local default. A directly embedded chat outside a presentation does not gain a close button; your app supplies its navigation or dismissal controls. `Reception.shared.closeChat()` dismisses an SDK-owned sheet, not a host-owned `ReceptionChatView`. See [Entry point](/docs/entry-point) for presentation ownership.

### closeIcon

Signature: `public var closeIcon: Reception.CloseIcon`. Default: `.xmark`. Allowed values: `.xmark`, `.chevronDown`, `.arrowDown`. Their raw symbol names are `xmark`, `chevron.down`, and `arrow.down`.

Selects the optional chat close button’s symbol. It does not change the dismissal action, show the button by itself, or change the photo viewer’s close symbol.

![Native chat close button with an xmark symbol](/docs/images/ios-appearance-detail-icon-xmark.webp ".xmark")

![Native chat close button with a downward chevron symbol](/docs/images/ios-appearance-detail-icon-chevron.webp ".chevronDown")

![Native chat close button with a downward arrow symbol](/docs/images/ios-appearance-detail-icon-arrow.webp ".arrowDown")

In your main-actor setup function:

```swift
Reception.shared.appearance.showsCloseButton = true
Reception.shared.appearance.closeIcon = .chevronDown
```

Assign `.xmark` to restore the local default.

### fadesOlderMessages

Signature: `public var fadesOlderMessages: Bool`. Default: `true`. Allowed values: `true`, `false`.

Lightens older outgoing text bubble fills toward white. The newest outgoing text bubble keeps the accent color. Text, photos, and incoming bubbles are unaffected. **Increase Contrast** disables fading. Sending-state dimming is separate.

![Outgoing messages with progressively lighter fills for older messages](/docs/images/ios-appearance-detail-fade-enabled.webp "true · default")

![The same outgoing messages with uniform accent fills at every age](/docs/images/ios-appearance-detail-fade-disabled.webp "false")

In your main-actor setup function:

```swift
Reception.shared.appearance.fadesOlderMessages = false
```

`false` keeps outgoing fills at the accent color; assign `true` to restore local age-based fading.

## Localization of texts {#localization}

Leave the three text properties unset to retain built-in translations. An assigned `String` is a local override, even when its contents equal the English default. ReceptionKit does not translate that string for you. Resolve custom strings through your app’s string catalog and reassign them when your app’s own language selection changes.

See [Language](/docs/language) for every supported language code, `Reception.shared.languageOverride`, and matching rules. See [Remote appearance](/docs/remote-appearance) for dashboard translation selection, limits, and fallbacks.

## Dashboard appearance {#remote-appearance}

Publish colors, text, typography, and behavior from the dashboard without shipping a new app build. The [Remote appearance guide](/docs/remote-appearance) explains the editor, draft and published states, language-specific text, caching, and when changes become visible. Custom font files and `fontFamily` remain host-app resources.

## Return to defaults

Optional color properties, `preferredColorScheme`, `fontDesign`, and `fontFamily` reset locally with `nil`. Restore nonoptional properties using their defaults listed above.

Assigning an empty string or the displayed default doesn't restore automatic translation. For example, `Reception.shared.appearance.title = Reception.Appearance().title` copies the current translated text into a fixed override; it does not restore future automatic language changes.

To restore automatic localized defaults, construct a fresh `Reception.Appearance` and reapply only the customization you want to keep. Put this in your main-actor setup function to keep an accent while restoring all other local defaults:

```swift
var appearance = Reception.Appearance()
appearance.accentColor = Color("SupportAccent")
Reception.shared.appearance = appearance
```

For a complete local reset, use this assignment in the same main-actor context:

```swift
Reception.shared.appearance = Reception.Appearance()
```

These assignments do not disable remote appearance or clear published settings. In the dashboard, removing an override restores inheritance from the app’s local value. Restore defaults clears the editor’s draft; publish the reset to deliver it. It does not reset your Swift configuration. See [Remote appearance](/docs/remote-appearance).

## Verify your customization

Open both an empty chat and a chat containing incoming and outgoing messages. Check light and dark mode, larger Dynamic Type sizes, **Increase Contrast**, your supported languages, and your actual sheet or embedded presentation.

If an option appears ineffective, check whether a published remote override applies. For fonts, clear `fontFamily` before checking `fontDesign`. For close controls, confirm that the chat is presented and `showsCloseButton` resolves to `true`. For welcome text, inspect an empty chat. After publishing dashboard changes, allow the refresh to complete and reopen chat; the dashboard preview cannot reproduce your app’s local overrides or bundled fonts.
