Should you want to add content to the widget (or indeed any of our UI components), since we use a Shadow DOM to ensure encapsulation of styling, you should first access the shadowRoot property of the host element - from there you can access the elements and manipulate them or append new ones.

For example, if you want to target the Dynamic Widget, you’d look for an element with data-testid="dynamic-modal-shadow":

   const shadowHosts = document.querySelectorAll(
        '[data-testid="dynamic-modal-shadow"]'
    );

From there you’ll need to pick the element that is the shadowRoot:

  shadowHosts.forEach((shadowHost) => {
    if (shadowHost && shadowHost.shadowRoot) {
      // Logic here
    }
  })

As a best practice, you can encapsulate your manipulation logic in a function, then call that function immediately but also add it to a mutation observer.

The observer is important for multiple reasons:

  1. The widget content may change dynamically (e.g., different views or states).
  2. The widget might be destroyed and recreated in the DOM.
  3. Your custom content might be overwritten by internal widget updates.
    const injectButton = () => {
      // Logic to inject a new button into the widget
    }

    injectButton();

    const observer = new MutationObserver((mutations) => {
      injectButton();
    });

    observer.observe(shadowHost.shadowRoot, {
      childList: true,
      subtree: true,
    });

Now you have access to the modal, you can target whatever element you want to adjust, or append new elements at will.