Skip to content

Instantly share code, notes, and snippets.

@amk221
Last active October 23, 2024 10:20
Show Gist options
  • Save amk221/1f9657e92e003a3725aaa4cf86a07cc0 to your computer and use it in GitHub Desktop.
Save amk221/1f9657e92e003a3725aaa4cf86a07cc0 to your computer and use it in GitHub Desktop.
Prosemirror placeholder plugin approach
.ProseMirror[data-placeholder]::before {
color: global.$placeholder-colour;
position: absolute;
content: attr(data-placeholder);
pointer-events: none;
}
import { Plugin } from 'prosemirror-state';
export default function placeholder(text) {
const update = (view) => {
if (view.state.doc.textContent) {
view.dom.removeAttribute('data-placeholder');
} else {
view.dom.setAttribute('data-placeholder', text);
}
};
return new Plugin({
view(view) {
update(view);
return { update };
}
});
}
@udany
Copy link

udany commented Nov 18, 2022

Thank you, found it very helpful ♥

@amk221
Copy link
Author

amk221 commented Nov 18, 2022

👍

@michael
Copy link

michael commented Jul 5, 2023

Wow! Really elegant. Thanks a lot!

@amk221
Copy link
Author

amk221 commented Jul 5, 2023

Just a heads up that this working, depends on your schema.

You might also need this, if you have block nodes:

if (view.state.doc.textContent || view.state.doc.firstChild?.content.size > 0)

@michael
Copy link

michael commented Jul 5, 2023

You mean a situation where you have no text at all, but other content rendered as block nodes? Yeah, then view.state.doc.textContent will not pick it up. So adding the second check makes it robust for that case as well. 👍

@michael
Copy link

michael commented Jul 5, 2023

Oh and for centered text the placeholder gets aligned strangely. Maybe you have an idea how to deal with that situation?

@amk221
Copy link
Author

amk221 commented Jul 5, 2023

Nothing springs to mind for center. But perhaps right: 0 would work for rtl.
Sorry I can't be more help. I kinda wish PM solved this for us

@michael
Copy link

michael commented Jul 6, 2023

Yeah, and the placeholder ideally works without knowing about layout details. But yeah this seems to be a hard nut to crack. I tried once, and ended up with a workaround too. If I find a way to do it, I will let you know here! :)

For now I have this hack in place:

/* HACK to fix centered placeholders in bio */
.__centered .ProseMirror[data-placeholder]::before {
  position: static;
}

Will not work for multi-line inputs, and cursor will be at the end of the word, but better than an offset placeholder.

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