Skip to content
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

Unable to add CSS class names to editor iframe #56831

Open
markhowellsmead opened this issue Dec 6, 2023 · 9 comments
Open

Unable to add CSS class names to editor iframe #56831

markhowellsmead opened this issue Dec 6, 2023 · 9 comments
Labels
[Package] Editor /packages/editor [Type] Bug An existing feature does not function as intended

Comments

@markhowellsmead
Copy link

Description

I'm attempting to add CSS class names to the new iframe in the editor using JavaScript. The aim is to apply a user-selected accent colour in the editor.

I've only been able to do so using an overly-complicated combination of MutationObserver (to detect when the iframe becomes available) and a setInterval to repeatedly try to apply the class name until it sticks. This seems to be unnecessarily complex. Is there a better solution?

I've tried to add the class names using the admin_body_class hook in PHP, but this doesn't feel right (as it's PHP) and it also only appears to work on the main body (which doesn't help, as it's hidden by the iframe).

Step-by-step reproduction instructions

See the code example.

Screenshots, screen recording, code snippet

https://gist.github.com/markhowellsmead/01c8c29937162e93a11e21c8209872d1

Environment info

  • WordPress 6.4
  • No plugins.

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@markhowellsmead markhowellsmead added the [Type] Bug An existing feature does not function as intended label Dec 6, 2023
@markhowellsmead
Copy link
Author

See #17854 and

// Ideally ALL classes that are added through get_body_class should
// be added in the editor too, which we'll somehow have to get from
// the server in the future (which will run the PHP filters).
setBodyClasses(
Array.from( ownerDocument.body.classList ).filter(
( name ) =>
name.startsWith( 'admin-color-' ) ||
name.startsWith( 'post-type-' ) ||
name === 'wp-embed-responsive'
.

The solution is to use the admin_body_class hook in PHP to add class names to the main body. By prefixing the class names with admin-color-, the class names will be automatically copied over to the editor iframe.

@markhowellsmead
Copy link
Author

Reopening as there should be a more logical way to do this.

@jordesign jordesign added the [Package] Editor /packages/editor label Dec 6, 2023
@ramonjd
Copy link
Member

ramonjd commented Dec 7, 2023

I'm just throwing this out there without much thought, so it might be irrelevant or useless.

The comment above says:

// Ideally ALL classes that are added through get_body_class should
// be added in the editor too, which we'll somehow have to get from
// the server in the future (which will run the PHP filters).

I wonder if it'd be okay to inject the return value of body_class() in get_block_editor_settings, whose output is rendered in the editor HTML — and therefore accessible to the block editor applications — via wp.[editSite | editPost].initializeEditor?

@colinduwe
Copy link
Contributor

Here's a proposal PR. I'd appreciate any feedback #68538

@colinduwe
Copy link
Contributor

@Mamaduka has suggested that we should not use $settings and get_block_editor_settings to add a bodyClass property to the editor. I am led to believe that is a deprecated method for transmitting data to the editor. What is the current best practice for sending a new property like bodyClasses to the editor from the server that also supports a PHP filter so extenders can then modify that property before the editor initializes?

Once the property is part of the 'core/block-editor' state, it becomes pretty easy to hook in and keep the body classes up to date.

@Mamaduka
Copy link
Member

Mamaduka commented Jan 9, 2025

Thanks, @colinduwe!

I must look up why iframe limits classes copied from the parent body. The original code was introduced in #32057, but I don't see any related comments. My current guess is to avoid leaking styles into the iframe.

Technically speaking, I don't see a difference between injecting values returned by body_class() via selector or letting iframe copy all the classes.

Code in question:

// Ideally ALL classes that are added through get_body_class should
// be added in the editor too, which we'll somehow have to get from
// the server in the future (which will run the PHP filters).
setBodyClasses(
Array.from( ownerDocument.body.classList ).filter(
( name ) =>
name.startsWith( 'admin-color-' ) ||
name.startsWith( 'post-type-' ) ||
name === 'wp-embed-responsive'

@colinduwe
Copy link
Contributor

@Mamaduka The current iframe body class implementation isn't flexible enough. It currently only runs onLoad and the classes are proscribed there in the onLoad. Instead, the bodyClasses should be a part of the blockEditorStore. Have a look here.
That way we can update the bodyClasses, for example when the user swaps templates.

Currently, body classes that we had in the TinyMCE era are not present in the ownerDocument.body.classlist. For example, page-template.

I'd also like to call attention to #17854 begun in 2019. Is there a single issue where we should be discussing this?

@markhowellsmead
Copy link
Author

Agreed that this should be subscribable. The point of the origins requirement is that the frame colour can be changed at any time when clicking on a page-level colour selector.

@Mamaduka
Copy link
Member

Is there a single issue where we should be discussing this?

Yes, it would be nice to consolidate this into a single issue. The usual policy is to use the oldest issue, reference new ones and close them.

Somewhat related: #60299 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Editor /packages/editor [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

5 participants