-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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 Editable Permalinks #5756
Add Editable Permalinks #5756
Conversation
Related: #5494 Aside: I see a notice |
@afercia: Bug squished, thanks. 🙂 |
On this branch I am noticing one thing not like the design, which actually was in the thread and that's copying when clicking the link icon. Here is the conversation for reference:#3418 (comment). We need to of course test this with notices again but overall seems like the design and on track there. |
Oh, I totally missed that in the conversation. Thanks, @karmatosed! I turned the |
Good catch, yes can the icon grey out maybe for now until a revisit of that page or refresh? We can consider later if we need a text feedback also. |
Done! |
Sorry I have to reference also to the a11y feedback given in the previous PR see #3418 (comment)
Also:
Visually, I'd leave this to @karmatosed but I'm not fully sure about the copy button discoverability: it doesn't look like a button, not sure why users should understand it's an UI control. Note: the permalink is empty now. |
Link that opens in a new tab/window ( |
clearTimeout( this.dismissCopyConfirmation ); | ||
componentWillMount() { | ||
if ( this.props.samplePermalinkData ) { | ||
this.updateSamplePermalink( this.props.samplePermalinkData[ 0 ], this.props.samplePermalinkData[ 1 ] ); |
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 a once-documented premature optimization anti-pattern, as it's duplicating the source of truth, not necessarily state of the component:
It will save many a headache to simply calculate the value as used.
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.
Further, a better optimization we might consider is to create a separate component which manages the editing behaviors, and is only rendered when this.state.editingPermalink
is true.
(i.e. why do we calculate this state when I'm merely editing the title's text, or viewing the permalink?)
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.
Good point, changed to just calculating when rendering the form.
* @param {string} postName The post slug to use in replacements. | ||
*/ | ||
updateSamplePermalink( template, postName ) { | ||
const regex = /%(?:postname|pagename)%/; |
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.
If this is constant, seems we could move it to top-of-file (shared scope) and document appropriately for what it's matching.
this.setState( { | ||
showCopyConfirmation: true, | ||
samplePermalink: template.replace( regex, postName ), | ||
samplePermalinkPrefix: template.split( regex )[ 0 ], |
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.
Aside from potential waste in needlessly calling String#split
twice generating the same result, this is a good use case for ES6 array destructuring:
const [ samplePermalinkPrefix, samplePermalinkSuffix ] = template.split( regex );
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.
👍🏻
samplePermalink: template.replace( regex, postName ), | ||
samplePermalinkPrefix: template.split( regex )[ 0 ], | ||
samplePermalinkSuffix: template.split( regex )[ 1 ], | ||
postName: postName, |
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: This can be shortened to just postName,
when property name and variable value match.
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.
👍🏻
type="text" | ||
className="editor-post-permalink__edit" | ||
defaultValue={ postName } | ||
onChange={ ( e ) => this.setState( { editedPostName: e.target.value } ) } |
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.
What is e
? error
?
I'm being facetious 😄 but I generally tend to discourage abbreviations where ambiguity is possible.
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.
👍🏻
previewLink: getEditedPostPreviewLink( state ), | ||
samplePermalinkData: getEditedPostAttribute( state, 'sample_permalink' ), | ||
|
||
permalinkStructure: window.wpApiSettings.schema.permalink_structure, |
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.
A few issues:
- As much as possible, we shouldn't access the
window
global directly, since it proliferates the expected global prerequisites beyond that which we're otherwise establishing through the single entry point for initializing an editor - This value is not being sourced from the editor state, and as such does not belong in
connect
'smapStateToProps
(not mapped from state) - To the previous point, perhaps this should be in editor state, or otherwise provided through context in
EditorProvider
, where other settings are exposed and later accessed bywithContext
- To this previous point, technically there is context already available for this provided through
withAPIData
, but since we're not really using API data here, it doesn't seem necessarily appropriate to create a dependency here on this context.
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.
Turns out I didn't need that at all, everything was in sample_permalink
on the post.
}; | ||
}, | ||
{ | ||
editPost, |
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 fine enough since we already have connect
here anyways, but new usage is encouraged (and hopefully simplified) to use withDispatch
instead:
import { withDispatch } from '@wordpress/data';
import { Component, compose } from '@wordpress/element';
// ...
export default compose( [
connect( ( state ) => {
return {
isNew: isEditedPostNew( state ),
previewLink: getEditedPostPreviewLink( state ),
samplePermalinkData: getEditedPostAttribute( state, 'sample_permalink' ),
permalinkStructure: window.wpApiSettings.schema.permalink_structure,
};
} ),
withDispatch( ( dispatch ) => {
const { editPost } = dispatch( 'core/editor' );
return { editPost };
} ),
] )( PostPermalink );
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.
👍🏻
@@ -34,3 +38,20 @@ | |||
@include long-content-fade( $size: 20% ); | |||
} | |||
} | |||
|
|||
.editor-post-permalink__edit-form { | |||
width: 100%; |
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 element is technically the child of a flex container and could be sized with flex-basis: 100%; flex-shrink: 1;
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.
💪🏻
} | ||
|
||
.editor-post-permalink__save { | ||
float: right; |
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.
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.
💪🏻
permalinkStructure && ! editingPermalink && | ||
<Button | ||
className="editor-post-permalink__edit button" | ||
onClick={ () => this.setState( { editingPermalink: true } ) } |
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.
Because we only set editedPostName
when changing input, if one presses "Edit" and then immediately "Ok", the permalink is reset to empty.
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.
👍🏻
Perhaps we can build this behavior into the base |
Yah, I'm inlined to go this way. It's not an external link, so it seems weird to be using the Also, thanks to the magic of flexbox, mobile is significantly less unusably ugly now. |
Is there a selector like |
Quickly tested: while it seems to work with new posts: it doesn't seem to work well with existing posts:
From an accessibility perspective, I see part of the feedback is ignored. Navigating content for keyboard users and assistive technologies users is often a linearized experience. Content should be placed in a logical order, taking into account linearization. In this regard, the previous PR was better because it had in order:
(of course, "Copy" shouldn't be a primary button and some details were still unpolished, but the UI in the previous PR was better IMHO) |
Ooops. 🙃
Not ignored, you mentioned you were going to look at it in #5494, so I assumed the action was going to happen there. I'll see if I can make some changes in this PR, too. |
@afercia: I've just pushed a few tweaks to the keyboard order, can you give some feedback on that? I used |
Thanks @pento. Some a11y considerations: As long as it works in supported browsers, I think using autofocus is fine in this case, as this mini-UI has the specific task to edit the permalink The buttons placement is still not ideal, and it's a violation of a specific WCAG guideline: the visual order should always match the DOM order: Tooltips work in an accessible way out of the box when used for the Switching components on the fly produces a focus loss:
I'd remove the dot at the end of the string :) Note: I've edited the focus loss issue description, I had described a wrong scenario. |
If it's reasonable to apply broadly, I think we should pull this behavior out of |
1b6252e
to
6991336
Compare
Thanks for the extra info, @afercia. As it's just a shiny new kind of accessibility issue, I've reverted the DOM order of the copy button back to it's original place: @karmatosed previously mentioned that the design in this PR is a starting point, so let's look at how we can order these things in the next iteration. When the edit form is closed, it now focusses on the permalink, which seems to be the most relevant element to shift the focus to. From an accessibility perspective, how do you feel about the current state of this PR as a place to iterate from? There are certainly improvements to be made, but it seems like they are better made as part of the design iterations, as they depend on how things are laid out. @aduth: could you review the code again? @karmatosed: I think I've caught everything, but can you confirm that the current design of this PR matches what you had in mind? |
@pento thanks for the changes. The most important thing is to avoid the focus loss and that is addressed now (we can iterate on the better place to move focus to). Not sure @aduth As per the placement of elements, yep this is a case where design and accessibility have different needs. As you suggested I think we can iterate in #5494 even if that issue was meant to improve the placement and tab order of the whole UI, I think it can focus also on the UI content. @karmatosed I'd suggest to consider the link icon doesn't really look like a button, I have concerns on its discoverability. Can we consider a standard button, for better clarity for all users? |
Duplicates a similar fix in the classic editor.
…tion of the postname, and reshuffle the relevant code.
…ed the Change Permalinks button.
…nent is unmounting.
…and don't have a slug defined.
dc15592
to
6d3960f
Compare
This has been fun, y'all. Let's do polish things in follow up PRs. |
Description
#5414 has become way too unwieldy to work with, so this PR is a fresh attempt, based on @karmatosed's design.
Screenshots (jpeg or gifs if applicable):
Checklist: