Themes and Styling¶
Kodemirror replaces CSS-based theming with Kotlin data classes and Compose styling primitives.
Editor theme¶
The EditorTheme data class controls the editor's visual appearance — background, foreground, cursor, gutter, selection colors, and the text style. Here is the demo's Tokyo Night-inspired custom theme:
private val customTheme = EditorTheme(
background = Color(0xFF1A1B26),
foreground = Color(0xFFA9B1D6),
cursor = Color(0xFFC0CAF5),
selection = Color(0xFF364A82),
activeLineBackground = Color(0xFF1E2030),
gutterBackground = Color(0xFF1A1B26),
gutterForeground = Color(0xFF3B4261)
)
Apply it as an extension:
val session = rememberEditorSession(
doc = SampleDocs.javascript,
extensions = basicSetup + javascript().extension +
editorTheme.of(customTheme)
)
Built-in themes¶
Two themes are provided out of the box:
defaultEditorTheme— dark theme (One Dark-inspired)lightEditorTheme— light theme
The :theme-one-dark module provides a complete oneDark extension that bundles both the editor theme and syntax highlighting colors.
Syntax highlighting¶
Syntax highlighting colors are separate from the editor theme. They are defined with HighlightStyle, which maps syntax tags to SpanStyle values:
import com.monkopedia.kodemirror.language.*
import com.monkopedia.kodemirror.lezer.highlight.Tags
import androidx.compose.ui.text.SpanStyle
val myHighlighting = HighlightStyle.define(listOf(
TagStyleSpec(Tags.keyword, SpanStyle(color = Color(0xFFCBA6F7))),
TagStyleSpec(Tags.string, SpanStyle(color = Color(0xFFA6E3A1))),
TagStyleSpec(Tags.comment, SpanStyle(color = Color(0xFF6C7086))),
TagStyleSpec(Tags.number, SpanStyle(color = Color(0xFFFAB387))),
TagStyleSpec(Tags.variableName, SpanStyle(color = Color(0xFFCDD6F4))),
TagStyleSpec(Tags.typeName, SpanStyle(color = Color(0xFFF9E2AF))),
TagStyleSpec(Tags.function(Tags.variableName), SpanStyle(color = Color(0xFF89B4FA)))
))
Apply it with:
Combining theme and highlighting¶
A complete theme extension bundles both:
This is the same pattern the oneDark extension uses.
Accessing the theme in composables¶
The theme is distributed via CompositionLocal, so panels, tooltips, and widgets can read it:
@Composable
fun MyPanel() {
val theme = LocalEditorTheme.current
Text("Panel", color = theme.foreground)
}
Comparison with upstream CodeMirror¶
| Upstream (CSS) | Kodemirror (Compose) |
|---|---|
EditorSession.theme({...}) with CSS selectors | editorTheme.of(EditorTheme(...)) |
HighlightStyle.define([{tag, color}]) | HighlightStyle.define(listOf(TagStyleSpec(...))) |
| CSS class names | SpanStyle values |
--cm-editor-background | EditorTheme.background: Color |
| Applied via DOM class swap | Applied via Compose recomposition |
Related API¶
EditorTheme— editor theme data classHighlightStyle— tag-to-style mappingTagStyleSpec— tag style specificationTags— standard syntax tag definitions
Based on the CodeMirror Styling example.