Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 0 additions & 12 deletions docs/designers-developers/developers/themes/theme-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ There are a few new concepts to consider when building themes:
- **Editor Text Size Palette** - A default set of sizes is provided, but themes can register their own and optionally lock users into picking from preselected sizes.
- **Responsive Embeds** - Themes must opt-in to responsive embeds.
- **Frontend & Editor Styles** - To get the most out of blocks, theme authors will want to make sure Core styles look good and opt-in, or write their own styles to best fit their theme.
- **Dark Mode** - If a Theme is a Dark Theme with a dark background containing light text, the theme author can opt-in to the Dark Mode.
Copy link
Contributor

Choose a reason for hiding this comment

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

Love that we don't use this phrase :) It can be dark mode, or it can just be a dark background! 👌

- **Block Tools** - Themes can opt-in to several block tools like line height, custom units.
- **Core Block Patterns** - Themes can opt-out of the default block patterns.

Expand Down Expand Up @@ -316,17 +315,6 @@ add_theme_support( 'editor-styles' );

You shouldn't need to change your editor styles too much; most themes can add the snippet above and get similar results in the classic editor and inside the block editor.

### Dark backgrounds

If your editor style relies on a dark background, you can add the following to adjust the color of the UI to work on dark backgrounds:

```php
add_theme_support( 'editor-styles' );
add_theme_support( 'dark-editor-style' );
```

Note you don't need to add `add_theme_support( 'editor-styles' );` twice, but that rule does need to be present for the `dark-editor-style` rule to work.

### Enqueuing the editor style

Use the `add_editor_style` function to enqueue and load CSS on the editor screen. For the classic editor, this was the only function needed to add style to the editor. For the new block editor, you first need to `add_theme_support( 'editor-styles');` mentioned above.
Expand Down
4 changes: 3 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 47 additions & 20 deletions packages/block-editor/src/components/editor-styles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,61 @@
* External dependencies
*/
import { compact, map } from 'lodash';
import tinycolor from 'tinycolor2';

