I also wholeheartedly recommend ProseMirror. It’s a bit complicated in some ways, but it works across platforms, is used in production widely at big companies despite sort of flying under the radar, and has been stable for years. If you’re looking for a fully baked React integration, TipTap[0] seems really nice, or if something minimalist then a plug for my own integration: use-prosemirror[1].
At work we need only the most basic customization (some inline spans for template vars) and we've cobbled together a Draft.JS implementation that's pretty buggy and has random runtime errors (unhandled nulls internal to the Draft.JS code).
Draft.js was another far out experience for me. I built the first attempt at my app with it, only to discover that Draft.js didn't work on Android. It was buggy on iOS, but on Android just didn't work. If you've been using Draft.js you probably remember Android support landing with the huge PR from Fabio M. Costa at GoDaddy[0], but by then I had already decided I needed to find something else. That PR actually led me to ProseMirror:
> This approach is the one used by Prosemirror (see https://github.com/ProseMirror/prosemirror-view/blob/master/...), which is the only Rich Text Editor I've tried that works well on Android. [1]
When I looked at ProseMirror, I was spooked by the apparent complexity. Tried Quill, Trix (worked great, but uncustomizable) and then went with Slate, only to have the above-mentioned experience. Remembered that comment on the PR, and redid my editor in ProseMirror, which finally was something that worked. Thank you Marijn and the ProseMirror community. It's been a journey with these editors.
[0] https://github.com/facebook/draft-js/pull/2035
[1] https://github.com/facebook/draft-js/pull/2035#issue-2613622...
After few weeks of development we ran into IE11 issues we couldn't fix and Slate devs expressed that they are not at all interested in supporting IE11 in any way, which is a fair point of course since IE11 is on its way out and supporting it is a big chore. There were some PRs that were supposed to address some of the issues, but development is kinda all over the place on Slate so we weren't confident enough to go with it and decided to switch to ProseMirror.
It hasn't been easy and ProseMirror can be complicated, but we managed to work it out and created what we needed.
I started using this library several years ago and have eventually had to rework it using prosemirror because I just couldn't keep up with the breaking changes.
Both libraries work in very similar ways, with slate using React for its rendering layer. However Prosemirror has been v1 for quite a while and in retrospect I'd have saved myself a lot of headaches if I'd taken the above warning more seriously.