-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Problem Description
When building complex layout components in Slate (like multi-column layouts), there's no way to exclude certain DOM elements from Slate's contentEditable handling. This causes the browser to place the cursor in structural/UI elements when clicking on empty areas of the Editable component.
Current Behavior
Given this structure:
<div {...attributes}>
<ContainerWrapper> {/* Grid container */}
<ResizeHandle /> {/* UI element */}
<StyledColumns>
<Column>
<Paragraph>Text content</Paragraph>
</Column>
</StyledColumns>
<ResizeHandle /> {/* UI element */}
</ContainerWrapper>
</div>
When clicking on the Editable area where the grid/UI elements are visually positioned (but the actual DOM element is still Editable), the browser tries to place the cursor and finds the nearest contentEditable element, which becomes the structural containers (ContainerWrapper, StyledColumns, etc.).
- Setting
contentEditable={false}
on ContainerWrapper makes all children non-editable due to inheritance - Setting
contentEditable={true}
on children makes the container itself editable - Slate doesn't provide a way to mark DOM elements as "ignore for cursor placement"
Solution
There should be a way to tell Slate: "this DOM element is part of the component structure but should not participate in contentEditable behavior". Similar to how data-slate-void works, but for non-void structural elements.
Proposed Solution
Add a data attribute that Slate recognizes:
<ContainerWrapper data-slate-ignore-cursor>
{/* This element won't receive cursor focus */}
</ContainerWrapper>
Or a way to configure this in the editor:
editor.isIgnoredForCursor = (element) => {
return element.hasAttribute('data-slate-structural');
}
Alternatives
- Making the component a void element - but then children can't be normal Slate elements
- Using
contentEditable={false}
- but this affects all children - Intercepting clicks - but this is fragile and doesn't handle all cases
Context
This is a common issue when building advanced layouts in Slate. The current void element system works well for atomic elements (images, videos) but doesn't help with structural containers that need to contain regular Slate elements.
The issue is that Slate relies on the browser's contentEditable behavior, and there's no standard way to exclude certain elements from contentEditable cursor placement while keeping their children editable.