Repository navigation
Replace paragraph/heading options with configurable textBlocks - #6375
Closed
VPS-Andreas wants to merge 5 commits into
Closed
VPS-Andreas wants to merge 5 commits into
VPS-Andreas wants to merge 5 commits into
Conversation
The text block type select could only ever offer a fixed paragraph entry plus every enabled heading level, in a fixed order, with no way to show two distinct entries for the same underlying tag (e.g. a "Display" heading-1 variant next to a plain "Heading 1"). textBlockStyles' appliesTo-based style selection had the same limitation for styles.
textBlocks replaces the paragraph/heading options with a single ordered array of { name, tag, styles?, defaultStyle? } entries, driving both the type dropdown's content and order directly. Multiple entries may share a tag; the stored textBlockName attribute (now mandatory on every paragraph/heading node) disambiguates them. textBlockStyles entries lose their appliesTo in favor of being referenced by name from textBlocks[].styles, and a configured defaultStyle is applied automatically and made mandatory (no "Default" option) for that entry.
A safety-net migration (buildApplyTextBlocksMigration) always runs last, guaranteeing every node's textBlockName/textBlockStyle stay valid even after a later, textBlocks-unaware migration changes its tag (e.g. one that bumps every heading level).
listStyles is a new, separate option for a list item's text block style, since a list isn't a textBlocks entry of its own (it's toggled via a toolbar button, not chosen from the type dropdown) — previously expressed via appliesTo: ["ordered-list", "unordered-list"].
isTextBlockType (cms-admin only) marks a textBlockStyles entry as a text block's sole identity rather than a free style choice: as an entry's only style and defaultStyle, it hides that entry's otherwise pointless single-option style dropdown, matching how the legacy Draft.js RTE never separated element and style for a block type like this.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adapts every existing story's config to textBlocks/listStyles, adds stories for the new defaultStyle-required style (no "Default" option) and isTextBlockType (a style acting as a text block's sole identity, e.g. a "Display" heading-1 variant), and splits the heading-focused stories (levels, heading-only, isTextBlockType) into their own file, matching the existing Translation/InlineStyles split. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
textBlocks order was the only way to pick a schema's default block type (used for new/empty content and, for a heading-only schema, the ProseMirror default): whichever entry a consumer wanted as the default had to also be listed first in the type dropdown. The old paragraph/heading options didn't have this problem — heading's defaultLevel picked the default independently of the dropdown's own (unsorted, as-given) levels order. defaultTextBlock restores that independence: an optional name of a textBlocks entry, defaulting to textBlocks[0] when omitted, that a consumer can set without disturbing the dropdown order. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…eading level via keyboard shortcut In a heading-only schema, Mod-Alt-<level> bypassed the toolbar's type-switch logic and called setHeading directly, leaving textBlockName pointing at the old level's textBlocks entry and textBlockStyle unvalidated against the new level's styles. Extract the toolbar's "preserve style if still valid, else fall back to the target's default" logic into resolveTextBlockStyleForSwitch and reuse it from both the heading shortcut and the toolbar's dropdown. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
The text block type select could only ever offer a fixed paragraph entry plus every enabled heading level, in a fixed order, with no way to show two distinct entries for the same underlying tag (e.g. a "Display" heading-1 variant next to a plain "Heading 1").
textBlockStyles'appliesTo-based style selection had the same limitation for styles.textBlocksreplaces theparagraph/headingoptions with a single ordered array of{ name, tag, styles?, defaultStyle? }entries (pluslabelon the admin side), driving both the type dropdown's content and order directly. Multiple entries may share atag; the storedtextBlockNameattribute (now mandatory on every paragraph/heading node) disambiguates them.textBlockStylesentries lose theirappliesToin favor of being referenced by name fromtextBlocks[].styles, and a configureddefaultStyleis applied automatically and made mandatory (no "Default" option) for that entry.defaultTextBlocknames whichtextBlocksentry is the schema's default (for new/empty content, and for a heading-only schema, the ProseMirror default block), independent of the array's own dropdown order — restoring the independence the oldheading.defaultLevel/heading.levelsoptions had.A safety-net migration (
buildApplyTextBlocksMigration) always runs last, guaranteeing every node'stextBlockName/textBlockStylestay valid even after a later,textBlocks-unaware migration changes its tag (e.g. one that bumps every heading level) — and backfillstextBlockNamefor legacy content that predates this attribute entirely.listStylesis a new, separate option for a list item's text block style, since a list isn't atextBlocksentry of its own (it's toggled via a toolbar button, not chosen from the type dropdown) — previously expressed viaappliesTo: ["ordered-list", "unordered-list"].isTextBlockType(cms-admin only) marks atextBlockStylesentry as a text block's sole identity rather than a free style choice: as an entry's only style anddefaultStyle, it hides that entry's otherwise pointless single-option style dropdown — covering the "Display" heading-1-variant case (#6369) without needing automatic dropdown-position heuristics, since order now comes directly from thetextBlocksarray position.This still builds on TipTap's own
Paragraph/Headingextensions (via.extend()), not a from-scratch replacement — only StarterKit's bundled copies are disabled in favor of the extended standalone packages, same as the existing pattern fortextBlockStyle.Example
Also covered by
createTipTapRichTextBlock.test.ts/.test.tsx, the migration tests, and the Storybook stories under "Heading" (Chromatic):Open TODOs/questions
buildApplyTextBlocksMigration(legacy heading content missingtextBlockNameentirely; a staletextBlockNameafter a later migration changes a shared-tag node's level)textBlockMaptargets one of twotextBlocksentries sharing a tag🤖 Generated with Claude Code