I'm trying to integrate the RoosterJS rich text editor into a Shadow DOM component, but it doesn’t seem to work correctly. The editor initializes, but formatting features like bold, italic, and bullet lists don’t apply as expected.
My Setup: I have created a simple rich text editor using RoosterJS inside a Shadow DOM as shown below:
import { Editor, toggleBold, toggleBullet, toggleItalic } from "roosterjs";
let editor: Editor | null = null;
function initializeEditor() {
const container = document.getElementById('app')!;
const shadowRoot = container.attachShadow({ mode: 'open' });
const wrapper = document.createElement('div');
wrapper.style.width = '100%';
wrapper.style.height = '100%';
const buttonBar = document.createElement('div');
const boldButton = createButton('Bold', () => editor && toggleBold(editor));
const italicButton = createButton('Italic', () => editor && toggleItalic(editor));
const bulletButton = createButton('Bullet', () => editor && toggleBullet(editor));
buttonBar.appendChild(boldButton);
buttonBar.appendChild(italicButton);
buttonBar.appendChild(bulletButton);
const editorDiv = document.createElement('div');
editorDiv.id = 'editor';
editorDiv.style.border = '1px solid black';
editorDiv.style.height = '200px';
editorDiv.style.width = '100%';
editorDiv.contentEditable = 'true';
wrapper.appendChild(buttonBar);
wrapper.appendChild(editorDiv);
shadowRoot.appendChild(wrapper);
// Initialize RoosterJS
editor = new Editor(editorDiv);
}
function createButton(text: string, onClick: () => void): HTMLButtonElement {
const button = document.createElement('button');
button.textContent = text;
button.addEventListener('click', onClick);
return button;
}
document.addEventListener('DOMContentLoaded', initializeEditor);
The Issue: The editor initializes within the Shadow DOM, but formatting functions like toggleBold, toggleItalic, and toggleBullet do not work when buttons are clicked. It seems like RoosterJS is unable to apply formatting to the content inside the Shadow DOM, potentially due to isolation constraints.
What I’ve Tried: Referencing the editor container using shadowRoot.querySelector('#editor') instead of document.getElementById. Ensuring that all necessary styles and scripts are accessible within the Shadow DOM. Searching through the documentation and other resources for Shadow DOM compatibility but haven’t found a solution.
Has anyone successfully integrated RoosterJS within a Shadow DOM component? If so, what adjustments or configurations are needed to make it work? Any help or alternative approaches would be greatly appreciated!
According to this issue: https://github.com/microsoft/roosterjs/issues/722
RoosterJS does not work inside of shadowRoots yet. Apparantly originally a Safari issue was blocking this funcionality but it has since been resolved. Yet the RoosterJS issue still exists.
According to this: https://github.com/codex-team/editor.js/issues/2274#issuecomment-1455197600
Microsoft got it to work inside a shadowRoot but whatever they did has not been merged into RoosterJS
In this issue: https://github.com/microsoft/fast/issues/5658
TipTap has been recommended as an alternative. I don't know about TipTap but maybe you want to have a look at that one.