[SuperEditor] Add toggleable headers (Resolves #2276) #2404
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[SuperEditor] Add toggleable headers. Resolves #2276
This PR adds the ability to group nodes together under header nodes or list item nodes, where each group can be collapsed/expanded by tapping on a button near it.
The groups are created upon initialization, when adding or removing a node, and when changing a node that couldn’t start a group to a node that can start a group. For example, typing "# " at the beginning of a paragraph converts it to a header node and creates a new group.
Navigating using the arrow keys skips nodes inside a collapsed group. For example, pressing ARROW DOWN skips nodes that are inside a collapsed group.
The user cannot start or end a selection inside a collapsed group. Also, if the selection starts or ends within a group and the user collapses the group, the selection is adjusted to avoid starting or ending inside the collapsed group.
Node grouping is customizable and apps can implement their own grouping logic, if desirable.
Implementation
A
GroupBuilder
interface was added with the methods required to grouping nodes:canStartGroup
: to signal the document layout that the current node can start a group, for example, when it is a level one header.canAddToGroup
: to signal the document layout that a node can be added to an existing group.build
: to create the widget for this group.SuperEditor
will take a list ofGroupBuilder
s as a constructor parameter.Previously, all components were organized into a vertical list of components inside the
SingleColumnDocumentLayout
. Now, whenever aGroupBuilder
returnstrue
forcanStartGroup
, the document layout will callcanAddToGroup
to each node below it, untilcanAddToGroup
returnsfalse
. After gathering all nodes that are part of the group,SingleColumnDocumentLayout
callsbuild
on theGroupBuilder
to create a widget subtree for that group.To handle the key navigation, at the current state of this PR, it was added an
isComponentVisible
method to theDocumentLayout
interface, so the layout can report that a component is not currently visible. This is yet subject to change, depending on how we expose an API to programmatically collapse/expand/check state of a group.This PR adds
HeaderGroupBuilder
andListItemGroupBuilder
with default behavior for headers and list items. All customization can be done using constructor parameters for these builders. For example, customizing the toggle button, restricting the maximum number of children of a group, etc.ToggleableGroup
is the default widget used for headers and list items, which includes a default button that fades in when the mouse enters, fades out when the mouse leaves, animates upon tap. It also includes a vertical line below the button, that also fades in/out. The widget can optionally animate the expanding/collapsing of a group.A change that might be regrettable is that I changed
_SingleColumnDocumentLayoutState
to be public, so I can access information about groups inside tests. Once we figure out a public API for that this can be reverted.Remaining work
Screen.Recording.2024-11-11.at.16.23.53.mov