Skip to content

feat(ios): nested lists - #814

Open
hejsztynx wants to merge 17 commits into
@ksienkiewicz/feat-nested-listsfrom
@ksienkiewicz/feat-nested-lists-ios
Open

hejsztynx wants to merge 17 commits into
@ksienkiewicz/feat-nested-listsfrom
@ksienkiewicz/feat-nested-lists-ios

Conversation

@hejsztynx

@hejsztynx hejsztynx commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Implementation of the nested list feature. Updated API looks as follows:

  • ref.indentList() - moves the list element deeper into the nesting
  • ref.outdentList() - flattens the list element inside the nesting
  • updated the onChangeState payload of orderedList, unorderedList and checkboxList with a new depth field:
{
    isActive: boolean;
    isConflicting: boolean;
    isBlocking: boolean;
    depth: number;
}

Added relevant indent/outdent buttons in the toolbar, inside the example app.

The Android and Web implementations are stubbed for now, marked with // TODO comments.

This PR does not target docs, mobile e2e tests or the HTML normalizer shared across mobile platforms.

Test Plan

Play around with both new ref methods, experiment with different selection ranges, mixing list styles. You can also check the generated HTML and its parsing during a round-trip or pushing the text into an EnrichedText component. Try deleting portions of the nested list - the structure should stay valid.

Screenshots / Videos

Short demo

Screen.Recording.2026-10-12.at.14.20.02.mov

Compatibility

OS Implemented
iOS ✅
Android ❌
Web ❌

Checklist

  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

Copilot AI balanced review requested due to automatic review settings October 12, 2026 12:33
@hejsztynx
hejsztynx marked this pull request as draft October 12, 2026 12:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cross-platform codegen compatibility and several list selection, state, logging, and HTML parsing issues remain unresolved.

4 open findings
What changed in this PR

Adds iOS nested-list editing, rendering, HTML round-tripping, and list-depth state reporting.

Changes:

  • Adds list indentation/outdentation commands and depth state.
  • Introduces nested-list integrity, styling, drawing, and parsing logic.
  • Adds example toolbar controls.
File Description
src/​web/​tiptapWatchers/​useOnChangeState.ts Adds placeholder list depths.
src/​web/​EnrichedTextInput.tsx Adds placeholder nesting commands.
src/​types.ts Extends public list APIs and state.
src/​spec/​EnrichedTextInputNativeComponent.ts Extends native events and commands.
src/​native/​EnrichedTextInput.tsx Exposes native nesting commands.
ios/​utils/​TextListsUtils.mm Adds list-chain utilities.
ios/​utils/​TextListsUtils.h Declares list-chain utilities.
ios/​utils/​StyleUtils.mm Updates conflict handling.
ios/​utils/​StyleUtils.h Declares conflict detection.
ios/​utils/​ParagraphAttributesUtils.mm Preserves nested typing attributes.
ios/​utils/​ListIntegrityUtils.mm Validates nested-list structure.
ios/​utils/​ListIntegrityUtils.h Declares list validation.
ios/​utils/​CheckboxHitTestUtils.mm Accounts for ancestor indentation.
ios/​textHtmlParser/​TextHtmlParser.mm Parses nested list metadata.
ios/​styles/​UnorderedListStyle.mm Applies cumulative indentation.
ios/​styles/​OrderedListStyle.mm Applies cumulative indentation.
ios/​styles/​ListStyleBase.mm Implements shared nesting behavior.
ios/​styles/​CheckboxListStyle.mm Supports nested checkbox lists.
ios/​interfaces/​StyleHeaders.h Introduces shared list interfaces.
ios/​interfaces/​StyleBase.mm Adds list-aware style hooks.
ios/​interfaces/​StyleBase.h Declares list-aware style hooks.
ios/​inputHtmlParser/​InputHtmlParser.mm Imports nested lists into inputs.
ios/​htmlParser/​HtmlParser.mm Adds nested-list HTML round-tripping.
ios/​extensions/​LayoutManagerExtension.mm Draws nested markers and numbering.
ios/​EnrichedTextInputView.mm Integrates commands, validation, and depth events.
apps/​example/​src/​constants/​editorConfig.ts Adds default list depths.
apps/​example/​src/​components/​Toolbar.tsx Adds indent/outdent controls.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ios/htmlParser/HtmlParser.mm
Comment thread src/spec/EnrichedTextInputNativeComponent.ts
Comment thread ios/EnrichedTextInputView.mm Outdated
Comment thread src/types.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Mixed-style selections can lose list levels, gain unintended nesting, or make the new commands no-op.

1 open finding
4 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Detect list styles across mixed-style selections

ios/​EnrichedTextInputView.mm:1611

detect: only succeeds when the entire selected range has one leaf list style. A selection containing, for example, both unordered and ordered items therefore returns nullptr, making both new nesting commands silently do nothing. Select a ListStyleBase when any list style is present; the modifier already reads each paragraph's own marker format.

Medium severity Remove list entries only from paragraphs with matching leaf styles

ios/​styles/​ListStyleBase.mm:139

remove: strips the deepest list entry from every paragraph in actualRange, even when this style is not that paragraph's leaf style. Conflict handling invokes this method over the whole selection for each list type found anywhere, so a mixed ordered/checkbox selection can remove unrelated list levels multiple times. Check styleCondition: for each subRange before removing its leaf entry.

🧠 Review effort: Balanced

Comment thread ios/EnrichedTextInputView.mm
@hejsztynx
hejsztynx changed the base branch from main to @ksienkiewicz/feat-nested-lists October 13, 2026 11:33
@hejsztynx
hejsztynx requested a review from szydlovsky October 13, 2026 11:35
@hejsztynx
hejsztynx marked this pull request as ready for review October 13, 2026 11:35

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants