-
Notifications
You must be signed in to change notification settings - Fork 8
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
feat: improve collapsible blocks #154
Conversation
Nice! My Notion-like editor experience dreams are becoming a reality. Could you say more about the situation of deleting content across nodes containing a collapsible block? I'm not sure I understand the situation well enough to comment. When in doubt, try it in Notion! A few differences I notice from Notion:
Screen.Recording.2023-06-14.at.1.06.18.PM.mov
I also hit what I believe to be a bug: I have an unordered list inside of a collapsible element. When the cursor is at the end of the collapsible element text, I hit Screen.Recording.2023-06-14.at.1.13.46.PM.mov |
Thank you for the feedback! What I meant for the situation of deleting across nodes was this situation: Screen.Recording.2023-06-14.at.12.38.33.movWhat happens in notion is that the content of the last collapsible block is added as the content of the collapsible block where the start of the selection is. But this actually brings another question: what should happen when the start of the selection is not in collapsible block? This is the result on notion and it seems a bit weird: as you can see the empty collapsible block is moved above 1.1.3 for some reason: Screen.Recording.2023-06-14.at.12.40.07.mov
|
That is weird! I don't have a great thought for the right behavior in this situation. The "ghost" collapsible caret with the text dangling below it doesn't seem ideal but maybe there are deeper reasons Notion does that. I think we're fine if we write down the decision we make and file it away to revisit later.
Sounds correct to me. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely a strong move in the direction of Notion parity!
The code for manipulating the nodes is quite intricate and my main question is around how we want to set up testing for it. A few ideas:
- Have a "script" that a human periodically goes through ("type ABC, put the cursor between B and C and hit enter"). This would be tedious but would at least document our expectations. This is kind of what @hammer and I are doing already in the comments :)
- Look into some kind of test runner like Playwright. These sorts of things are always a bit of a PITA to set up but they do create an extremely realistic test environment. I believe this is what VS Code uses. TipTap looks like it uses Cypress, which is similar.
- Try to create some sort of unit test by creating the nodes that tip tap expects (maybe by writing out Markdown) and calling the individual functions like
setCollapsibleBlock
with each situation (no selection, selected text on the fold header line, selection crossing the header line and foldable content). Depending on how TipTap works internally, this may or may not be possible
src/TipTapEditor/CollapsibleBlock/helpers/unsetCollapsibleBlock.ts
Outdated
Show resolved
Hide resolved
src/TipTapEditor/CollapsibleBlock/helpers/unsetPartiallySelectedCollapsibleBlocks.ts
Outdated
Show resolved
Hide resolved
src/TipTapEditor/CollapsibleBlock/helpers/unsetPartiallySelectedCollapsibleBlocks.ts
Outdated
Show resolved
Hide resolved
src/TipTapEditor/CollapsibleBlock/nodes/CollapsibleBlockNode.ts
Outdated
Show resolved
Hide resolved
if (dispatch) { | ||
tr.setNodeAttribute(collapsibleBlockStartPos, 'folded', !folded); | ||
if (!folded) { | ||
// Reset selection if it was inside the content |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hadn't really considered how toggling a fold would interact with selections but… wow!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I hadn't considered it either, before playing around with the editor. The choice here is to place the caret at the end of the collapsible block's header when the selection overlaps the block content. That's not what notion does, but I think it's a viable solution, that is too hard to implement.
I pulled @danvk's comments on Notion parity into a new issue: #154 (comment). Feel free to address the relevant ones here and do the rest in a future PR! |
You can improve the BACKSPACE behaviour when editing the collapsible block to match Notion. Screen.Recording.2023-06-21.at.15.49.42.movAdditionally you can also implement the SHIFT+TAB action to "remove 1 indentation" when used in a collapsible block. |
expect($from.sameParent(editor.state.doc.resolve($from.pos - 1))).toBe(false); | ||
}); | ||
|
||
test('should do nothing when the block cannot be turned into a collapsible block', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why can't we turn headings into collapsible? @sehyod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is because headers are blocks, whereas collapsible summary must be inline content. I have checked on notion and this is aligned with what they do (you cannot turn a header into a collapsible block)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is only true for H1 (the page title) in Notion.
You are right @hammer. We will move these comments to the other issue(s) and merge this (it's actually merged already 🎉 ). |
Thank you for all the comments! I have addressed the easiest remaining issues and have added tests.
|
Fixes #139
>
now creates a collapsible (or transforms the current block into a collapsible block)This is a WIP branch, the behaviours when pressing Enter and when deleting content across nodes containing a collapsible block still need to be defined.