Skip to content

fix: Exit the list on Backspace in an empty list item in Docs#339

Merged
hackerwins merged 2 commits into
wafflebase:mainfrom
semimikoh:docs/list-item-backspace-exit
Jun 16, 2026
Merged

fix: Exit the list on Backspace in an empty list item in Docs#339
hackerwins merged 2 commits into
wafflebase:mainfrom
semimikoh:docs/list-item-backspace-exit

Conversation

@semimikoh

@semimikoh semimikoh commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Design note for issue #338: pressing Backspace at the start of an empty list
item
should exit the list (convert it back to a paragraph), matching what Enter
already does. Today it does not — it is a no-op when the list item is the first
block (e.g. an empty document with numbering), or it merges into the previous
block otherwise.

This is the design-note-first step (no code yet) — opening for direction
before implementing. Implementation will follow on this same branch.

Why

The two paths live in packages/docs/src/model/document.ts. Enter →
splitBlock() has an early branch that converts an empty list-item to a
paragraph to exit the list. Backspace → deleteBackward() has no such
branch: at offset 0 it goes straight to "merge with previous", and the
if (blockIndex <= 0) return pos guard returns first when the item is the only
block — which is exactly why the empty-document case does nothing.

The note proposes mirroring splitBlock's branch in deleteBackward, placed
after the offset > 0 return and before the blockIndex <= 0 guard so it
also fires for the first/only block. It flags nested-list outdent (listLevel > 0)
as a non-goal / open question (matching Enter's simpler behavior for now).

Test plan

No code changes yet — design note only. The note's Test Plan covers the
implementation that will follow (mirrors the existing splitBlock empty-list-item
test in packages/docs/test/model/document.test.ts): empty list item as first
block, as non-first block, non-empty list item unchanged, mid-text delete
unchanged.

Notes for Reviewers

AI tools assisted with this PR: the code investigation and the note draft were
produced with Claude Code (Claude Opus 4.8). I reviewed the root-cause analysis
and every line of the note.

Fixes #338.

Summary by CodeRabbit

  • Bug Fixes

    • Backspace on an empty list item now exits the list by converting it to a paragraph, preserving the caret position and avoiding unintended merges.
  • Documentation

    • Added a design doc describing the Backspace-empty-list-item behavior, caret expectations, edge cases, risks, and a test plan; updated the Docs index.
  • Tests

    • Added unit tests validating the new Backspace behavior for empty list items.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6a0aa84b-8b63-419e-a7b0-77ef2f9582e8

📥 Commits

Reviewing files that changed from the base of the PR and between ce55f31 and 456fe0a.

📒 Files selected for processing (2)
  • packages/docs/src/model/document.ts
  • packages/docs/test/model/document.test.ts

📝 Walkthrough

Walkthrough

Adds a design document and README index entry, implements an early-return branch in Doc.deleteBackward to convert an empty list-item to a paragraph at offset 0, and adds two tests verifying the conversion and cursor behavior for first/only and non-first empty list items (listLevel: 0).

Changes

Backspace empty list-item exit design & implementation

Layer / File(s) Summary
Design document and index entry
docs/design/docs/docs-list-item-backspace-exit.md, docs/design/README.md
Design doc for issue #338 specifying Backspace at offset 0 on an empty list-item should convert the block to a paragraph; documents insertion point in deleteBackward(), caret expectations, risks, and a unit test plan. README index updated.
deleteBackward empty-list-item branch
packages/docs/src/model/document.ts
Adds an early branch in Doc.deleteBackward converting a zero-length list-item to paragraph via setBlockType and returning immediately.
Unit tests for Backspace behavior
packages/docs/test/model/document.test.ts
Adds two tests under the existing splitBlock/type-aware suite verifying Backspace turns empty list-item into paragraph for first/only and non-first cases and preserves cursor position without improper merging.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 Backspace taps the empty line, I hop—
A list-item sheds its hat and wakes as prose.
Caret stays steady, no messy merge or drop,
Design penned, tests in place, the editor grows.
Hop hop—code onward!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: implementing Backspace behavior to exit a list when pressed on an empty list item, which is the primary objective across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Design note for issue wafflebase#338. Backspace at the start of an empty list
item is a no-op (when it is the first block) or merges into the previous
block, instead of exiting the list. Enter already handles this in
Doc.splitBlock (empty list-item -> paragraph); Doc.deleteBackward is
missing the same branch, and the blockIndex<=0 guard returns before any
list handling, which is why the empty-document case does nothing.

The note proposes mirroring splitBlock's branch in deleteBackward,
placed before the blockIndex<=0 guard so it also fires for the
first/only block. Design-note-first; implementation to follow on this
branch.
@semimikoh
semimikoh force-pushed the docs/list-item-backspace-exit branch from 9133984 to ce55f31 Compare June 7, 2026 23:23
Backspace at offset 0 of an empty list-item now converts it to a
paragraph, exiting the list. Previously it was a no-op when the item
was the first/only block and merged into the previous block otherwise.

This mirrors the branch Doc.splitBlock already has for Enter, added to
Doc.deleteBackward before the blockIndex<=0 guard so it also fires for
the first/only block. Closes wafflebase#338.
@hackerwins
hackerwins self-requested a review June 16, 2026 08:54

@hackerwins hackerwins left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for your contribution.

@hackerwins
hackerwins merged commit 9f84085 into wafflebase:main Jun 16, 2026
4 checks passed
@semimikoh semimikoh changed the title Exit the list on Backspace in an empty list item in Docs fix: Exit the list on Backspace in an empty list item in Docs Jun 16, 2026
@hackerwins hackerwins mentioned this pull request Jun 20, 2026
3 tasks
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.

Backspace on an empty list item does not remove the list (Enter does)

2 participants