-
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
Render preview in a modal with responsive sizes. #18385
Conversation
24ecf7e
to
991c7d7
Compare
dff34cb
to
00b9f49
Compare
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 working nicely. The code seems pretty tidy, all the comments should be easy to fix.
The only thing I noticed in testing is that on a slower connection the iframe content can take a little while to load, so I wonder if we want some kind of placeholder or loading spinner to be displayed.
</DotTip> | ||
</Button> | ||
{ this.state.isPreviewOpen && | ||
<Modal |
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.
Indentation here doesn't look quite right. Usually these components are indented an extra tab when there's boolean logic.
{ this.state.isPreviewOpen && | ||
<Modal | ||
title={ | ||
// translators: Preview dialog title. |
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 the comment should be indented at the same level as the __()
function call below.
> | ||
{ _x( 'Preview', 'imperative verb' ) } | ||
|
||
<DotTip tipId="core/editor.preview"> |
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.
Just thought I'd double check that the DotTip
should be here? My understanding is they've all been removed in master.
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.
Uh, rebase gone wrong 😄
target={ this.getWindowTarget() } | ||
onClick={ this.openPreviewInNewTab } | ||
> | ||
{ _x( 'Open preview in new tab', 'imperative verb' ) } |
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.
{ _x( 'Open preview in new tab', 'imperative verb' ) } | |
{ __( 'Open preview in new tab' ) } |
<Modal | ||
title={ | ||
// translators: Preview dialog title. | ||
__( 'Preview' ) |
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.
__( 'Preview' ) | |
_x( 'Preview', 'imperative verb' ) |
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.
Hmm maybe the modal title shouldn't be "preview"? It doesn't sound right to have a component title as an imperative. I'll change it to "Preview dialog" for now, open to better suggestions.
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.
Oh right, I missed that it's the noun form. I think you can always change it to _x( 'Preview', 'noun' );
shouldCloseOnClickOutside={ false } | ||
className="editor-block-preview" | ||
> | ||
<div className="editor-block-preview__controls"> |
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.
<div className="editor-block-preview__controls"> | |
<div className="editor-post-preview__controls"> |
onRequestClose={ this.closePreviewWindow } | ||
// Needed so the Modal doesn't close when tabbing into the iframe. | ||
shouldCloseOnClickOutside={ false } | ||
className="editor-block-preview" |
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 classname should be made up of the package and component names. I think this would ideally be something like editor-post-preview-button__preview-modal
. I notice the button that was here originally also had the wrong class name, it should be editor-post-preview-button
.
// Display a 'Generating preview' message in the Preview tab while we wait for the | ||
// autosave to finish. | ||
writeInterstitialMessage( this.previewWindow.document ); | ||
closePreviewWindow() { |
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 this closes the modal, so the name of the function is a bit confusing.
@@ -128,7 +67,24 @@ export class PostPreviewButton extends Component { | |||
return `wp-preview-${ postId }`; | |||
} | |||
|
|||
openPreviewWindow( event ) { | |||
openPreviewOverlay() { |
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'd be good to stick with the name Modal instead of window or overlay 😄
@@ -138,59 +94,123 @@ export class PostPreviewButton extends Component { | |||
|
|||
// Open up a Preview tab if needed. This is where we'll show the preview. | |||
if ( ! this.previewWindow || this.previewWindow.closed ) { | |||
this.previewWindow = window.open( '', this.getWindowTarget() ); | |||
this.previewWindow = window.open( '', '_blank' ); |
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 it be _blank
? It looks like getWindowTarget
is still being used elsewhere.
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 funny one. I found that using the window name returned from getWindowTarget
caused window.open
to focus the iframe in the modal, rather than opening a new window (this although the iframe doesn't have any name set). Switching to _blank
solves that problem and if a preview tab is already open it will still be reused, so doesn't seem to make any difference.
I have similar questions in relation to adding Block controls which have different settings across viewports. There's a working effort in a PR here I'd like to sync my work with yours. |
@getdave this particular PR is not very relevant to yours because here I'm implementing responsive views in Preview mode, not in the editor. The ticket this originated from does mention the possibility of responsive editor controls though, and I'm intending to have a play around with that and see what we can do, but in another PR. I think both options answer different needs. The editor mode won't be an easy problem to solve though 😅 , usability-wise if not technically. |
GIF of ongoing work: It is helpful to see responsive previews like this. However making it a dialog feels like it's optimizing for how the editor works today, at the expense of how we'd like the editor to work in the future:
I much appreciate Dave reaching out to sync up, because feedback on the DimensionControl closely mirrors the challenge here. It recognizes that the editing canvas is currently neither responsive nor a proper preview, and tries to address that in a way that will arguably transform into technical debt one day when the editing canvas is responsive and a proper preview. What could be an interim step? Making it not a dialog, but showing it in the canvas itself, as mocked up here. It may seem a subtle difference — showing it as a not-modal modal absolutely positioned layer over the editing canvas. But it is a treament that can transform into what it should be in the future. And given it shows the sidebar, it might even lend itself to an interim responsive preview control for block settings too. |
<Modal | ||
title={ | ||
// translators: Preview dialog title. | ||
__( 'Preview dialog' ) |
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.
Please remove the word "dialog". That's already automatically announced by assistive technologies because of the role=dialog.
<div className="editor-post-preview__frame-container"> | ||
<iframe | ||
className="editor-post-preview__frame" | ||
title={ __( 'Responsive preview frame' ) } |
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.
Please remove the word "frame", that's already announced by assistive technologies because of the element native role
Re: the aXe test failure [question asked on Slack](https://wordpress.slack.com/archives/C02RP4X03/p1575522453104800), it is possible that aXe doesn;t get the content within the iframe and it "sees" it empty. Regardless, the rule aims to make sure:
In this specific implementation, the iframe container needs to be horizontally scrollable. Note that this will produce visible scrollbars on Windows (and also on macOS depending on user settings). Since it's scrollable, the scroll mechanism needs to be operable also when using the keyboard. Browsers behavior differs on scrollable divs. To make them accessible and consistent, see: Short note on improving usability of scrollable regions
Indication of focus would be a good addition.
After that, the container height should be adjusted to not exceed the modal height otherwise, when it receives focus, the modal content will scroll. Re: the modal size: Other things noticed in this PR that need to be addressed:
Lastly, worth noting that when tabbing to an iframe element, browsers behavior differs, for example:
Not sure this (historical) inconsistency can be addressed in any way as it's just a different vendor implementation. |
Thanks for your feedback @jasmussen ! It would be good to further discuss a few points:
We can make the editing canvas responsive today, and that's likely what we need to do for @getdave's PR, but we can't make it a true preview, and I doubt we will ever be able to do so. Let me elaborate: The markup for the editing canvas is necessarily different from the output markup. It's a lot more complex, and blocks are wrapped up in lots of layers needed to display the editing controls. Even if we assume that
it'll always be a brittle situation where any change to the editor can potentially cause theme styles to not render properly in it. Even if the editor gets really good at mirroring the output content, which no doubt we can accomplish, we can't trust it'll be exactly the same. Bearing that in mind, I think it's useful to keep the distinction between (responsive) editor and preview.
My concerns with making this a dropdown are that it adds an intermediate step to the flow, as you click to open the dropdown, and then have to click again before getting to the preview, and also that it makes it harder to toggle between the different screen sizes. With the modal all the controls are visible along with the preview, so we can just switch between them. We might even have custom views, such as the AMP view, render in the same iframe. I guess this could also be worked around by showing a toolbar instead of a dropdown though.
Positioning the preview over the canvas is technically possible but I don't think we should do it with a modal as that would make keyboard focus management very awkward. I also anticipate that it will be very confusing for users to see the content in the editor area and then not be able to edit it. When it appears as a modal, it's clearly a different interface so that confusion isn't possible. Fwiw, I think we should implement both this preview and the responsive editor. I still have questions about how the responsiveness would work on a mobile device, though. I left a few thoughts about that here too. |
Showing the preview as it works currently in the editing canvas seems like it might be an option that bridges what we want in the future and what we have today.
I might be misunderstanding how it works, but I do wonder if the dropdown is obvious enough. My first reaction might be "Where has the Preview button gone?" given that by default it might just say 'Full Page', and it would take some active searching from a user to locate the option. Another question is whether the Code Editor would also become one of these modes. It currently works quite similarly in that it replaces the entire editing canvas and quite considerably changes the functionality in the editor. |
Heya! I just saw this proposal and I think there's a lot that is worth discussion and exploration, and while I can add some feedback on the various points in this conversation... I think this isn't really addressing the problem stated in the issue referenced in #13203:
I'd suggest to review the approach here, in two parts:
Notice also that the above approach will sidestep the more structural point raised by Matías in the other thread, addressing the issue raised without yet having to confront two other key points:
and:
— On the specifics, I agree with @talldan:
|
Thank you for walking through the thought process. The heart is in the right place.
There are profound technical hurdles. But on the horizon are also technologies that will enable us to get almost all the way to a perfect preview:
Even with the clunkiness of editor styles today, we can get very close to a 1:1 preview; TwentyNineteen and TwentyTwenty are examples of this. It may be worth checking in with @ellatrix, she's been fighting to get the editor closer to the front-end, and is better positioned than myself to suggest how close to parity we can get.
What we want to avoid is reinforce the idea that the editor itself is not a preview, because it ideally should be, same as WordPress page builders, Squarespace, Wix and Weebly. But to Dan's point, maybe the dropdown idea needs more time in the oven. @folletto notes that it's worth addressing the editor responsiveness first; doing so would definitely help inform how to design a better preview. As an interim solution I do worry that adding this preview dialog now will just end up creating vestigial features. |
We're definitely working towards an editor that will 100% be the same as the front-end.
The markup will be much simpler in the near future. Block controls will eventually be removed from the content's DOM, and all block wrapper elements will go away. Instead, we'll render the controls in floating popovers. When all this is done, theme authors won't need to add extra editor styles. |
@folletto @jasmussen @ellatrix thanks for your feedback and additional information! Based on that, I have made a new PR to try out resizing the editing canvas: #19082 Also, thanks @talldan and @afercia for your comprehensive reviews. I'll leave this PR open for now until we reach a decision on the best way forward. |
Any GitHub issue where this is discussed and worked on? Rendering the Block controls UI far in the DOM will significantly worsen the experience for all non-mouse / non-touch users and goes against what the accessibility team always recommended. That is: render the controls in close proximity to the edited block, in a logical, predictable, order. |
@afercia I don't know of any single issue for this work, but there have been a few (already merged) PRs working towards it: There have been changes to how keyboard navigation works too: #19235 I hope that answers your question! I'm closing this PR now because the alternative approach in #19082 has been merged. |
Description
Addresses #13203
I removed the interstitial screen for now because the autosave now happens when the overlay is opened so opening new tab is quicker.
Further iterations/ things to consider:
It would be nice if initial preview size matched the size of user's device, so if post was being edited on a tablet preview would open up in tablet mode. Make sure this works when users are zoomed in on desktop.
Figure out what the best experience is to show previews for devices larger than what the user is on. If viewing on a phone, should desktop preview be really zoomed out and tiny, or have a horizontal scroll?
Should preview sizes be customisable by themes, or should we make a call on what the most standard device sizes are?
Is interstitial markup still necessary now we're rendering preview in a modal?
Anything else I've forgotten?
How has this been tested?
Tested in multiple browsers, keyboard navigation checked and also checked with VoiceOver and NVDA.
Updated unit and e2e tests.
Screenshots
Types of changes
Breaking change (fix or feature that would cause existing functionality to not work as expected)
Checklist: