-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Replace the side inserter by an inserter with shortcuts on empty paragraphs #4953
Conversation
Amazingly fast work. Also closes #4954. Taking a look. |
This is already feeling much better than anything we've done in the past. |
editor/store/reducer.js
Outdated
@@ -627,12 +634,17 @@ export function preferences( state = PREFERENCES_DEFAULTS, action ) { | |||
insert, | |||
...reject( prevState.recentInserts, isSameAsInsert ), | |||
], | |||
insertUsage: { | |||
...prevState.insertUsage, | |||
[ id ]: usage, |
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 think it would be slightly clearer if we remove lines 624-627 and increment the count right here:
insertUsage: {
...prevState.insertUsage,
[ id ]: {
count: prevState.insertUsage[ id ] ? prevState.insertUsage[ id ].count + 1 : 1,
insert,
},
},
editor/store/selectors.js
Outdated
} | ||
|
||
/** | ||
* Determines the items that appear in the inserter with shortcodes based on the block usage |
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.
Typo: s/shortcodes/shortcuts/
* @return {Editor.InserterItem[]} Items that appear in the 'Recent' tab. | ||
*/ | ||
export function getRecentInserterItems( state, enabledBlockTypes = true ) { | ||
function getItemsFromInserts( state, inserts, enabledBlockTypes = true, maximum = MAX_RECENT_BLOCKS ) { |
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'm wondering if we should we get rid of MAX_RECENT_BLOCKS
and force callers to just always pass in a maximum.
editor/store/selectors.js
Outdated
* | ||
* @return {Editor.InserterItem[]} Items that appear in the 'Recent' tab. | ||
*/ | ||
export function getMostFrequentlyUsedBlocks( state, enabledBlockTypes = true, maximum = MAX_RECENT_BLOCKS ) { |
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.
Would getFrequentInserterItems
be a better name for this? Then there would be a nice duality between this function and getRecentInserterItems
.
editor/store/test/selectors.js
Outdated
}, | ||
}; | ||
|
||
// We should get back 8 items with no duplicates |
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.
Typo: s/8/4/
return null; | ||
} | ||
|
||
const itemsWithTheDefaultBlock = |
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.
Should this be named itemsWithoutDefaultBlock
?
export default compose( | ||
connect( | ||
( state ) => ( { | ||
items: getMostFrequentlyUsedBlocks( state, true, 3 ), |
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.
We should pass in the proper enabledBlockTypes
setting instead of true
here.
} | ||
|
||
const itemsWithTheDefaultBlock = | ||
filter( items, ( item ) => item.name !== getDefaultBlockName() || ! item.initialAttributes ) |
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.
! item.initialAttributes
will always evaluate to false. I think this should be:
const itemsWithoutDefaultBlock = filter( items, ( item ) =>
item.name !== getDefaultBlockName() || Object.keys( item.initialAttributes ).length > 0
).slice( 0, 2 );
Using without
and isEmpty
would help make it read more naturally:
const itemsWithoutDefaultBlock = without( items, ( item ) =>
item.name === getDefaultBlockName() && isEmpty( item.initialAttributes )
).slice( 0, 2 );
Just realised this has the |
@noisysocks No problem, it's always good to have feedback. And I would have missed most of these ;). Thanks |
@youknowriad one more thing to look at is the blue inserter line when you click on the + button — it should not be there as you'd be replacing the existing block instead: Also, related to 4492, none of the block UI should be showing when clicking on the + button. |
Will the inserter shortcuts be grayed out until hovered as in #4951 and Dropbox Paper? I like the subtly of that apperance, which puts the focus back on the content. |
ed9f42b
to
a611508
Compare
I made some tweaks here, this should be closer to merge now. I'd love to have some input. |
@youknowriad this is working really well for me. If there's one last thing to add, it'd be to try not showing the block outline, the paragraph toolbar, and the ellipsis menu when the paragraph block is empty. |
523b376
to
dbad796
Compare
Got a DM approval for this one cc @mtias . Merging to be ready for the release. There's still an edge-case where the |
🎉🔥 |
I really like this iteration. One issue I've noticed: It's not possible to expand the "More Options" block ellipsis menu with an empty default block. Potentially related to #4872 (comment) If it is, maybe we should evaluate whether that auto-focus logic is worthwhile? |
@aduth I don't it's related to #4872, it's more related to this comment #4953 (comment) and this commit dbad796 It's a bit tricky though, because we want the empty paragraph block to always appear unselected while allowing these menus on hover. |
} | ||
|
||
const itemsWithoutDefaultBlock = filter( items, ( item ) => | ||
item.name !== getDefaultBlockName() || ! isEmpty( item.initialAttributes ) |
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 ! isEmpty( item.initialAttributes )
?
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.
It's so that shared paragraph blocks don't get filtered out.
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.
As a casual observer, I'd have no hints from the context available to reach this conclusion. Even now, I'm not clear what it is about shared blocks that causes us to filter them.
I'd suggest some combination of code comment and/or explaining variable.
closes #4951
This PR updates the side inserter. Instead of having a side inserter at the right of each block we show a quick inserter with shortcuts for the most frequently used blocks on empty paragraphs.
Combined with the default block appender, this allows a nice writing flow, where you click the empty area at the bottom of a post to create a new empty paragraph which will trigger this side inserter.