#63076 closed defect (bug) (fixed)
Site Editor: Remove admin bar from site preview for classic theme
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 6.8 | Priority: | normal |
Severity: | normal | Version: | |
Component: | Editor | Keywords: | has-patch has-unit-tests |
Focuses: | Cc: |
Description
Originally reported on https://github.com/WordPress/gutenberg/issues/69474
Starting with 6.8, classic themes with editor-style support or theme.json file can use StyleBook. At the same time, the root page of the site editor shows a front-end preview of the theme.
To remove the admin bar from this preview, there is JS code to remove it after the iframe content is loaded.
This JS code runs after the site is loaded, so the admin bar appears for a moment on initial load.
This issue can be solved by injecting CSS, as suggested in this Gutenberg PR, but other approaches have been proposed to use PHP hooks to not show the admin bar in the first place.
Using the show_admin_bar
hook is probably the best solution, but I'd be happy to discuss what the best approach is.
Attachments (1)
Change History (23)
This ticket was mentioned in PR #8475 on WordPress/wordpress-develop by @wildworks.
6 weeks ago
#2
- Keywords has-patch has-unit-tests added; needs-patch removed
Trac ticket: https://core.trac.wordpress.org/ticket/63076
This PR hides the admin bar if the get parameter wp_site_preview=1
is present.
This PR is needed to hide the admin bar from the classic theme site preview in the site editor.
This PR cannot yet be tested in the site editor, but can be tested on the frontend.
- Admin bar is not visible:
- Admin bar is visible:
@wildworks commented on PR #8475:
6 weeks ago
#3
I'm wondering whether the JS code that disables interactive elements should also be moved to this PR and output as an inline JS.
@presstoke commented on PR #8475:
6 weeks ago
#4
I'm wondering whether the JS code that disables interactive elements should also be moved to this PR and output as an inline JS.
I think it’s a good idea because otherwise the elements can be interactive for a moment before the load
event. Yet I also think we may want the flexibility to modify that logic without having to change core code. If so, we might make the inline JS merely `post a message` that the parent window can listen for.
@wildworks commented on PR #8475:
6 weeks ago
#5
@stokesman Thanks for the feedback!
I'm not familiar with the approach using postMessage
, so could you provide a sample implementation?
By the way, I came up with a different approach that doesn't implement any custom JS code and simply wraps the iframe
element in a Disabled
component, what do you think?
This approach is used in various places, including the pattern preview.
@wildworks commented on PR #8475:
6 weeks ago
#6
By the way, I came up with a different approach that doesn't implement any custom JS code and simply wraps the
iframe
element in aDisabled
component, what do you think?
This approach didn't work 😅 Because the <Disable>
makes the iframe content unscrollable.
@wildworks commented on PR #8475:
6 weeks ago
#7
I'm wondering whether the JS code that disables interactive elements should also be moved to this PR and output as an inline JS.
Perhaps this can be addressed in a follow-up?
@presstoke commented on PR #8475:
6 weeks ago
#8
I'm not familiar with the approach using
postMessage
, so could you provide a sample implementation?
The inline script would be something like this:
add_action( 'wp_print_footer_scripts', function() {
echo '<script>', <<<JS
if ( window.parent ) {
window.parent.postMessage( 'preview dom available' );
}
JS, '</script>';
} );
The only important part of that is that it appears after any other elements we’ll want to manipulate through DOM methods.
Then the Gutenberg side would listen for the message with something like this:
const messageEffect = useRefEffect( ( node ) => { const { defaultView } = node.ownerDocument; const onMessage = ( event ) => { if ( event.origin === siteUrl && event.data === 'preview dom available' ) { // Make interactive elements unclickable… } }; const { defaultView } = node.ownerDocument; defaultView.addEventListener( 'message', onMessage ); return () => defaultView.removeEventListener( 'message', onMessage ); }, [ siteUrl ] ); // attaching the ref callback to the iframe would follow…
That has to be done through the ref callback since it seems React doesn’t do onMessage
. I'll go ahead and post a working example diff in the thread that started this.
#9
@
5 weeks ago
Test Report
As mentioned in the PR description, this change cannot yet be tested in the Site Editor. However, I have tested it on the frontend, and it works as expected. ✅
- When accessing
/?wp_site_preview=1
, the admin bar is successfully hidden ✅ - When accessing
/
or/?wp_site_preview=2
, the admin bar remains visible as expected ✅
#10
@
5 weeks ago
Thanks @wildworks! While testing the current PR, I noticed that this not only affects the admin bar, but also other front-end code gets loaded into this preview. For example, in my testing, the Query Monitor panel is loading in the preview (cc: @johnbillion).
While the links and form elements do not seem to be functional, I suspect that things like cookie dialogues or ads might also get loaded in these previews, so we may need to find a more wholistic way of dealing with these concerns.
There may be some prior art in the way the Customizer loads front end previews that we could borrow from here.
#12
@
5 weeks ago
Query Monitor specifically hides itself from Customiser previews, the fact it doesn't appear there isn't anything to do with core behaviour. Same for a few other places such as the plugin info modals.
#13
@
5 weeks ago
Could using the IFRAME_REQUEST
constant be appropriate here? https://github.com/johnbillion/query-monitor/blob/482c5f5e2cf56abf134dcbcf396d99a2c44f5c63/dispatchers/Html.php#L873-L882
#14
@
5 weeks ago
Thanks @johnbillion. I do think setting IFRAME_REQUEST
for these previews might be exactly right. It's also worth considering adding a helper similar to is_customize_preview()
for the site editor that could be incorporated directly into is_admin_bar_showing()
rather than needing to filter the return value.
#15
@
5 weeks ago
Thanks for the feedback everyone. Setting IFRAME_REQUEST
seems to work as expected.
Note that this PR cannot yet be tested in the Site Editor. This is because Gutenberg PR (https://github.com/WordPress/gutenberg/pull/69514) was not automatically cherry-picked. I would like to address this problem separately.
@wildworks commented on PR #8475:
5 weeks ago
#16
@stokesman We found that some plugins load code into the preview. To solve this problem, it seems best to define IFRAME_REQUEST
instead of filtering show_admin_bar
hook. See trac ticket for more details.
#17
@
5 weeks ago
I prepared two PRs on Gutenberg:
- (WP6.8) Site Editor: Set IFRAME_REQUEST constant for classic theme site preview #69536
- Site Editor: Set IFRAME_REQUEST constant for classic theme site preview #69535
If using IFRAME_REQUEST
constant is an ideal approach and once committed to the core, I would like to move forward these two PRs.
@Mamaduka commented on PR #8475:
5 weeks ago
#18
The capability check makes sense, but I don't know if nonce is necessary. Unlike theme previews, this flag just renders the site front-end like iframe (which is already accessible when public); it doesn't override anything else.
@wildworks commented on PR #8475:
5 weeks ago
#19
I would be happy if this PR is committed before Beta 3. I think the following two suggestions could be considered in a follow-up:
- Use inline JS to make interactive elements unclickable instead of the
onLoad
prop of the iframe element - Use a nonce for the value of the wp_site_preview query string parameter
@peterwilsoncc commented on PR #8475:
5 weeks ago
#20
The capability check makes sense, but I don't know if nonce is necessary. Unlike theme previews, this flag just renders the site front-end like iframe (which is already accessible when public); it doesn't override anything else.
Fair point, that works for me.
#22
@
5 weeks ago
Noting for any reviewers that the use of this wp_site_preview
query param will be handled on in the @wordpress/edit-site
package after https://github.com/WordPress/gutenberg/pull/69536 is merged.
Yes indeed a PHP solution seems doable. Using a GET parameter is probably the easiest way to fix the issue with a server side solution.