Postulate is the best way to take and share notes for classes, research, and other learning.
When creating a new post in Postulate, a Slate-Plugins editor shows up with an empty paragraph node as its value. This node renders as whitespace, and it's not clear to users that there is an editor there to write in.
The solution to this is to add a placeholder, low-opacity text that says something like "Write something great here...". A component-level placeholder plugin was recently merged, but what I wanted -- a placeholder that shows up when the entire editor is empty -- is a little different.
To create this placeholder, I created a new component SlatePlaceholder
, placing it inside my editor:
<SlatePlugins id="testId" value={body} onChange={newValue => setBody(newValue)} plugins={pluginsMemo} components={draggableComponents} options={options} > <SlateBalloon/> <SlatePlaceholder/> </SlatePlugins>
The component itself is straightforward:
import {useTSlate} from "@udecode/slate-plugins-core"; import {Element, Text} from "slate"; export default function SlatePlaceholder() { const {children} = useTSlate(); const isEmpty = children.every(d => getIsEmpty(d)); function getIsEmpty(node: Element | Text) { if (("children" in node && !node.children.length) || "text" in node && node.text === "") return true; if ("children" in node) return node.children.every(d => getIsEmpty(d)); return false; } return isEmpty ? ( <p className="opacity-50 absolute">Write something great...</p> ) : <></>; }
I use useTSlate
to get the current editor's children
property. Then, I use a recursive function getIsEmpty
to search through the editor's current value. If all nodes are empty, then I render a half-opacity paragraph reading "Write something great...". Setting it to absolute makes it show up in the same spot as the empty paragraph, so it can be clicked and written on like any other text field placeholder. As soon as something is typed, the placeholder disappears.
Founder and dev notes from building Postulate