Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lexical-react][lexical-playground] Feature: Makes the sidebar available inside Column Layout #7361

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

sescandell
Copy link
Contributor

Description

The DraggablePlugin currently only works on top-level nodes. For instance, when using the Column Layout block, users cannot access the "Add Above" or "Add Below" buttons inside a column. This limitation makes it difficult to work with nested structures.

This PR introduces a new mechanism allowing users to provide a function to control how deeply the plugin navigates and how to retrieve inner nodes within complex structures. This enhancement gives users greater flexibility to customize the plugin's behavior and user interface.

Additionally, this PR introduces the ability to replicate Notion-like behaviors for column layouts. However, it does not address drag-and-drop functionality inside columns, as that is already unsupported. This PR serves as a first step toward enabling drag-and-drop within column layouts, which will be probably tackled in a separate PR.

Test plan

Before

msedge_98hS6Oa8t9.mp4

After

msedge_0qxeOMlMnV.mp4

Copy link

vercel bot commented Mar 22, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
lexical ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 22, 2025 6:01pm
lexical-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 22, 2025 6:01pm

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 22, 2025
Copy link
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a useful feature but I am not sure the approach here is quite general enough

@@ -43,17 +43,56 @@ const Downward = 1;
const Upward = -1;
const Indeterminate = 0;

let prevIndex = Infinity;
interface ElementInfosHolder {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is kinda redundant, information doesn't have a separate plural form in english and generally speaking any data structure is a "holder" (particularly in a language like JS) so "InfosHolder" doesn't make sense. I would just call it BlockElement because that's how you're referring to it in the API (e.g. getBlockElementFromNodes returns this type)

Suggested change
interface ElementInfosHolder {
interface BlockElement {

[draggableElement, editor],
);

const $getInnerNodes = useCallback(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no reason to wrap this with useCallback, it could just be a top-level function since it doesn't close over any variables in the component

Comment on lines +133 to +135
function getBlockElementFromNodes(
// Array of array: from left to right then top to bottom
nodeKeys: string[][],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't done a very close audit of all of these changes but I am not sure this is the right data structure and API for this purpose. I think a better solution might be to have a function that's more like $getBlockDescendants: (key: ElementNode) => ElementNode[], working directly with keys is something that's more of an implementation detail rather than a good interface for users to specify.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you mention it... I should be able to use the isInline() method to determine whether I need to go deeper or not, and create something more dynamic and general, rather than being limited to the Column Layout.

Give me some time to rework this PR. 👍

Copy link
Collaborator

@etrepum etrepum Mar 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for this case a parent with $isRootOrShadowRoot is likely what you need to be looking at rather than isInline, e.g. RootNode, LayoutItemNode, TableCellNode, CollapsibleContentNode are probably the only nodes in the playground that should have this UX for managing their children and they are all roots or shadow roots. There are other shadow roots but there's generally some command listeners that prevent selections from falling there, e.g. TableNode, TableRowNode, CollapsibleContainerNode, etc.

@sescandell sescandell changed the title [lexical-react][lexical-playground] Feature: Makes the sidebar available inside Column Layout [WIP][lexical-react][lexical-playground] Feature: Makes the sidebar available inside Column Layout Mar 23, 2025
@sescandell sescandell marked this pull request as draft March 23, 2025 21:09
@sescandell sescandell changed the title [WIP][lexical-react][lexical-playground] Feature: Makes the sidebar available inside Column Layout [lexical-react][lexical-playground] Feature: Makes the sidebar available inside Column Layout Mar 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants