# Keep custom controls in sync

> Render selection-aware controls and confirm what each command did.



The Bold button from the [first control guide](/editor/custom-ui/controller-setup) changes as you move the selection. It
does not inspect the document DOM. It renders command state from the Editor, runs the command, and handles the result.

## Follow one control through the loop [#follow-one-control-through-the-loop]

Choose each sample selection below. Press **Bold** when it is available. The model shows the state your control renders
and the result it handles after the command runs.

> **Interactive model: watch one control follow the selection**
>
> The sample selection is simulated. Normal text reports `enabled: true` and `active: false`. Pressing Bold changes `active` to `true` and reports `{ success: true }`. Bold text starts with `active: true`. A locked heading reports `enabled: false`, `active: false`, and a disabled reason. State describes what the control should render; the execution result confirms what the command did.


Every custom control repeats the same four steps:

1. Read the command's current state.
2. Render that state in your control.
3. Run the command from the user's action.
4. Inspect the result before reporting success or starting dependent work.

## Render the current state [#render-the-current-state]

Each command exposes a small state object:

| Field       | What your control should do                                       |
| ----------- | ----------------------------------------------------------------- |
| `enabled`   | Disable the action when it cannot run                             |
| `active`    | Show whether a toggle is applied                                  |
| `value`     | Show the current value for a picker                               |
| `reason`    | Explain why an action is disabled                                 |
| `supported` | Check whether the controller recognizes and can route the command |

Use `getState()` for the initial value and `observe()` for later changes. In React, `useSuperDocCommand(id)` does both
and rerenders the component when the state changes.

Do not derive state from the rendered document DOM. Selection, mode, history, and document content can all change
whether a command is available.

Disable a control when `enabled` is `false`. Show `reason` when it helps someone recover. Remove the control only when
the workflow does not need it.

## Confirm the command result [#confirm-the-command-result]

Use `executeAsync()` when your interface or later work depends on the action:

| Result               | Meaning                                               |
| -------------------- | ----------------------------------------------------- |
| `false`              | The controller could not route the command            |
| `true`               | The host completed the command without a receipt      |
| `{ success: true }`  | The document operation completed                      |
| `{ success: false }` | The receipt explains why the operation did not finish |

Command state is a snapshot, so check the result even when `enabled` was `true`. For receipt failure codes, see
[Receipts and errors](/document-api/receipts-and-errors).

## Choose commands deliberately [#choose-commands-deliberately]

Use `BuiltInCommandId` when a control accepts only SuperDoc commands. Use `CommandId` when it can also accept commands
registered by your application. Both types are exported from `superdoc/ui`.

`ui.commands.ids` lists the commands known to the current controller, and `ui.commands.has(id)` checks one ID. Use those
methods for discovery or capability checks. Choose the actions your workflow needs instead of generating a toolbar from
the entire list.

Next, [build a custom toolbar](/editor/custom-ui/formatting-controls) that applies this loop to Bold, font, and size. If
you do not need to own the toolbar's markup or interaction design, configure the
[built-in toolbar](/editor/built-in-ui/configure-the-toolbar) instead.
