---
title: Theme, messages, and marks
description: Restyle the flow through custom properties, replace any sentence in the message catalog, supply provider artwork, and swap the default icon set.
sidebar:
  label: Presentation
seo:
  title: Style and localise the DomainKit React flow
---

Branding stays in your app. `DomainKit.Root` takes everything the flow renders with, and the
defaults are only defaults.

## Theme

<Snippet file="examples/react/presentation.tsx" region="theme" title="A theme" />

Every value becomes a `--domainkit-*` custom property on the root element, so the stylesheet reads
your values and you can also set them from CSS.

| Key                            | Property                            |
| ------------------------------ | ----------------------------------- |
| `accent`, `accentContrast`     | `--domainkit-accent`, `-contrast`   |
| `danger`, `dangerContrast`     | `--domainkit-danger`, `-contrast`   |
| `success`                      | `--domainkit-success`               |
| `background`, `fill`, `border` | The three surfaces                  |
| `text`, `muted`                | Foreground and secondary foreground |
| `radius`, `shadow`, `backdrop` | Shape, elevation, dialog backdrop   |
| `fontFamily`                   | `--domainkit-font-family`           |

`colorScheme` is `inherit`, `light`, or `dark`. `inherit` follows whatever your page already does.

## Messages

<Snippet file="examples/react/presentation.tsx" region="messages" title="Replacing sentences" />

`Messages.Catalog` holds every user-visible string in eight groups: actions, progress, connection,
plan review, records, receipts, verification, and one function per `DomainKit.Error` reason. The
catalog is closed, so every key has a default in `Messages.english`; `messages` takes a
`Partial<Catalog>` and merges over it, and a host replaces one key without restating the rest.

Nothing renders a tag. A reason becomes a sentence through the catalog, an operation becomes a
sentence through `operation`, and a token field name becomes a label through `fieldLabel`, which
humanises `accountId` into "Account id" until a host names it properly.

The verification group phrases what a failing check found: `expectedValue(value)`,
`observedValues(values)`, and `observedNothing`. The only observer text that reaches a customer
unwrapped is the `detail` the observer itself wrote.

`notConnected` is what the connection slot says in read-only, where a connect control would
otherwise be.

## Provider marks

<Snippet file="examples/react/presentation.tsx" region="marks" title="Provider artwork" />

<ReactExample story="provider-mark" />

`marks` is keyed by provider id and takes a node or a function of the provider descriptor. Without
an entry the mark is the provider's own initial, drawn with the theme's tokens. Nothing is fetched
at render time, so a provider list costs no requests.

## Icons

`icons` overrides `defaultIcons` by slot name. `useIcons()` returns the set in context, so a part
you render yourself uses the same icons as the rest of the flow.

## Portals

`portalContainer` decides where dialogs and popovers render. Pass the element your app portals into;
DomainKit checks it belongs to the same document before using it, and falls back to the body when it
does not.
