---
title: "UI customization set UI configuration | Nutrient Web SDK"
canonical_url: "https://www.nutrient.io/guides/web/user-interface/ui-customization/set-ui/"
md_url: "https://www.nutrient.io/guides/web/user-interface/ui-customization/set-ui.md"
last_updated: "2026-05-15T19:10:05.104Z"
description: "Learn to update Nutrient Web SDK UI customization after load using setUI, replacing slots, nested components, and layouts dynamically."
---

# Set UI customization configuration

When configuring user interface (UI) customization, provide the settings in the `ui` option when you load the SDK:

```tsx

NutrientViewer.load({
  //... Your configuration.
  ui: {
    // Initial configuration for UI customization.
  },
});

```

You may also want to update the UI customization configuration after the SDK has been loaded. Use the [`setUI`](https://www.nutrient.io/api/web/classes/NutrientViewer.Instance.html#setui) method on `instance` to do so.

## Updating the UI configuration

With `setUI`, you can update any of the slots in your UI customization configuration. This also applies to nested slots.

Consider the following example where you’re customizing the `commentThread` slot:

```tsx

NutrientViewer.load({
  //... Your configuration.
  ui: {
    commentThread: (getInstance, id) => ({
      render: (params) => {
        // Return a DOM node.
        const div = document.createElement("div");
        div.style.backgroundColor = "lightblue";
        div.style.padding = "10px";
        div.style.border = "1px solid #ccc";

        div.style.borderRadius = "5px";
        div.innerText = `This is a custom UI for the comment thread: ${id}`;

        return div;
      },
    }),
  },
});

```

Later, if you want to update the `commentThread` slot to change its content, you can do so with `instance.setUI`:

```tsx

instance.setUI({
  commentThread: (getInstance, id) => ({
    render: (params) => {
      // Return a DOM node.
      const div = document.createElement("div");
      div.style.backgroundColor = "lightblue";
      div.style.padding = "10px";
      div.style.border = "1px solid #ccc";

      div.style.borderRadius = "5px";
      div.innerText = `Updated content for comment thread.`;

      return div;
    },
  }),
});

```

### Updating nested slots

Nested slots can be updated the same way.

Note that you need to provide the full configuration object to `setUI`. The provided object replaces the entire configuration passed in the `ui` option during SDK load.

Consider the following example where you’re customizing the `header` slot within the `commentThread` slot:

```tsx

NutrientViewer.load({
  //... Your configuration.
  ui: {
    commentThread: {
      header: () => {
        return {
          render: () => {
            const div = document.createElement("div");
            div.style.backgroundColor = "lightgreen";
            div.style.padding = "5px";
            div.innerText = "This is a custom header for the comment thread.";

            return div;
          },
        };
      },
    },
  },
});

```

Later, if you want to remove the `header` customization and add `footer` customization at the same time, you can do so with `instance.setUI`:

```tsx

instance.setUI({
  commentThread: {
    footer: () => {
      return {
        render: () => {
          const div = document.createElement("div");
          div.style.backgroundColor = "lightcoral";
          div.style.padding = "5px";
          div.innerText = "This is a custom footer for the comment thread.";

          return div;
        },
      };
    },
  },
});

```

## Partially updating the UI configuration

The configuration object you pass to `setUI` completely replaces the previous configuration. But you may want to update only specific slots while leaving the rest of the UI intact.

To do this, store your UI configuration in a variable before passing it to the `ui` property in `load`. When passing an updated configuration to `setUI`, build a new object by merging your previous configuration with the new changes. Keeping references to unchanged slots intact tells the SDK not to update them.

Pass a new object to `setUI` instead of mutating the previous configuration object so that the SDK can reliably detect changes.

Suppose you’ve customized the `header` and `footer` slots within the `commentThread` slot:

```tsx

// Instead of directly passing the object to the `ui` property, store it in a variable first.
const uiConfig = {
  commentThread: {
    header: () => {
      return {
        render: () => {
          const div = document.createElement("div");
          div.style.backgroundColor = "lightgreen";
          div.style.padding = "5px";
          div.innerText = "This is a custom header for the comment thread.";

          return div;
        },
      };
    },
    footer: () => {
      return {
        render: () => {
          const div = document.createElement("div");
          div.style.backgroundColor = "lightcoral";
          div.style.padding = "5px";
          div.innerText = "This is a custom footer for the comment thread.";

          return div;
        },
      };
    },
  },
};

NutrientViewer.load({
  //... Your configuration.
  ui: uiConfig,
});

```

To update the `footer` slot within `commentThread` while keeping the `header` slot intact, merge your previous configuration with the new changes:

```tsx

instance.setUI({
  // Spread the previous configuration to keep unchanged slots intact....uiConfig,
  commentThread: {
    // Spread the previous `commentThread` configuration to keep unchanged slots, such as header, intact....uiConfig.commentThread,
    footer: () => {
      return {
        render: () => {
          const div = document.createElement("div");
          div.style.backgroundColor = "lightcoral";
          div.style.padding = "5px";
          div.innerText = "Updated content for the custom footer.";

          return div;
        },
      };
    },
  },
});

```

## Grouped slots

Grouped slots follow the same pattern. Pass the full nested structure to `setUI` — the new configuration completely replaces the previous one:

```tsx

// Hide annotation actions and replace the delete confirmation at runtime.
instance.setUI({
  annotations: {
    actions: (getInstance, id) => ({ render: () => null }),
    deleteConfirm: (getInstance, id) => ({
      render: () => {
        const div = document.createElement("div");
        div.textContent = "Are you sure you want to delete?";
        const btn = document.createElement("button");
        btn.textContent = "Confirm";
        btn.onclick = async () => {
          const instance = getInstance();
          if (!instance) return;
          const selected = instance.getSelectedAnnotations();
          if (selected?.size) await instance.delete(selected.first().id);
        };
        div.appendChild(btn);
        return div;
      },
    }),
  },
});

```

## Presets at runtime

You can apply or remove a preset at runtime:

```tsx

// Switch to minimal (canvas-only) mode:
instance.setUI({ preset: 'minimal' });

// Minimal mode with only search visible:
instance.setUI({
  preset: 'minimal',
  search: (getInstance, id) => ({
    render: () => {
      const div = document.createElement("div");
      div.textContent = "Custom search";
      return div;
    },
  }),
});

// Reset to full default UI:
instance.setUI({});

```
---

## Related pages

- [Building a comment thread UI with the customization API](/guides/web/user-interface/ui-customization/comment-thread-example.md)
- [Custom sidebars](/guides/web/user-interface/ui-customization/custom-sidebars.md)
- [Building headless document UIs](/guides/web/user-interface/ui-customization/headless-ui.md)
- [Slot customization examples](/guides/web/user-interface/ui-customization/examples.md)
- [Customizing the Nutrient Web SDK UI](/guides/web/user-interface/ui-customization/introduction.md)
- [Supported slots for UI customization](/guides/web/user-interface/ui-customization/supported-slots.md)