/**
* WordPress dependencies
*/
import { useEffect } from '@wordpress/element';
import { useCallback, useRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import transformStyles from '../../utils/transform-styles';

export default function useEditorStyles( ref, styles ) {
useEffect( () => {
const updatedStyles = transformStyles(
styles,
'.editor-styles-wrapper'
);

const { ownerDocument } = ref.current;
const nodes = map( compact( updatedStyles ), ( updatedCSS ) => {
const node = ownerDocument.createElement( 'style' );
node.innerHTML = updatedCSS;
ownerDocument.body.appendChild( node );

return node;
} );

return () =>
nodes.forEach( ( node ) => ownerDocument.body.removeChild( node ) );
}, [ ref, styles ] );
function syncDarkThemeBodyClassname( node ) {
const backgroundColor = window
.getComputedStyle( node, null )
.getPropertyValue( 'background-color' );

const { ownerDocument } = node;
const body = ownerDocument.getElementsByTagName( 'body' )[ 0 ];

if ( tinycolor( backgroundColor ).getLuminance() > 0.5 ) {
body.classList.remove( 'is-dark-theme' );
} else {
body.classList.add( 'is-dark-theme' );
}
}

export default function useEditorStyles( styles ) {
const nodes = useRef( [] );

return useCallback(
( node ) => {
if ( ! node ) {
nodes.current.forEach( ( styleElement ) =>
styleElement.ownerDocument.body.removeChild( styleElement )
);
return;
}

const updatedStyles = transformStyles(
styles,
'.editor-styles-wrapper'
);

const { ownerDocument } = node;
nodes.current = map( compact( updatedStyles ), ( updatedCSS ) => {
const styleElement = ownerDocument.createElement( 'style' );
styleElement.innerHTML = updatedCSS;
ownerDocument.body.appendChild( styleElement );

return styleElement;
} );

syncDarkThemeBodyClassname( node );
},
[ styles ]
);
}
1 change: 1 addition & 0 deletions packages/edit-post/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"classnames": "^2.2.5",
"lodash": "^4.17.19",
"memize": "^1.1.0",
"react-merge-refs": "^1.0.0",
"rememo": "^3.0.0"
},
"publishConfig": {
Expand Down
4 changes: 1 addition & 3 deletions packages/edit-post/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { useSelect, useDispatch } from '@wordpress/data';
import {
BlockBreadcrumb,
__experimentalLibrary as Library,
__unstableUseEditorStyles as useEditorStyles,
} from '@wordpress/block-editor';
import {
Button,
Expand Down Expand Up @@ -176,7 +175,6 @@ function Layout( { styles } ) {
const ref = useRef();

useDrop( ref );
useEditorStyles( ref, styles );
const [ inserterDialogRef, inserterDialogProps ] = useDialog( {
onClose: () => setIsInserterOpened( false ),
} );
Expand Down Expand Up @@ -260,7 +258,7 @@ function Layout( { styles } ) {
<TextEditor />
) }
{ isRichEditingEnabled && mode === 'visual' && (
<VisualEditor />
<VisualEditor styles={ styles } />
) }
<div className="edit-post-layout__metaboxes">
<MetaBoxes location="normal" />
Expand Down
17 changes: 14 additions & 3 deletions packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import mergeRefs from 'react-merge-refs';

/**
* WordPress dependencies
*/
Expand All @@ -16,9 +21,10 @@ import {
__experimentalBlockSettingsMenuFirstItem,
__experimentalUseResizeCanvas as useResizeCanvas,
__unstableUseCanvasClickRedirect as useCanvasClickRedirect,
__unstableUseEditorStyles as useEditorStyles,
} from '@wordpress/block-editor';
import { Popover } from '@wordpress/components';
import { useRef } from '@wordpress/element';
import { useRef, useCallback } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -27,7 +33,7 @@ import BlockInspectorButton from './block-inspector-button';
import { useSelect } from '@wordpress/data';
import { store as editPostStore } from '../../store';

export default function VisualEditor() {
export default function VisualEditor( { styles } ) {
const ref = useRef();
const { deviceType, isTemplateMode } = useSelect( ( select ) => {
const {
Expand Down Expand Up @@ -57,13 +63,18 @@ export default function VisualEditor() {
useClipboardHandler( ref );
useTypingObserver( ref );
useCanvasClickRedirect( ref );
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like there's a number of hooks above that can be reworked as hooks that return "refs" instead of receiving refs (outside the scope of this PR)

const editorStylesRef = useEditorStyles( styles );
const mergedRefs = useCallback( mergeRefs( [ ref, editorStylesRef ] ), [
ref,
editorStylesRef,
] );
Copy link
Member

Choose a reason for hiding this comment

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

When does styles change? How can I trigger a change?

@youknowriad We discussed this a few times that adding dependencies here will give problems when passing new functions as a callback ref.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I see your comment now #28233 (comment)
I'll rebase #27768 in a bit and see what is missing there.


return (
<div className="edit-post-visual-editor">
<VisualEditorGlobalKeyboardShortcuts />
<Popover.Slot name="block-toolbar" />
<div
ref={ ref }
ref={ mergedRefs }
className="editor-styles-wrapper"
style={ resizedCanvasStyles || desktopCanvasStyles }
>
Expand Down
11 changes: 8 additions & 3 deletions packages/edit-site/src/components/block-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ import TemplatePartConverter from '../template-part-converter';
import NavigateToLink from '../navigate-to-link';
import { SidebarInspectorFill } from '../sidebar';

function Canvas( { body, styles } ) {
function Canvas( { body } ) {
useBlockSelectionClearer( body );
useTypingObserver( body );
useEditorStyles( body, styles );

return (
<DropZoneProvider>
Expand Down Expand Up @@ -70,6 +69,8 @@ export default function BlockEditor( { setIsInserterOpen } ) {
const contentRef = useRef();

useMouseMoveTypingReset( ref );
// Ideally this should be moved to the place where the styles are applied (iframe)
const editorStylesRef = useEditorStyles( settings.styles );

// Allow scrolling "through" popovers over the canvas. This is only called
// for as long as the pointer is over a popover.
Expand Down Expand Up @@ -102,7 +103,11 @@ export default function BlockEditor( { setIsInserterOpen } ) {
<SidebarInspectorFill>
<BlockInspector />
</SidebarInspectorFill>
<div className="edit-site-visual-editor" onWheel={ onWheel }>
<div
ref={ editorStylesRef }
className="edit-site-visual-editor"
onWheel={ onWheel }
>
<Popover.Slot name="block-toolbar" />
<Iframe
style={ resizedCanvasStyles }
Expand Down
8 changes: 3 additions & 5 deletions packages/edit-widgets/src/components/layout/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
__experimentalLibrary as Library,
__unstableUseEditorStyles as useEditorStyles,
} from '@wordpress/block-editor';
import { useEffect, useRef } from '@wordpress/element';
import { useEffect } from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
import {
InterfaceSkeleton,
Expand Down Expand Up @@ -51,9 +51,7 @@ function Interface( { blockEditorSettings } ) {
).getActiveComplementaryArea( editWidgetsStore ),
isInserterOpened: !! select( editWidgetsStore ).isInserterOpened(),
} ) );
const ref = useRef();

useEditorStyles( ref, blockEditorSettings.styles );
const editorStylesRef = useEditorStyles( blockEditorSettings.styles );

// Inserter and Sidebars are mutually exclusive
useEffect( () => {
Expand All @@ -74,7 +72,7 @@ function Interface( { blockEditorSettings } ) {

return (
<InterfaceSkeleton
ref={ ref }
ref={ editorStylesRef }
labels={ interfaceLabels }
header={ <Header /> }
secondarySidebar={
Expand Down
3 changes: 2 additions & 1 deletion packages/interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"@wordpress/plugins": "file:../plugins",
"@wordpress/viewport": "file:../viewport",
"classnames": "^2.2.5",
"lodash": "^4.17.19"
"lodash": "^4.17.19",
"react-merge-refs": "^1.0.0"
},
"publishConfig": {
"access": "public"
Expand Down
13 changes: 7 additions & 6 deletions packages/interface/src/components/interface-skeleton/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
* External dependencies
*/
import classnames from 'classnames';
import mergeRefs from 'react-merge-refs';

/**
* WordPress dependencies
*/
import { forwardRef, useEffect, useRef } from '@wordpress/element';
import { forwardRef, useCallback, useEffect, useRef } from '@wordpress/element';
import { __unstableUseNavigateRegions as useNavigateRegions } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

Expand Down Expand Up @@ -40,10 +41,7 @@ function InterfaceSkeleton(
ref
) {
const fallbackRef = useRef();

ref = ref || fallbackRef;

const regionsClassName = useNavigateRegions( ref, shortcuts );
const regionsClassName = useNavigateRegions( fallbackRef, shortcuts );

useHTMLClass( 'interface-interface-skeleton__html-container' );

Expand All @@ -68,7 +66,10 @@ function InterfaceSkeleton(

return (
<div
ref={ ref }
ref={ useCallback( mergeRefs( [ ref, fallbackRef ] ), [
ref,
fallbackRef,
] ) }
className={ classnames(
className,
'interface-interface-skeleton',
Expand Down