
Rich text editor with efficient long-form rendering, custom spans, per-edit events, exposed scroll state, spell‑checking and built-in find/replace for advanced text editing.
Compose has been missing a Rich Text Editor since its inception. I've taken a crack at this previously, as have others.
However, they have all suffered from fundamental limitations in BasicTextField, the foundation of
all text entry in Compose.
This project is an attempt to re-implement text entry from scratch to finally have a solution to the various problems.
I've been trying to implement a spell checking text
field in Compose, and keep running up against
the limitations of BasicTextField. Pretty much out of options, I decided to see what it might take
to replace BasicTextField with something that solved all of my needs.
And now, it's working, and at this point, working pretty well.
<u>), highlight (==text== or <mark>), colour and size (<span style>)# , - , **bold**)You can Give it a try here, or browse the API reference & recipes.
Green is supported and yellow is not supported yet. Grey is not planned:
CommonMark: 532 of the spec's 652 examples
Not planned: raw HTML (71), blocks inside list items or block quotes (26), list items holding more than one paragraph (10), blank lines kept as empty lines (10), and images inside text or links (3).
GitHub Flavored Markdown extensions: 12 of 24 examples
| Platform | Status |
|---|---|
| Desktop (JVM) | Supported |
| Android | Supported |
| iOS | Beta: typing, autocorrect, CJK composition, the edit menu, loupe and touch handles |
| WASM | Beta: typing, IME composition, the rich clipboard and drag and drop |
Text Editor:
implementation("com.darkrockstudios:composetexteditor:3.2.0")
Markdown addon, to use the editor as a markdown editor (state.withMarkdown()):
implementation("com.darkrockstudios:composetexteditor-markdown:3.2.0")
Spell Checking addon:
implementation("com.darkrockstudios:composetexteditor-spellcheck:3.2.0")
Find & Replace addon:
implementation("com.darkrockstudios:composetexteditor-find:3.2.0")
Or take the BOM and leave the versions off the modules, so they always match:
implementation(platform("com.darkrockstudios:composetexteditor-bom:3.2.0")
implementation("com.darkrockstudios:composetexteditor")
implementation("com.darkrockstudios:composetexteditor-markdown")
implementation("com.darkrockstudios:composetexteditor-spellcheck")
implementation("com.darkrockstudios:composetexteditor-find")Upgrading from 2.x (markdown as its own module, decoration layers, shortcuts matched on the keyboard layout): see docs/MIGRATION.md. How the editor is built is in docs/ARCHITECTURE.md, and how it is tested in docs/TESTING.md.
On iOS, host the Compose view with .ignoresSafeArea(.keyboard) in SwiftUI, as the
Compose Multiplatform template does. The editor keeps its caret above the keyboard itself;
letting SwiftUI shrink the view as well moves the content twice.
On Android, declare android:windowSoftInputMode="adjustResize" on the activity, as
Compose apps should; otherwise Android also pans the whole window to the caret. The
editor keeps its caret in view whether the host pads it by the keyboard's inset
(imePadding) or lets the keyboard cover it. TextEditorState.keyboardSettings asks the
keyboard for its capitalisation, autocorrect, layout and action key; an editor for code
would turn capitals and autocorrect off. Android, iOS and the web honour it; the web
ignores autocorrect.
I don't know. Maybe. It might not be a permanent solution.
BasicTextField2's new state based approach and gap-buffer has reached maturity and includes a lot of what I would need
to replace this, but still cannot handle rich text rendering.
So until that is solved, this is the only solution that I am aware of that ticks every box.
Compose has been missing a Rich Text Editor since its inception. I've taken a crack at this previously, as have others.
However, they have all suffered from fundamental limitations in BasicTextField, the foundation of
all text entry in Compose.
This project is an attempt to re-implement text entry from scratch to finally have a solution to the various problems.
I've been trying to implement a spell checking text
field in Compose, and keep running up against
the limitations of BasicTextField. Pretty much out of options, I decided to see what it might take
to replace BasicTextField with something that solved all of my needs.
And now, it's working, and at this point, working pretty well.
<u>), highlight (==text== or <mark>), colour and size (<span style>)# , - , **bold**)You can Give it a try here, or browse the API reference & recipes.
Green is supported and yellow is not supported yet. Grey is not planned:
CommonMark: 532 of the spec's 652 examples
Not planned: raw HTML (71), blocks inside list items or block quotes (26), list items holding more than one paragraph (10), blank lines kept as empty lines (10), and images inside text or links (3).
GitHub Flavored Markdown extensions: 12 of 24 examples
| Platform | Status |
|---|---|
| Desktop (JVM) | Supported |
| Android | Supported |
| iOS | Beta: typing, autocorrect, CJK composition, the edit menu, loupe and touch handles |
| WASM | Beta: typing, IME composition, the rich clipboard and drag and drop |
Text Editor:
implementation("com.darkrockstudios:composetexteditor:3.2.0")
Markdown addon, to use the editor as a markdown editor (state.withMarkdown()):
implementation("com.darkrockstudios:composetexteditor-markdown:3.2.0")
Spell Checking addon:
implementation("com.darkrockstudios:composetexteditor-spellcheck:3.2.0")
Find & Replace addon:
implementation("com.darkrockstudios:composetexteditor-find:3.2.0")
Or take the BOM and leave the versions off the modules, so they always match:
implementation(platform("com.darkrockstudios:composetexteditor-bom:3.2.0")
implementation("com.darkrockstudios:composetexteditor")
implementation("com.darkrockstudios:composetexteditor-markdown")
implementation("com.darkrockstudios:composetexteditor-spellcheck")
implementation("com.darkrockstudios:composetexteditor-find")Upgrading from 2.x (markdown as its own module, decoration layers, shortcuts matched on the keyboard layout): see docs/MIGRATION.md. How the editor is built is in docs/ARCHITECTURE.md, and how it is tested in docs/TESTING.md.
On iOS, host the Compose view with .ignoresSafeArea(.keyboard) in SwiftUI, as the
Compose Multiplatform template does. The editor keeps its caret above the keyboard itself;
letting SwiftUI shrink the view as well moves the content twice.
On Android, declare android:windowSoftInputMode="adjustResize" on the activity, as
Compose apps should; otherwise Android also pans the whole window to the caret. The
editor keeps its caret in view whether the host pads it by the keyboard's inset
(imePadding) or lets the keyboard cover it. TextEditorState.keyboardSettings asks the
keyboard for its capitalisation, autocorrect, layout and action key; an editor for code
would turn capitals and autocorrect off. Android, iOS and the web honour it; the web
ignores autocorrect.
I don't know. Maybe. It might not be a permanent solution.
BasicTextField2's new state based approach and gap-buffer has reached maturity and includes a lot of what I would need
to replace this, but still cannot handle rich text rendering.
So until that is solved, this is the only solution that I am aware of that ticks every box.