Ordered and Unordered Lists¶
Table of Contents¶
- Basic Usage
- List Nesting and Levels
- List Style Types
- Ordered Lists
- Unordered Lists
- Per-List Style Types
- List Indentation
- List Prefix Alignment
- List Marker Style
- Common Operations
- Default Values
- Keyboard Shortcuts
- Typing Shortcuts
- List Behavior
- Visual Examples
Basic Usage¶
You can add ordered and unordered lists using RichTextState:
// Toggle ordered list.
richTextState.toggleOrderedList()
// Toggle unordered list.
richTextState.toggleUnorderedList()
You can get if the current selection is an ordered or unordered list, using RichTextState:
// Get if the current selection is an ordered list.
val isOrderedList = richTextState.isOrderedList
// Get if the current selection is an unordered list.
val isUnorderedList = richTextState.isUnorderedList
List Nesting and Levels¶
You can increase or decrease the nesting level of lists using RichTextState:
// Increase list level (nesting)
richTextState.increaseListLevel()
// Decrease list level (un-nesting)
richTextState.decreaseListLevel()
// Check if list level can be increased/decreased
val canIncrease = richTextState.canIncreaseListLevel
val canDecrease = richTextState.canDecreaseListLevel
List Style Types¶
Ordered Lists¶
You can customize the style of ordered lists using different formats:
// Set ordered list style type
richTextState.config.orderedListStyleType = OrderedListStyleType.Decimal // 1, 2, 3, ...
richTextState.config.orderedListStyleType = OrderedListStyleType.LowerAlpha // a, b, c, ...
richTextState.config.orderedListStyleType = OrderedListStyleType.UpperAlpha // A, B, C, ...
richTextState.config.orderedListStyleType = OrderedListStyleType.LowerRoman // i, ii, iii, ...
richTextState.config.orderedListStyleType = OrderedListStyleType.UpperRoman // I, II, III, ...
// Use different styles for different nesting levels
richTextState.config.orderedListStyleType = OrderedListStyleType.Multiple(
OrderedListStyleType.UpperAlpha, // First level: A, B, C
OrderedListStyleType.LowerAlpha, // Second level: a, b, c
OrderedListStyleType.Decimal // Third level: 1, 2, 3
)
Unordered Lists¶
You can customize the style of unordered lists using different bullet types:
// Set unordered list style type
richTextState.config.unorderedListStyleType = UnorderedListStyleType.Disc // •
richTextState.config.unorderedListStyleType = UnorderedListStyleType.Circle // ◦
richTextState.config.unorderedListStyleType = UnorderedListStyleType.Square // ▪
// Use custom markers for different nesting levels
richTextState.config.unorderedListStyleType = UnorderedListStyleType.from(
"•", // First level
"◦", // Second level
"▪" // Third level
)
Per-List Style Types¶
Note: This API is marked
@ExperimentalRichTextApiand may change in a future release.
The config style types above are editor-wide presentation: every list follows them and they are not saved with the content. A single list can also carry a style type of its own, the way an <ol> or <ul> carries a list-style-type in HTML. Set it on the lists at the selection:
// The whole ordered list at the cursor becomes a, b, c, ...
richTextState.setOrderedListStyleType(OrderedListStyleType.LowerAlpha)
// The whole unordered list at the cursor uses square bullets
richTextState.setUnorderedListStyleType(UnorderedListStyleType.Square)
// Back to the config style
richTextState.setOrderedListStyleType(null)
The style applies to every item of the list each selected item belongs to: the items at its nesting level, up to the previous and next paragraph that is not a list item, is nested less deeply, or is a list of the other kind. A nested list is a list of its own and keeps or sets its style independently. New items created with Enter, with the typing shortcuts, or by toggling a paragraph right below the list inherit its style. Changing the config afterwards does not affect a list with a style type of its own. Each call is one undo step.
For a toolbar, read the style type of the list at the selection. It is null when the selection is not in a list of that kind, when the list follows the config, or when the selected items carry different style types:
val orderedStyle: OrderedListStyleType? = richTextState.currentOrderedListStyleType
val unorderedStyle: UnorderedListStyleType? = richTextState.currentUnorderedListStyleType
A per-list style type is part of the content: toHtml() writes it as style="list-style-type: ..." on the <ol> or <ul>, setHtml() reads it from the list tag or from an <li>, and the document model and JSON carry it too. Only the predefined types have a CSS keyword and round trip:
| Style type | CSS keyword |
|---|---|
OrderedListStyleType.Decimal | decimal |
OrderedListStyleType.LowerAlpha | lower-alpha (also read from lower-latin) |
OrderedListStyleType.UpperAlpha | upper-alpha (also read from upper-latin) |
OrderedListStyleType.LowerRoman | lower-roman |
OrderedListStyleType.UpperRoman | upper-roman |
OrderedListStyleType.ArabicIndic | arabic-indic |
OrderedListStyleType.Arabic | arabic-abjad |
UnorderedListStyleType.Disc | disc |
UnorderedListStyleType.Circle | circle |
UnorderedListStyleType.Square | square |
A custom style type (an own OrderedListStyleType implementation, an OrderedListStyleType.Multiple, or UnorderedListStyleType.from(...) with other prefixes) renders in the editor but is not written to HTML, the document or JSON. An unknown keyword in HTML leaves the list following the config. Markdown has no list style types.
List Indentation¶
You can control the list indentation using RichTextState:
// Change list indentation (ordered and unordered).
richTextState.config.listIndent = 20
// Change only ordered list indentation.
richTextState.config.orderedListIndent = 20
// Change only unordered list indentation.
richTextState.config.unorderedListIndent = 20
List Prefix Alignment¶
Note: This API is marked
@ExperimentalRichTextApiand may change in a future release.
You can control where the list marker (1., 10., •, ...) sits relative to the indent "gutter" using ListPrefixAlignment:
// Default: HTML-style - the marker sits inside the gutter and ends at the content
// start, so "1." and "10." have their dots aligned vertically.
richTextState.config.listPrefixAlignment = ListPrefixAlignment.End
// Alternative: every item's marker starts at the same left edge, giving a uniform
// left edge even when item widths differ (e.g. "1." vs "10.").
richTextState.config.listPrefixAlignment = ListPrefixAlignment.Start
| Alignment | Layout | Example |
|---|---|---|
End (default) | marker right-aligned to content start, dots align vertically | 1. / 10. / 11. - dots stacked |
Start | marker left-aligned to the indent origin, marker left edges stack | 1. / 10. / 11. - numbers stacked |
If the configured indent is smaller than the marker width (for example orderedListIndent = 0), End clamps the first-line indent at 0 so the marker stays visible. Clamping (rather than switching formulas per item) keeps the whole list on a single layout so paragraphs with different marker widths stay visually consistent.
List Marker Style¶
Note: This API is marked
@ExperimentalRichTextApiand may change in a future release.
You can control how list markers (•, 1., etc.) inherit styles from the list item's text using ListMarkerStyleBehavior:
// Default: marker inherits typography from the item's text but drops decorations.
richTextState.config.listMarkerStyleBehavior = ListMarkerStyleBehavior.InheritFromText
// Alternative: every marker renders with the default span style regardless of content.
richTextState.config.listMarkerStyleBehavior = ListMarkerStyleBehavior.AlwaysDefault
With InheritFromText (the default), markers match the paragraph's typography so they stay visually aligned with the text. This matches Google Docs behavior:
| Attribute | Applied to marker |
|---|---|
color | yes |
fontSize | yes |
fontWeight (bold) | yes |
fontStyle (italic) | yes |
fontFamily | yes |
letterSpacing | yes |
textDecoration (underline, strikethrough) | no |
background (highlight) | no |
baselineShift (super/subscript) | no |
shadow | no |
textGeometricTransform | no |
Use AlwaysDefault when you want bullets that look identical no matter how the line is formatted (for example, editors that style markers entirely through a separate theme).
Common Operations¶
Styling the markers directly¶
To style the bullets and numbers on their own, set listMarkerStyle. It is applied on top of the marker style behavior above, so anything it leaves unset still follows that behavior:
@OptIn(ExperimentalRichTextApi::class)
richTextState.config.listMarkerStyle = SpanStyle(color = Color.Red)
// Bold, colored numbers and bullets
richTextState.config.listMarkerStyle = SpanStyle(color = Color.Gray, fontWeight = FontWeight.Bold)
It is an appearance setting of the editor, like the link and code span colors: it applies to every list in the editor and is not saved in the document, so toHtml() and toMarkdown() do not include it. Reset it with SpanStyle().
Default Values¶
By default, the Rich Text Editor uses these configurations: - Ordered List Style: OrderedListStyleType.Multiple with: - First level: Decimal (1, 2, 3, ...) - Second level: LowerRoman (i, ii, iii, ...) - Third level: LowerAlpha (a, b, c, ...) - Unordered List Style: UnorderedListStyleType.from with: - First level: • (bullet) - Second level: ◦ (circle) - Third level: ▪ (square) - List Indentation: 38 - List Prefix Alignment: ListPrefixAlignment.End (HTML-style, dots aligned) - List Marker Style: ListMarkerStyleBehavior.InheritFromText - Exit List on Empty Item: true (configurable via richTextState.config.exitListOnEmptyItem) - List Typing Shortcuts: true (configurable via richTextState.config.listTypingShortcutsEnabled)
Keyboard Shortcuts¶
The editor supports common keyboard shortcuts for list operations: - Tab: Increase list level (indent) - Shift + Tab: Decrease list level (outdent) - Enter on an empty list item: Exit the list - Backspace at the start of a list item: Decrease list level or exit list
Typing Shortcuts¶
Typing a list marker at the start of a paragraph turns it into a list: - - or *: unordered list - A number followed by . (for example 1. or 57.): ordered list starting at that number
To keep lists but turn these shortcuts off, so the typed characters stay as text:
The list functions (toggleOrderedList, toggleUnorderedList and the others) and lists in loaded or pasted content keep working. To remove lists from the editor altogether, leave them out of the feature set instead (see Editor features).
List Behavior¶
When working with lists: 1. Creating a new list item: - Press Enter at the end of a list item to create a new one - The new item inherits the same level and style as the previous one
- Exiting a list:
- Press
Enteron an empty list item (configurable viaexitListOnEmptyItem) - Press
Backspaceat the start of an empty list item:- When list level > 1: Decreases the list level by 1
- When list level = 1: Exits the list
Note: The behavior of pressing
Enteron an empty list item can be configured usingrichTextState.config.exitListOnEmptyItem. When set totrue(default), it exits the list. When set tofalse, it creates a new list item.
- Converting between list types:
- You can convert between ordered and unordered lists by toggling the respective type
- The list level and content are preserved during conversion
Visual Examples¶
Note: The following examples are representations of how lists might appear. The actual appearance in your application may vary based on your configuration settings (style type, indentation, etc.).
Ordered List Example¶
1. First level item
a. Second level item
i. Third level item
b. Another second level
2. Back to first level
Unordered List Example¶
• First level item
◦ Second level item
▪ Third level item
◦ Another second level
• Back to first level
Related Documentation¶
- For HTML list import/export, see HTML Import and Export
- For Markdown list import/export, see Markdown Import and Export