-
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
Add Archives block #5495
Add Archives block #5495
Conversation
Specs for the possible archives REST API endpoint in case of going that direction:
Thoughts? |
I don't think that the response should include |
Okay. I was thinking that maybe including However, I guess from API's perspective it makes more sense to just return raw data in this case 👍 |
Have to agree with @miina approach. Other works on visual shortcodes are returning HTML from WP, including CSS + JS |
The main problem with this for me is what to do about content that is added with the archives block. Is the content only for when there is nothing in the archive, is there an option for that. Will it fall-back to the built-in WP content experience (with oEmbed & shortcode) etc? If it does, I think running |
…t of the REST API * Singularize "blocks renderer" to "block renderer" * Rename 'output' property to 'rendered' property. * Re-use get_item_permissions_check and get_item method names.
* Supply block attributes schema as endpoint schema. * Introduce attributes endpoint property and let REST API schema validate and sanitize them. * Ensure that attribute values are sanitized in addition to validated.
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.
core-blocks/archives/index.php
Outdated
*/ | ||
function render_block_core_archives( $attributes ) { | ||
static $block_id = 0; | ||
$block_id++; |
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.
The way this is used in tandem with ServerSideRender
, this will generally lead to ID conflicts. From my own local testing:
document.querySelectorAll( '#wp-block-archives-1' )
returns multiple elements if I have more than one Archive block in my editor.
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.
Worth noting that implementing an edit
for this block type would allow the editor to retain more control over this kind of information.
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.
Added using uniqid
instead, thoughts?
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.
@mcsf Also disabled the pointer-events of the links, this way it'll not cause the leaving page alert, however, the links are not clickable within the editor. Probably better but not ideal, thoughts?
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.
Added using
uniqid
That should do for now, thanks.
disabled the pointer-events of the links
It doesn't solve for other interactions (e.g. when attribute Display as dropdown is on). It's indeed not ideal, but I don't have a good solution. I mean, sure, we could also disable pointer-events on select
elements, but then even more interaction is lost, perhaps leading the user to perceive the experience as "buggy" and, thus, confusing. On the other hand, hijacking select
elements to remove their onchange
attribute could technically help, but that sounds like a very bad precedent to set. /cc @mtias
core-blocks/archives/index.php
Outdated
static $block_id = 0; | ||
$block_id++; | ||
|
||
$show_post_count = ! empty( $attributes['showPostCounts'] ) ? true : false; |
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.
Ternary unnecessary
// for any boolean A,
( A ? true : false ) === A
core-blocks/archives/block.js
Outdated
onChange={ ( nextAlign ) => { | ||
setAttributes( { align: nextAlign } ); | ||
} } | ||
controls={ [ 'left', 'center', 'right', 'full' ] } |
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.
Curious why full
is supported but not wide
. (If both should be, the controls
prop doesn't need to be passed at all.)
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.
Not sure if it should support full
either, removed it.
Edit: Originally based this on other dynamic blocks, e.g. Categories
and Latest Posts
. Not sure if there's a standard for which controls to support. Thoughts?
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 not aware of a proper standard. I think it's fine to remove both for now.
In any case, cc'ing @jasmussen to make sure you're aware of these differences :)
</Fragment> | ||
); | ||
} | ||
} |
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.
Considering the life cycle of the ArchivesBlock component, and the fact that the block proper isn't very interactive, I'm not sure we need a class-based component and the ahead-of-time binding of the toggle*
methods. In other words, edit
could just be a functional component.
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.
@mcsf Curious if that's a matter of preference or would there be benefits for using edit
as functional component instead?
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 sort of been a tendency throughout Gutenberg to avoid what is, in a way, a performance trade-off that prioritizes performance of repeated rendering, at the (slight) cost of init-time bindings and increased memory footprint (which may add up with every little component) and at the (arguably) higher cost of code complexity for newcomers. For a component like ArchivesBlock, I'm tempted to say we're better off going with something simpler (i.e. functional component) even if it means binding two event handlers when rendering.
More on the subject of the cost of render-time inline functions: https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578
'type' => 'boolean', | ||
'default' => false, | ||
), | ||
'align' => array( |
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.
Minor/subjective, but the whitespace resulting from keeping certain elements aligned across lines can be distracting.
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.
The linter enforces this, for better or worse 🙂
@miina, moving to the 3.2 milestone. Do you need any help with this one, it wasn't updated in the last 18 days. |
Cool, so we will simply move it back to 3.1 if @mcsf is happy about the current shape of PR :) |
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.
Thanks for your patience, @miina.
Codewise I think we're essentially there, but I'm pretty concerned about the handling of interactive elements, namely those triggering navigation, as pointed out in inline comments.
To go into a broader discussion, I think this hurdle illustrates how tricky it can be to bridge server-rendered widgets (made for the specific context of front-end visualization; usually dependent on server logic but then also occasionally interacting with the client) and editor-facing blocks (highly interactive but also specifically built for the editing context). Solving for Archives will help for the next widgets that should be ported using <ServerSideRender />
, but I suspect more challenges will be met.
Let me reflect a bit, and also see if someone else has a different perspective on this that helps us move forward.
@mcsf Any thoughts on the implementation so far? For information that I'm going to be mostly offline now until the end of July -- if any changes would be necessary meanwhile to have the PR merged, anyone is welcome to pick it up. |
Some similar reflections came up while adding the Playlist block (#7126). I think that, in general, we should avoid using Having said that, I think That's my 2¢! Curious to hear what the leads think @mtias @karmatosed. |
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.
Code's looking really great! If we can think of a more durable solution than pointer-events: none
, then I'm happy.
@@ -0,0 +1,4 @@ | |||
.gutenberg .wp-block-archives a { | |||
pointer-events: none; |
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.
Unfortunately this doesn't completely disable the link. A user is still able to "click" it by focusing it using their keyboard and then pressing ENTER.
I'd try wrapping the <ServerSideRender>
component with the <Disabled>
component that we have and seeing what happens.
https://github.com/WordPress/gutenberg/tree/master/components/disabled
<InspectorControls key="inspector"> | ||
<PanelBody title={ __( 'Archives Settings' ) }> | ||
<ToggleControl | ||
label={ __( 'Show post counts' ) } |
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 probably should make this title case for consistency with other inspector control labels in Gutenberg.
label={ __( 'Show Post Counts' ) }
onChange={ this.toggleShowPostCounts } | ||
/> | ||
<ToggleControl | ||
label={ __( 'Display as dropdown' ) } |
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.
Same again here.
label={ __( 'Display as Dropdown' ) }
controls={ [ 'left', 'center', 'right' ] } | ||
/> | ||
</BlockControls> | ||
<ServerSideRender key="archives" block="core/archives" attributes={ this.props.attributes } /> |
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 could replace this.props.attributes
with attributes
.
|
||
save() { | ||
// Handled by PHP. | ||
return null; |
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.
Is there something we can return here as a fallback for clients like RSS readers that don't support dynamic blocks?
(Probably not, just wondering.)
|
||
category: 'widgets', | ||
|
||
keywords: [ __( 'archives' ) ], |
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 could remove this line. Gutenberg will treat the title (Archives) as an implicit search keyword.
'type' => 'boolean', | ||
'default' => false, | ||
), | ||
'align' => array( |
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.
The linter enforces this, for better or worse 🙂
Will continue implementation on #7949 |
Co-authored-by: Pascal Birchler <hello@pascalbirchler.ch> Co-authored-by: Miina Sikk <miina.sikk@gmail.com> Co-authored-by: Weston Ruter <weston@xwp.co>
* Changes from PR #5495 squashed into single commit Co-authored-by: Pascal Birchler <hello@pascalbirchler.ch> Co-authored-by: Miina Sikk <miina.sikk@gmail.com> Co-authored-by: Weston Ruter <weston@xwp.co> * Remove archived keywords, since the title is implicitly a keyword already * Use already destructured property `attributes` over `this.props.attributes` * Use title case for copy * Use `Disabled` element to prevent interaction with Archives Block editor view Use of `pointer-events` to disable interaction was problematic. It didn't disabled the dropdown version of the block and it doesn't prevent keyboard interaction. The Disabled component handles these situations. * Rename block.js to edit.js for consistency with other blocks * Convert ArchivesEdit to a function component * Remove `isSelected` boolean and inline InspectorControls * Render archives list container as `ul` when a list and `div` when a dropdown * Remove unnecessary React keys * Improve description copy
Uses #5602
Continued archives block implementation from #1518. Archive block implementation that uses similar output and filters as the archives widget. Has alignment toolbar within the block (
left
,center
,right
).Screenshots:
Block toolbar:
Inspector toolbar:
Dropdown view:
List view:
Fixes #1464.