Repository navigation
[Bug]: Tab in a composer numbered list keeps the number and does not nest the item in the sent Markdown #17124
Copy link
Copy link
Open
Labels
bugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
Description
Activity
Note
Grok responding on behalf of Julius.
Thanks for the detailed report. I checked it against current
main(30cc78897), and the Tab and Shift+Enter parts hold up.What the code does (confirmed)
- Tab:
listIndentForTabalways inserts" "at the start of the line and leaves the marker alone, so2.stays2.. The existing test only checks a bullet (- foo→- foo). - Both modes use it: the Tiptap editor passes Tab to the composer's key handler in plain and rich mode, and Tiptap's own list Tab/Shift-Tab are turned off.
ChatComposerthen callslistIndentForTab. - Why rich mode looks nested: the rich-text parser treats any deeper indent prefix as a child list, with no content-column check. Serialization then writes the stored indent back as typed. So the editor draws
1. first\n 2. nestedas nested, but the prompt text that gets sent is exactly that string. I ran it throughmdast-util-from-markdownwith GFM (the same micromark stackreact-markdown/remark-gfmuse)."1. first\n 2. nested"comes out as one flat list with two items, and"1. first\n 1. nested"comes out nested.- a\n - bnests fine, as you said. - Plain-mode Shift+Enter on an empty item:
listContinuationForEnterremoves the marker no matter how deep the indent is. Rich mode handles list items throughsplitOrLiftListItem, which lifts an empty item one level. That's why the two modes behave differently. - Shift+Tab:
ChatComposertoggles plan mode, or returnsfalsewhen plan mode isn't available, which lets the browser move focus back. Nothing outdents a list item.
The user docs say Tab nests a list item and that what you type is what the agent receives. That makes the flat result a bug and not intended behavior.
Inferred / not verified
- I didn't check how the sent message bubble renders this in the app. With the parser above it would likely show as a flat list.
- How a given model reads
2. nestedis outside our control. The sent text is simply not a nested list in CommonMark.
Possible fix direction (untested)
- Tab on a list line should indent to the item above's content column (marker width plus its following space, so 3 for
1.and 4 for10.). For ordered items it should restart at1.or continue an existing sublist. Because rich mode serializes the stored indent, fixing the source edit would likely fix both modes. - Plain-mode Shift+Enter on an empty nested item could outdent to the parent's indent and continue the parent's numbering, matching what rich mode already does.
- Whether Shift+Tab should outdent nested list lines is a separate maintainer call, since it changes the plan-mode shortcut on those lines. It isn't needed for the Tab/Shift+Enter fix.
Related
- fix(web): renumber following items when inserting into a numbered list #14332 (open): renumbers following items when you insert into a numbered list. It edits the same
composer-list-continuation.tsfunctions and the sameChatComposercall site. It also adds a caret field toComposerListEdit. Your branch adds one too, so the two would need reconciling. GitHub already shows fix(web): renumber following items when inserting into a numbered list #14332 as conflicting withmain. - feat(web): block-level Markdown in the rich text composer #14677 (merged): added block-level Markdown to the rich composer, where the current list parsing and serialization live.
- [Bug]: Message with numbers transforms into numbered list with wrong numbers #8394 (open, different issue: numbers in a message turning into a list) and feat(web): continue markdown lists and complete code fences in composer #12145 (closed, unmerged earlier list-continuation attempt).
On scope, your fork branch is one commit. It touches
composer-list-continuation.tsand its tests,ChatComposer.tsx, anddocs/user/composer.md, which covers the Tab nesting, the Shift+Enter outdent, and the Shift+Tab outdent. I haven't run it.- Tab:
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
on Oct 8, 2026 - added a commit that references this issue
on Oct 8, 2026
Metadata
Metadata
Assignees
Labels
bugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.via-triageFiled through npx t3 triageFiled through npx t3 triage
Before submitting
Area
apps/web
Steps to reproduce
1. first.2.(correct).nestedand send the message.Expected behavior
Tab nests the item as a sub-item and starts a nested numbered list, i.e. the draft becomes
which renders as a nested list (
a.in the chat, viaol ol { list-style-type: lower-alpha }), and the agent receives a nested list.There should also be a way back out of the nesting: Shift+Enter on an empty nested item should move it up one level and continue the parent's numbering (
2.), as it already does in the rich-text composer.Actual behavior
Tab only prepends two spaces and keeps the number, so the draft becomes
2.instead of starting a nested list.1.in CommonMark: a child must reach the parent's content column (3 spaces for1., 4 for10.). The sent Markdown is therefore a flat two-item list. Checked withmdast-util-from-markdown:"1. foo\n 2. bar"parses as one list with 2 items,"1. foo\n 1. bar"as a nested list. The rich-text composer draws it nested, but the agent and the sent message see a flat list.Bullet lists are unaffected by the indent width (
-has a content column of 2).Cause:
listIndentForTabinapps/web/src/composer-list-continuation.tsalways inserts" "at the line start and never touches the marker; both composer modes route Tab through it.Impact
Minor bug or occasional failure
Version or commit
main @ 30cc788
Environment
macOS 26 (Darwin 25.6.0), Node 24.15.0, web client via
vp run dev; reproduced in both the rich-text and the plain composer.Workaround
Indent manually with 3 spaces and type
1.yourself.Proposed fix
I have a fix with focused tests on my fork, and I'm happy to open a PR once you agree with the direction:
main...michal-billtech:t3code:fix/composer-nested-ordered-list
1.or continuing an existing sublist. With nothing to nest under it keeps today's two-space indent.The Shift+Tab part changes an existing shortcut (plan mode toggle) on nested list lines, so I'd like your call on it. Without it, Shift+Enter on an empty nested item still provides the way out, and I can drop it from the PR.