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

Duotone: Pass filters to the Post Editor #49239

Merged
merged 25 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a98c60b
Duotone: Pass filters to the Post Editor
scruffian Mar 21, 2023
32355ba
remove whitespace change
scruffian Mar 21, 2023
7810e0a
remove whitespace change
scruffian Mar 21, 2023
0e6304e
Move SVGs into styles prop for EditorStyles
Mar 22, 2023
690cca4
Handle duotone presets settings in add_editor_settings
Mar 22, 2023
5a99e30
Fix php lint
Mar 22, 2023
8f9541e
Add a check for $settings['styles'] to be safe
Mar 22, 2023
2b8484b
Use SVG component instead of svg
Mar 22, 2023
6a19107
Use === instead of ==
Mar 22, 2023
6e0d5c0
output the rules for all global styles not just the used ones
scruffian Mar 22, 2023
44e46c8
Block Previews: Fix Duotone in Block Previews (#49290)
scruffian Mar 23, 2023
0b4dfe7
Rename duotone css and svg variables
Mar 23, 2023
9f84812
Move styles to the document.head with a portal
Mar 23, 2023
57471f9
Revert "Move styles to the document.head with a portal"
Mar 23, 2023
05121a2
Move EditorStyles to body for EditorCanvas iframe
Mar 23, 2023
20a6fde
Move EditorStyles to body for the global styles StylesPreview iframe
Mar 23, 2023
9b4e96c
Move EditorStyles to body for the StyleBook iframe
Mar 23, 2023
4fb10d4
Refactor editorStyles for EditorCanvas
Mar 23, 2023
5fe3835
Directly test for css in the transformStyles call since that is what …
Mar 23, 2023
32f2147
?.length is unnecessary
Mar 23, 2023
3688db6
Explain settings better
Mar 23, 2023
f426d62
Partially revert "Refactor editorStyles for EditorCanvas"
Mar 23, 2023
0dabaf4
Update useGlobalStylesOutput to use SVGs strings in styles instead of…
Mar 24, 2023
6bc19a9
Add missing __unstableType for svgs
Mar 24, 2023
a0be2bf
Add comment about required JS changes for __unstableType in PHP
Mar 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/block-supports/duotone.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,4 @@ function gutenberg_render_duotone_support( $block_content, $block ) {
add_filter( 'render_block', array( 'WP_Duotone_Gutenberg', 'render_duotone_support' ), 10, 2 );
add_action( 'wp_enqueue_scripts', array( 'WP_Duotone_Gutenberg', 'output_global_styles' ), 11 );
add_action( 'wp_footer', array( 'WP_Duotone_Gutenberg', 'output_footer_assets' ), 10 );
add_filter( 'block_editor_settings_all', array( 'WP_Duotone_Gutenberg', 'add_editor_settings' ), 10 );
38 changes: 38 additions & 0 deletions lib/class-wp-duotone-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,44 @@ public static function output_footer_assets() {
}
}

/**
* Adds the duotone SVGs and CSS custom properties to the editor settings so
* they can be pulled in by the EditorStyles component in JS and rendered in
* the post editor.
*
* @param array $settings The block editor settings from the `block_editor_settings_all` filter.
* @return array The editor settings with duotone SVGs and CSS custom properties.
*/
public static function add_editor_settings( $settings ) {
$duotone_svgs = '';
$duotone_css = 'body{';
foreach ( self::$global_styles_presets as $filter_data ) {
$duotone_svgs .= gutenberg_get_duotone_filter_svg( $filter_data );
$duotone_css .= self::get_css_custom_property_declaration( $filter_data );
}
$duotone_css .= '}';

if ( ! isset( $settings['styles'] ) ) {
$settings['styles'] = array();
}

$settings['styles'][] = array(
'assets' => $duotone_svgs,
'__unstableType' => 'svgs',
'isGlobalStyles' => false,
);

$settings['styles'][] = array(
'css' => $duotone_css,
// This must be set and must be something other than 'theme' or they will be stripped out in the post editor <Editor> component.
'__unstableType' => 'presets',
// These styles are no longer generated by global styles, so this must be false or they will be stripped out in gutenberg_get_block_editor_settings.
'isGlobalStyles' => false,
);

return $settings;
}

/**
* Appends the used global style duotone filter CSS Vars to the inline global styles CSS
*/
Expand Down
19 changes: 2 additions & 17 deletions packages/block-editor/src/components/block-preview/auto.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { Disabled } from '@wordpress/components';
import BlockList from '../block-list';
import Iframe from '../iframe';
import EditorStyles from '../editor-styles';
import { __unstablePresetDuotoneFilter as PresetDuotoneFilter } from '../../components/duotone';
import { store } from '../../store';

// This is used to avoid rendering the block list if the sizes change.
Expand All @@ -32,11 +31,10 @@ function ScaledBlockPreview( {

const [ contentResizeListener, { height: contentHeight } ] =
useResizeObserver();
const { styles, duotone } = useSelect( ( select ) => {
const { styles } = useSelect( ( select ) => {
const settings = select( store ).getSettings();
return {
styles: settings.styles,
duotone: settings.__experimentalFeatures?.color?.duotone,
};
}, [] );

Expand All @@ -56,10 +54,6 @@ function ScaledBlockPreview( {
return styles;
}, [ styles, additionalStyles ] );

const svgFilters = useMemo( () => {
return [ ...( duotone?.default ?? [] ), ...( duotone?.theme ?? [] ) ];
}, [ duotone ] );

// Initialize on render instead of module top level, to avoid circular dependency issues.
MemoizedBlockList = MemoizedBlockList || pure( BlockList );

Expand All @@ -76,7 +70,6 @@ function ScaledBlockPreview( {
} }
>
<Iframe
head={ <EditorStyles styles={ editorStyles } /> }
contentRef={ useRefEffect( ( bodyElement ) => {
const {
ownerDocument: { documentElement },
Expand Down Expand Up @@ -108,16 +101,8 @@ function ScaledBlockPreview( {
: minHeight,
} }
>
<EditorStyles styles={ editorStyles } />
{ contentResizeListener }
{
/* Filters need to be rendered before children to avoid Safari rendering issues. */
svgFilters.map( ( preset ) => (
<PresetDuotoneFilter
preset={ preset }
key={ preset.slug }
/>
) )
}
<MemoizedBlockList renderAppender={ false } />
</Iframe>
</Disabled>
Expand Down
30 changes: 29 additions & 1 deletion packages/block-editor/src/components/editor-styles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import a11yPlugin from 'colord/plugins/a11y';
/**
* WordPress dependencies
*/
import { SVG } from '@wordpress/components';
import { useCallback, useMemo } from '@wordpress/element';

/**
Expand Down Expand Up @@ -68,7 +69,20 @@ function useDarkThemeBodyClassName( styles ) {

export default function EditorStyles( { styles } ) {
ajlende marked this conversation as resolved.
Show resolved Hide resolved
const transformedStyles = useMemo(
() => transformStyles( styles, EDITOR_STYLES_SELECTOR ),
() =>
transformStyles(
styles.filter( ( style ) => style?.css ),
EDITOR_STYLES_SELECTOR
),
[ styles ]
);

const transformedSvgs = useMemo(
() =>
styles
.filter( ( style ) => style.__unstableType === 'svgs' )
ajlende marked this conversation as resolved.
Show resolved Hide resolved
.map( ( style ) => style.assets )
.join( '' ),
[ styles ]
);

Expand All @@ -80,6 +94,20 @@ export default function EditorStyles( { styles } ) {
{ transformedStyles.map( ( css, index ) => (
<style key={ index }>{ css }</style>
) ) }
<SVG
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 0 0"
width="0"
height="0"
role="none"
style={ {
visibility: 'hidden',
position: 'absolute',
left: '-9999px',
overflow: 'hidden',
} }
dangerouslySetInnerHTML={ { __html: transformedSvgs } }
/>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
store as blocksStore,
} from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import { useContext, useMemo } from '@wordpress/element';
import { renderToString, useContext, useMemo } from '@wordpress/element';
import { getCSSRules } from '@wordpress/style-engine';

/**
Expand Down Expand Up @@ -144,13 +144,16 @@ function getPresetsSvgFilters( blockPresets = {} ) {
return [ 'default', 'theme' ]
.filter( ( origin ) => presetByOrigin[ origin ] )
.flatMap( ( origin ) =>
presetByOrigin[ origin ].map( ( preset ) => (
<PresetDuotoneFilter
preset={ preset }
key={ preset.slug }
/>
) )
);
presetByOrigin[ origin ].map( ( preset ) =>
renderToString(
<PresetDuotoneFilter
preset={ preset }
key={ preset.slug }
/>
ajlende marked this conversation as resolved.
Show resolved Hide resolved
)
)
)
.join( '' );
} );
}

Expand Down Expand Up @@ -1049,9 +1052,9 @@ export function useGlobalStylesOutput() {
hasFallbackGapSupport,
disableLayoutStyles
);
const svgs = toSvgFilters( mergedConfig, blockSelectors );
ajlende marked this conversation as resolved.
Show resolved Hide resolved

const filters = toSvgFilters( mergedConfig, blockSelectors );
const stylesheets = [
const styles = [
{
css: customProperties,
isGlobalStyles: true,
Expand All @@ -1065,6 +1068,10 @@ export function useGlobalStylesOutput() {
css: mergedConfig.styles.css ?? '',
isGlobalStyles: true,
},
{
assets: svgs,
isGlobalStyles: true,
},
];

// Loop through the blocks to check if there are custom CSS values.
Expand All @@ -1073,7 +1080,7 @@ export function useGlobalStylesOutput() {
getBlockTypes().forEach( ( blockType ) => {
if ( mergedConfig.styles.blocks[ blockType.name ]?.css ) {
const selector = blockSelectors[ blockType.name ].selector;
stylesheets.push( {
styles.push( {
css: processCSSNesting(
mergedConfig.styles.blocks[ blockType.name ]?.css,
selector
Expand All @@ -1083,7 +1090,7 @@ export function useGlobalStylesOutput() {
}
} );

return [ stylesheets, mergedConfig.settings, filters ];
return [ styles, mergedConfig.settings ];
}, [
hasBlockGapSupport,
hasFallbackGapSupport,
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ function MaybeIframe( { children, contentRef, shouldIframe, styles, style } ) {

return (
<Iframe
head={ <EditorStyles styles={ styles } /> }
ajlende marked this conversation as resolved.
Show resolved Hide resolved
ref={ ref }
contentRef={ contentRef }
style={ { width: '100%', height: '100%', display: 'block' } }
name="editor-canvas"
>
<EditorStyles styles={ styles } />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding non styles to EditorStyles and then moving everything in the body? Why not add SVGs separately here?

Also what if we move this to the iframe component in the block-editor package? Wouldn't it then work automatically in all editors and allow us to remove a bunch of duplication?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my suggestion and for me these SVG filters are styles. They're just not "CSS styles". Basically if you check the code base, in all the places we use EditorStyles or generate the "styles" key we need to do the same for the "filters". It's an indication that they are the same thing, it's just the technology that changes.

The move to body is necessary because the filters can't be inserted into head in HTML. I suggest that we could potentially use ownerDocument to solve that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you could use a portal. Maybe we should build EditorStyles into the Iframe component as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should build EditorStyles into the Iframe component as well?

@ellatrix Is it okay if that's handled in a follow-up? Or do you think it's important for this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you could use a portal.

I tried doing this, but it causes a flash of unstyled content while React is grabbing the ref to use for the portal. Is there any reason we can't have the <style> elements in the <body> of the document?

Copy link
Contributor

@ajlende ajlende Mar 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what if we move this to the iframe component in the block-editor package? Wouldn't it then work automatically in all editors and allow us to remove a bunch of duplication?

EditorStyles aren't used exclusively in the Iframe component. We'd want them to work in those cases too.

{ children }
</Iframe>
);
Expand Down
36 changes: 13 additions & 23 deletions packages/edit-site/src/components/block-editor/editor-canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,13 @@ function EditorCanvas( { enableResizing, settings, children, ...props } ) {
const { setCanvasMode } = unlock( useDispatch( editSiteStore ) );
const deviceStyles = useResizeCanvas( deviceType );
const mouseMoveTypingRef = useMouseMoveTypingReset();

return (
<Iframe
expand={ isZoomOutMode }
scale={ ( isZoomOutMode && 0.45 ) || undefined }
frameSize={ isZoomOutMode ? 100 : undefined }
style={ enableResizing ? {} : deviceStyles }
head={
<>
<EditorStyles styles={ settings.styles } />
<style>{
// Forming a "block formatting context" to prevent margin collapsing.
// @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
`.is-root-container { display: flow-root; }
body { position: relative;
${ canvasMode === 'view' ? 'cursor: pointer;' : '' }}}`
}</style>
{ enableResizing && (
<style>
{
// Some themes will have `min-height: 100vh` for the root container,
// which isn't a requirement in auto resize mode.
`.is-root-container { min-height: 0 !important; }`
}
</style>
) }
</>
}
ref={ mouseMoveTypingRef }
name="editor-canvas"
className="edit-site-visual-editor__editor-canvas"
Expand All @@ -70,8 +50,18 @@ function EditorCanvas( { enableResizing, settings, children, ...props } ) {
}
readonly={ canvasMode === 'view' }
>
{ /* Filters need to be rendered before children to avoid Safari rendering issues. */ }
{ settings.svgFilters }
<EditorStyles styles={ settings.styles } />
<style>{
// Forming a "block formatting context" to prevent margin collapsing.
// @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
`.is-root-container{display:flow-root;${
// Some themes will have `min-height: 100vh` for the root container,
// which isn't a requirement in auto resize mode.
enableResizing ? 'min-height:0!important;' : ''
}}body{position:relative; ${
canvasMode === 'view' ? 'cursor: pointer;' : ''
}}}`
}</style>
{ children }
</Iframe>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { unlock } from '../../private-apis';
const { useGlobalStylesOutput } = unlock( blockEditorPrivateApis );

function useGlobalStylesRenderer() {
const [ styles, settings, svgFilters ] = useGlobalStylesOutput();
const [ styles, settings ] = useGlobalStylesOutput();
const { getSettings } = useSelect( editSiteStore );
const { updateSettings } = useDispatch( editSiteStore );

Expand All @@ -30,7 +30,6 @@ function useGlobalStylesRenderer() {
updateSettings( {
...currentStoreSettings,
styles: [ ...nonGlobalStyles, ...styles ],
svgFilters,
__experimentalFeatures: settings,
} );
}, [ styles, settings ] );
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/global-styles/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ const StylesPreview = ( { label, isFocused, withHoverView } ) => {
{ isReady && (
<Iframe
className="edit-site-global-styles-preview__iframe"
head={ <EditorStyles styles={ editorStyles } /> }
style={ {
height: normalizedHeight * ratio,
} }
onMouseEnter={ () => setIsHovered( true ) }
onMouseLeave={ () => setIsHovered( false ) }
tabIndex={ -1 }
>
<EditorStyles styles={ editorStyles } />
<motion.div
style={ {
height: normalizedHeight * ratio,
Expand Down
26 changes: 10 additions & 16 deletions packages/edit-site/src/components/style-book/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,25 +247,19 @@ function StyleBook( { isSelected, onSelect, onClose } ) {
{ ( tab ) => (
<Iframe
className="edit-site-style-book__iframe"
head={
<>
<EditorStyles styles={ settings.styles } />
<style>
{
// Forming a "block formatting context" to prevent margin collapsing.
// @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
`.is-root-container { display: flow-root; }
body { position: relative; padding: 32px !important; }` +
STYLE_BOOK_IFRAME_STYLES
}
</style>
</>
}
name="style-book-canvas"
tabIndex={ 0 }
>
{ /* Filters need to be rendered before children to avoid Safari rendering issues. */ }
{ settings.svgFilters }
<EditorStyles styles={ settings.styles } />
<style>
{
// Forming a "block formatting context" to prevent margin collapsing.
// @see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context
`.is-root-container { display: flow-root; }
body { position: relative; padding: 32px !important; }` +
STYLE_BOOK_IFRAME_STYLES
}
</style>
<Examples
className={ classnames(
'edit-site-style-book__examples',
Expand Down