Skip to content

feat: Placeholder DOM elements - #3205

Open
matthewlipski wants to merge 3 commits into
a11y-testingfrom
placeholder-element
Open

matthewlipski wants to merge 3 commits into
a11y-testingfrom
placeholder-element

Conversation

@matthewlipski

@matthewlipski matthewlipski commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Currently, DOM elements are rendered as CSS pseudo elements. This is a problem for a11y accessibility testing as we cannot use an axe-core scan to check its contrast. This is because axe only checks contrast for DOM elements. Therefore, this PR changes the implementation to use real DOM elements for placeholders.

This comes with a performance overhead. A script has been added in this PR which benchmarks the render time between the old & new implementations, using a document of 1000 empty paragraphs and 1000 empty list items. It measures the initial render times, as well as re-renders on selection and content changes. The table below shows the performance overhead tested locally.

Document Operation Old New
Paragraphs Initial render 32.80 ms 32.55 ms
Paragraphs Selection change 1.30 ms 1.60 ms
Paragraphs Content change 1.75 ms 2.00 ms
List items Initial render 50.25 ms 68.95 ms
List items Selection change 1.20 ms 2.70 ms
List items Content change 1.95 ms 4.00 ms

The alternative solution to this problem is to have additional contrast check tests just for placeholders. To be honest, both that solution and the one in this PR don't seem the cleanest, so I would appreciate feedback r.e. this.

This PR is currently more of an experimental change as I'm unsure whether we want this.

Fixes #3245. Replacing CSS pseudo-elements with DOM placeholders also resolves the stale "List" placeholder in Firefox after collaborative edits. Manually verified with Chromium as the writer and Firefox as the observer: the placeholder disappears when remote text arrives, including across repeated Enter-and-type cycles.

Rationale

TODO

Changes

TODO

Impact

TODO

Testing

TODO

Screenshots/Video

TODO

Checklist

  • Code follows the project's coding standards.
  • Unit tests covering the new feature have been added.
  • All existing tests pass.
  • The documentation has been updated to reflect the new feature

Additional Notes

TODO

@vercel

vercel Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
blocknote Ready Ready Preview Oct 22, 2026 12:24pm UTC
blocknote-website Ready Ready Preview Oct 22, 2026 12:24pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 18d00fe6-af80-42b7-a354-4cc0ec0e94e5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

// positions are hardcoded for now
if (state.doc.content.size === 6) {
decs.push(
Decoration.node(2, 4, {

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.

I think (had a quick look), you should be able to keep the old code, but change Decoration.node into Decoration.widget (in the right position)?

Your performance regression is likely that the new version loops the document (doc.descendents). From a quick look, I don't understand why all the code needed to change and not just the decoration type

# Conflicts:
#	packages/core/src/extensions/Placeholder/Placeholder.ts

This branch was successfully deployed

2 active deployments
Preview – blocknote-website — 4ef62360 Deployed Oct 22, 2026 by vercel[bot]
Preview – blocknote — 4ef62360 Deployed Oct 22, 2026 by vercel[bot]
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.

2 participants