Skip to content

feat: add toc toolbar item#3247

Open
VladaHarbour wants to merge 3 commits into
mainfrom
sd-2751_toc-node-icon
Open

feat: add toc toolbar item#3247
VladaHarbour wants to merge 3 commits into
mainfrom
sd-2751_toc-node-icon

Conversation

@VladaHarbour
Copy link
Copy Markdown
Contributor

No description provided.

@VladaHarbour VladaHarbour self-assigned this May 12, 2026
@VladaHarbour VladaHarbour requested a review from a team as a code owner May 12, 2026 15:26
@linear
Copy link
Copy Markdown

linear Bot commented May 12, 2026

SD-2751

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1456204222

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment on lines +728 to 746
#syncTableOfContentsToolbarAvailability() {
const tocItem = this.toolbarItems.find((item) => item.name.value === 'tableOfContents');
if (!tocItem) return;

if (!this.activeEditor) {
tocItem.setDisabled(true);
return;
}

let available = false;
try {
const cap = this.activeEditor.doc.capabilities();
available = Boolean(cap.operations['create.tableOfContents']?.available);
} catch {
available = false;
}

tocItem.setDisabled(!available);
}
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.

every other toolbar item derives its disabled state from HEADLESS_ITEM_MAP + the registry's state() deriver, which feeds snapshot.commands[id].disabled through #applyHeadlessState. this adds a parallel one-off path that calls capabilities() directly and only refreshes when updateToolbarState() runs. could tableOfContents register through HEADLESS_ITEM_MAP instead so it stays in sync with snapshots automatically and doesn't introduce a second mechanism for the same thing?

const XL_OVERFLOW_SAFETY_BUFFER = 20;
const XL_CUTOFF = RESPONSIVE_BREAKPOINTS.xl + XL_OVERFLOW_SAFETY_BUFFER;
const XL_ITEMS = ['linkedStyles', 'clearFormatting', 'copyFormat', 'ruler'];
const XL_ITEMS = ['linkedStyles', 'copyFormat', 'ruler'];
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.

clearFormatting is still in itemsToHideXL (defaultItems.js:1079), so removing it from this expected list silently drops a boundary assertion. was that intentional? if not, adding 'clearFormatting' back keeps the coverage.


const itemsToHideXL = ['linkedStyles', 'clearFormatting', 'copyFormat', 'ruler', 'formattingMarks'];
const itemsToHideSM = ['zoom', 'fontFamily', 'fontSize', 'redo'];
const itemsToHideSM = ['zoom', 'fontFamily', 'fontSize', 'redo', 'tableOfContents'];
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.

tableOfContents got added to itemsToHideSM but the test file only covers XL overflow. worth a small SM case mirroring the XL one — otherwise a future reorder could quietly move tableOfContents out of overflow without a test failure.

Comment on lines +143 to +147
if (inserted && props.dispatch) {
globalThis.queueMicrotask(() => {
syncTocBookmarks(editor, prepared.sources);
});
}
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.

the non-toolbar TOC path runs syncTocBookmarks synchronously after dispatch (toc-wrappers.ts:912). here the command schedules it via queueMicrotask. was the asymmetry intentional? running the sync from the toolbar caller after the command returns would match the existing pattern and keep the command itself a pure transaction producer.

throw error;
}
},
insertTableOfContentsFromToolbar: () => (props) => {
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.

the FromToolbar suffix bakes the caller into the API, but the behavior (insert at selection, fall back to document end) isn't toolbar-specific. if a slash menu or shortcut wants the same thing later the name will lie — drop the suffix?

Copy link
Copy Markdown
Contributor

@luccas-harbour luccas-harbour left a comment

Choose a reason for hiding this comment

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

hey @VladaHarbour!
I was reviewing this one in the browser and seem to have found some issues.

These are the steps I took:

  1. I opened the basic/advanced-text.docx document from our test corpus in the editor
  2. Then I placed the cursor at the start of the first line and pressed enter to create a new line above it
  3. I moved back up to the empty line I created
  4. I clicked the new TOC button in the toolbar
    Nothing happened, the TOC was not added and no javascript errors surfaced in the console.

Then, I did this:

  1. I placed the cursor after the document title (the SuperDoc Advanced Text Formatting line)
  2. I pressed enter to create a new line below the title
  3. I clicked the new TOC button in the toolbar
    This time the TOC was added but all page numbers were set to zero. I had to right-click and select "Update table of contents" for the numbers to show up correctly.

Also, codex found this one:

  • [P2] Disable the overflowed TOC item as well — packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js:729-729
    On widths below the small breakpoint, tableOfContents is moved into overflowItems, but this sync only searches this.toolbarItems. In that state, if create.tableOfContents is unavailable (for example a custom editor without the TOC extension), the overflow menu item remains enabled and clicking it can still route to a missing/unsupported command. Include this.overflowItems when locating the TOC item.

Claude found a few more things that I added as inline comments.

Can you check these? Thank you!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants