Skip to content

feat: cascade list type changes across related list items #219

@oobagi

Description

@oobagi

Problem

When changing the type of a list item via the palette (e.g., BulletListNumberedList or Checklist), only the active block changes. This breaks list consistency — you end up with a mixed list where one item is a different type than its siblings/parents/children, which is almost never what the user wants.

Context

  • Block types: internal/block/block.go:19 (BulletList, NumberedList, Checklist), with IsListItem() at line 73.
  • Palette type conversion is driven through internal/editor/palette.go (openForBlock, defaultPaletteItems) and applied in internal/editor/editor.go where palette selection mutates m.blocks[m.active].Type.
  • Indent is tracked per-block via Block.Indent (see nested lists work from 2026-04-06).

Approach

When the palette selects a new list type and the active block IsListItem():

  1. Walk outward from m.active to find the full contiguous list group — siblings at any indent level, plus children (deeper indent) and parents (shallower indent) that are still list items.
  2. Stop the walk at the first non-list-item block in either direction.
  3. Apply the new list type to every block in that group, preserving each block's Indent and Content (and Checked where applicable — dropping check state when converting to non-Checklist).

Wrap in a single pushUndo() so the whole cascade is one undo step.

Tasks

  • Add a helper (e.g., listGroupRange(idx int) (start, end int)) that returns the span of the contiguous list group containing idx.
  • On palette selection of a list type while m.blocks[m.active].IsListItem(), apply the new type across [start, end].
  • Handle the reverse: converting from list → paragraph via palette should also cascade (or explicitly not — decide and document).
  • Tests in internal/editor/palette_test.go covering flat lists, nested lists, and mixed-indent groups.

Acceptance criteria

  • Changing list type on any item in a list converts the entire contiguous list group.
  • Nested children (deeper Indent) and parents (shallower Indent) in the same group convert together.
  • Non-list blocks adjacent to the list are untouched.
  • A single Ctrl+Z undoes the full cascade.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions