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

Try/even better previews #16873

Merged
merged 83 commits into from
Aug 7, 2019
Merged
Show file tree
Hide file tree
Changes from 81 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
cdddad0
First stab at a proof of concept.
Jun 12, 2019
af648b1
Attempt to programmatically determine dest dimensions
getdave Jun 24, 2019
2cc1264
Add README stub.
jasmussen Jun 27, 2019
3ad0bc1
Updates to use default args for width and height
getdave Jul 23, 2019
3a15d94
Update class namespaces to match package
getdave Jul 23, 2019
167fadb
Add width and height as Effect Hook deps
getdave Jul 23, 2019
68fb82f
Use correct `createRef` from @wordpress/element
getdave Jul 23, 2019
2ae0507
Revert "Update class namespaces to match package"
getdave Jul 23, 2019
a920ee5
Migrate to useRef hook
getdave Jul 23, 2019
dc8738f
Adds basic unit test
getdave Jul 23, 2019
0f4f105
Refactor to avoid unecessary state and simplify implementation of sca…
getdave Jul 31, 2019
62e1109
Add some padding to the preview
getdave Jul 31, 2019
e822ae7
Refactor to utilise JS template strings
getdave Jul 31, 2019
04648b4
WIP: Adds zoom for small individual blocks
getdave Jul 31, 2019
a6f6e38
Updates to target block contents more reliably and to calc entire box…
getdave Jul 31, 2019
6f5c06f
block-preview: render scaled preview in a shadow dom
retrofox Jul 31, 2019
ff88234
try: setting styles to shadow dom elements
retrofox Jul 31, 2019
770ff2d
Revert "try: setting styles to shadow dom elements"
getdave Aug 1, 2019
a55e988
Removes attempt at auto zoom on Block contents
getdave Aug 1, 2019
7755b5b
Updates to remove scale by default in favour of opt in via prop
getdave Aug 1, 2019
94b6e3d
Adds scaleFactor prop to provide control for non dynamically scaled p…
getdave Aug 1, 2019
cffd2e8
Adjust scaleFactor for Block Styles preview
getdave Aug 1, 2019
550f99e
Fix to ensure hooks are called unconditionally to obey rules of Hooks
getdave Aug 1, 2019
c5c7079
Removes padding and border from preview on designer advice
getdave Aug 1, 2019
1489148
Only apply dimensions to preview content when dynamically scaling
getdave Aug 1, 2019
5649e51
block-preview: a different approach attempt.
retrofox Aug 2, 2019
c4d3843
Correct typo in util function name
getdave Aug 2, 2019
0bb1a30
Seek the firstChild of the Block DOM node
getdave Aug 2, 2019
8d77381
Tidy up effect timers and improve comments
getdave Aug 2, 2019
4def132
Dynamically calculate widths and offsets of preview container
getdave Aug 2, 2019
ea1d096
Updates to account for widths of all Blocks passed into to preview
getdave Aug 2, 2019
02e69f5
Revert class additions to Blocks
getdave Aug 2, 2019
52084af
Adds optional scope to DOM utils. Use to limit scope in Block width c…
getdave Aug 2, 2019
6d0a85d
Update packages/block-editor/src/components/block-preview/index.js
getdave Aug 2, 2019
3ed1f99
Allow prop based opt out from scaling
getdave Aug 2, 2019
7c86742
Fix to ensure smallest Block is found even if smaller than container
getdave Aug 2, 2019
efa2127
Remove unecessary Math.min usage
getdave Aug 2, 2019
595cf03
core/button: adjust dims of button wrapper
retrofox Aug 2, 2019
6941688
apply vertical alignment
retrofox Aug 2, 2019
d7e7b4a
set scale factor to 0.9
retrofox Aug 2, 2019
6a7c6d9
rollback testing purpose comment
retrofox Aug 2, 2019
0fab9b2
cpre/button: keep adjusting styles for preview
retrofox Aug 2, 2019
0f0d6b8
rename vars and css class names
retrofox Aug 2, 2019
d11b6ab
adjust rebase
retrofox Aug 2, 2019
d39c1d7
restore isScaled factor scale
retrofox Aug 2, 2019
55cd662
set the scale adjustment in the proper place
retrofox Aug 2, 2019
b942fb9
update README file
retrofox Aug 2, 2019
0ab14f8
core/button: tidy edit preview styles
retrofox Aug 5, 2019
c86f750
coer/button: tweak button preview
retrofox Aug 5, 2019
18ded7d
preview-block: ensure make the preview visible.
retrofox Aug 5, 2019
0b7de16
block-preview: hide dropzone
retrofox Aug 5, 2019
354d42c
core/button: adjust preview for thumb and full sizes
retrofox Aug 5, 2019
d70011f
core/button: set same width for preview
retrofox Aug 5, 2019
6089478
core/button: because it's !important
retrofox Aug 5, 2019
dbbe0bc
core/button: set nowrap button in preview
retrofox Aug 6, 2019
758468c
core/button: set nowrap onlu for button
retrofox Aug 6, 2019
2b71c32
core/quote: adjust quote size
retrofox Aug 6, 2019
65097d0
Make previews overflow to the bottom.
obenland Aug 6, 2019
8bdcb8e
Merge branch 'try/even-better-previews' of https://github.com/WordPre…
obenland Aug 6, 2019
6096c3e
Revert "core/button: set nowrap onlu for button"
obenland Aug 6, 2019
e1b9483
Fix unit test
obenland Aug 6, 2019
75d43ce
core/button: apply nowrap only to buttons
retrofox Aug 6, 2019
89f6393
Try a fixed canvas width
youknowriad Aug 6, 2019
5a1e5ad
Fix blocks editor styles
youknowriad Aug 6, 2019
3d47db8
core/button: centering preview
retrofox Aug 6, 2019
27b430f
core/button: adjust only into teh styles preview
retrofox Aug 6, 2019
d21df0b
block-preview: remove scaleAdjustment property
retrofox Aug 6, 2019
d8212f2
block-preview: hide inserte element in preview
retrofox Aug 6, 2019
2b1a111
block-preview: just pick up the first block to scale
retrofox Aug 6, 2019
e50cfcb
block-preview: fix set tall class. X position (wip)
retrofox Aug 6, 2019
5208a03
popover: remove commented lines
retrofox Aug 6, 2019
029e131
Refactor the preview
youknowriad Aug 7, 2019
72c5027
Remove debug code
youknowriad Aug 7, 2019
a4958f3
simplify preview resets
youknowriad Aug 7, 2019
22b4d84
Fix the preview recomputing
youknowriad Aug 7, 2019
f218f64
Vertical alignining small blocks
youknowriad Aug 7, 2019
835c4ba
block-editor: restore viewportWidth as a property
retrofox Aug 7, 2019
3fe45d7
Update Readme docs
obenland Aug 7, 2019
91f142f
Remove tests for now
obenland Aug 7, 2019
33fb2d9
block-preview: simplify comparision
retrofox Aug 7, 2019
527111e
Merge branch 'try/even-better-previews' of github.com:WordPress/guten…
retrofox Aug 7, 2019
6f29c27
Remove readme updates that break tests
obenland Aug 7, 2019
a3bb473
Update docs properly.
obenland Aug 7, 2019
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
9 changes: 7 additions & 2 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,21 @@ Undocumented declaration.

<a name="BlockPreview" href="#BlockPreview">#</a> **BlockPreview**

BlockPreview renders a preview given an array of blocks.
BlockPreview renders a preview of a block or array of blocks.

_Parameters_

- _props_ `Object`: Component props.
- _blocks_ `Array|Object`: A block instance (object) or an array of blocks to be previewed.
- _viewportWidth_ `Int`: Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview. Default: 700.

_Returns_

- `WPElement`: Rendered element.

_Related_

- <https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/block-preview/README.md>

<a name="BlockSelectionClearer" href="#BlockSelectionClearer">#</a> **BlockSelectionClearer**

Undocumented declaration.
Expand Down
14 changes: 8 additions & 6 deletions packages/block-editor/src/components/block-preview/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ Render the component passing in the required props:
```jsx
<BlockPreview
blocks={ blocks }
isScaled={ false }
viewportWidth={ 800 }
/>
```

## Props

### `blocks`
* **Type:** `array|object`
* **Type:** `Array|Object`
* **Default:** `undefined`

A block instance (object) or a blocks array you would like to render a preview.

### `isScaled`
* **Type:** `Boolean`
* **Default:** `false`
### `viewportWidth`
* **Type:** `Int`
* **Default:** `700`

Use this if you need to render previews in smaller areas, like block thumbnails.
Width of the preview container in pixels. Controls at what size the blocks will be rendered inside the preview.

`viewportWidth` can be used to simulate how blocks look on different device sizes or to make sure make sure multiple previews will be rendered with the same scale, regardless of their content.
123 changes: 102 additions & 21 deletions packages/block-editor/src/components/block-preview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,119 @@ import classnames from 'classnames';
*/
import { Disabled } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { useLayoutEffect, useState, useRef, useReducer, useMemo } from '@wordpress/element';

/**
* Internal dependencies
*/
import BlockEditorProvider from '../provider';
import BlockList from '../block-list';
import { getBlockPreviewContainerDOMNode } from '../../utils/dom';

export function BlockPreview( { blocks, settings, className, isScaled } ) {
if ( ! blocks ) {
function ScaledBlockPreview( { blocks, viewportWidth } ) {
const previewRef = useRef( null );

const [ isTallPreview, setIsTallPreview ] = useState( false );
const [ isReady, setIsReady ] = useState( false );
const [ previewScale, setPreviewScale ] = useState( 1 );
const [ { x, y }, setPosition ] = useState( { x: 0, y: 0 } );

// Dynamically calculate the scale factor
useLayoutEffect( () => {
// Timer - required to account for async render of `BlockEditorProvider`
const timerId = setTimeout( () => {
const containerElement = previewRef.current;
if ( ! containerElement ) {
return;
}

// If we're previewing a single block, scale the preview to fit it.
if ( blocks.length === 1 ) {
const block = blocks[ 0 ];
const previewElement = getBlockPreviewContainerDOMNode( block.clientId, containerElement );
if ( ! previewElement ) {
return;
}

const containerElementRect = containerElement.getBoundingClientRect();
const scaledElementRect = previewElement.getBoundingClientRect();

const scale = containerElementRect.width / scaledElementRect.width || 1;
const offsetX = scaledElementRect.left - containerElementRect.left;
const offsetY = ( containerElementRect.height > scaledElementRect.height * scale ) ?
( containerElementRect.height - ( scaledElementRect.height * scale ) ) / 2 : 0;

setIsTallPreview( scaledElementRect.height * scale > containerElementRect.height );
setPreviewScale( scale );
setPosition( { x: offsetX * scale, y: offsetY } );

// Hack: we need to reset the scaled elements margins
previewElement.style.marginTop = '0';
} else {
const containerElementRect = containerElement.getBoundingClientRect();
setPreviewScale( containerElementRect.width / viewportWidth );
setIsTallPreview( true );
}

setIsReady( true );
}, 100 );

// Cleanup
return () => {
if ( timerId ) {
window.clearTimeout( timerId );
}
};
}, [] );

if ( ! blocks || blocks.length === 0 ) {
return null;
}

const previewStyles = {
transform: `scale(${ previewScale })`,
visibility: isReady ? 'visible' : 'hidden',
left: -x,
top: y,
width: viewportWidth,
};

const contentClassNames = classnames( 'block-editor-block-preview__content editor-styles-wrapper', {
'is-tall-preview': isTallPreview,
'is-ready': isReady,
} );

return (
<Disabled
aria-hidden
className={
classnames(
className,
'block-editor-block-preview',
'editor-styles-wrapper',
{
'is-scaled': isScaled,
}
)
}
<div ref={ previewRef } className="block-editor-block-preview__container" aria-hidden>
<Disabled style={ previewStyles } className={ contentClassNames }>
<BlockList />
</Disabled>
</div>
);
}

export function BlockPreview( { blocks, viewportWidth = 700, settings } ) {
const renderedBlocks = useMemo( () => castArray( blocks ), [ blocks ] );
const [ recompute, triggerRecompute ] = useReducer( ( state ) => state + 1, 0 );
useLayoutEffect( triggerRecompute, [ blocks ] );
return (
<BlockEditorProvider
value={ renderedBlocks }
settings={ settings }
>
<BlockEditorProvider
value={ castArray( blocks ) }
settings={ settings }
>
<BlockList renderAppender={ false } />
</BlockEditorProvider>
</Disabled>
{
/*
* The key prop is used to force recomputing the preview
* by remounting the component, ScaledBlockPreview is not meant to
* be rerendered.
*/
}
<ScaledBlockPreview
key={ recompute }
blocks={ renderedBlocks }
viewportWidth={ viewportWidth }
/>
</BlockEditorProvider>
);
}

Expand Down
77 changes: 65 additions & 12 deletions packages/block-editor/src/components/block-preview/style.scss
Original file line number Diff line number Diff line change
@@ -1,34 +1,87 @@
.block-editor-block-preview {
// This is the preview that shows up to the right of the thumbnail when hovering.
.block-editor-block-switcher__preview {
padding: $block-padding;
font-family: $editor-font;
overflow: hidden;
width: 100%;
pointer-events: none;
display: none;

@include break-medium {
display: block;
}

.block-editor-block-preview__content {
font-family: $editor-font;

> div {
font-family: $editor-font;
}

&:not(.is-tall-preview) {
// Vertical alignment.
margin-top: 50%;
}
}

.block-editor-block-preview__title {
margin-bottom: 10px;
color: $dark-gray-300;
}
}

// These rules ensure the preview scales smoothly regardless of the container size.
.block-editor-block-preview__container {
// In the component, a top padding is provided as an inline style to provid an aspect-ratio.
// This positioning enables the content to sit on top of that padding to fit.
position: relative;

// The preview component measures the pixel width of this item, so as to calculate the scale factor.
// But without this baseline width, it collapses to 0.
width: 100%;
}

.block-editor-block-preview__content {
// This element receives inline styles for width, height, and transform-scale.
// Those inline styles are calculated to fit a perfect thumbnail.

// Position above the padding.
position: absolute;

// Vertical alignment. It works with the transform: translate(-50%, -50%)`,
top: 0;
left: 0;

// Important to set the origin.
transform-origin: top left;

// Resetting paddings, margins, and other.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if it was introduced here, but while the preview shows well in most contexts, in the block transform menu, I see horizontal scroll:

image

From some inspection, it seems to be because of the negative offsets from pseudo-elements surrounding the block in the block list:

left: -$block-padding * 2;
position: absolute;
right: -$block-padding * 2;

I'd think that ideally, we could have some concept of a "read-only" block list rendering, since these previews have no use for all of the extra control elements of a block.

But I comment here because it seems like you had to deal with this anyways. Maybe something we can be addressing with overflow: hidden ?

(Aside: I find it helps to use the "Show Scroll Bars: Always" option in macOS, to help discover these sorts of issues: https://cloudup.com/cqF641QROEe)

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't have a good answer here, This was a very complex PR and I know that it can be tricky to get right on all situations.

read-only mode or preview mode

I see this mentioned over and over and I think we'll probably need that for several things (previews and also some special FSE mode where some blocks are "enabled" while others are not)

negative left/right

This looks specific to the hover and selected styles, so yeah if we can move this out of the flow somehow (overflow: hidden maybe but I'd be very cautious), it could work or just remove the selected/hover styles entirely in preview.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👋 Honestly, I don't remember exactly the purposes of introducing these resets here. As Riad mentioned, it's a very complex PR and any modification can affect other instances where the preview is being used. AMost of these resets are usually an attempt to make cross-theme support.

read-only, view, etc. have been talked as well. I thought that even we could remove all elements which are not needed just for the preview (appender, drop-zone, etc) in order to make the preview process more efficient.

text-align: initial;
margin: 0;
overflow: visible;
min-height: auto;

// Resetting the block editor paddings and margins
.block-editor-block-list__layout,
.block-editor-block-list__block {
padding: 0;
}

.editor-block-list__block-edit [data-block] {
margin-top: 0;
margin: 0;
}

> div section {
height: auto;
}

> .reusable-block-indicator {
display: none;
&.is-tall-preview {
top: 4px;
}

.block-editor-block-list__insertion-point,
.block-editor-block-drop-zone,
.reusable-block-indicator,
.block-list-appender {
display: none;
}

&.is-scaled {
> div {
transform: scale(0.9);
transform-origin: center top;
}
}
}
7 changes: 1 addition & 6 deletions packages/block-editor/src/components/block-styles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,7 @@ function BlockStyles( {
aria-label={ style.label || style.name }
>
<div className="editor-block-styles__item-preview block-editor-block-styles__item-preview">
<BlockPreview
isScaled
blocks={ cloneBlock( block, {
className: styleClassName,
} ) }
/>
<BlockPreview blocks={ cloneBlock( block, { className: styleClassName } ) } />
</div>
<div className="editor-block-styles__item-label block-editor-block-styles__item-label">
{ style.label || style.name }
Expand Down
24 changes: 9 additions & 15 deletions packages/block-editor/src/components/block-styles/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
overflow: hidden;
border-radius: $radius-round-rectangle;
padding: $grid-size-small * 1.5;
padding-top: calc(50% * 0.75 - #{ $grid-size-small } * 1.5);
obenland marked this conversation as resolved.
Show resolved Hide resolved

&:focus {
@include block-style__focus();
Expand All @@ -30,28 +31,21 @@
}
}

// Show a little preview thumbnail for style variations.
.block-editor-block-styles__item-preview {
outline: $border-width solid transparent; // Shown in Windows High Contrast mode.
border: 1px solid rgba($dark-gray-900, 0.2);
overflow: hidden;
padding: 0;
text-align: initial;
border: $border-width solid rgba($dark-gray-900, 0.2);
border-radius: $radius-round-rectangle;
display: flex;
height: 60px;
overflow: hidden;
background: $white;
padding-top: 75%;
margin-top: -75%;

// Actual preview contents.
.block-editor-block-preview__content {
transform: scale(0.7);
transform-origin: center center;
width: 100%;

// Unset some of the styles that might be inherited from the editor style.
margin: 0;
padding: 0;
overflow: visible;
min-height: auto;
.block-editor-block-preview__container {
padding-top: 0;
margin-top: -75%;
}
}

Expand Down
15 changes: 13 additions & 2 deletions packages/block-editor/src/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@
* in cases where isolated behaviors need remote access to a block node.
*
* @param {string} clientId Block client ID.
* @param {Element} scope an optional DOM Element to which the selector should be scoped
*
* @return {Element} Block DOM node.
*/
export function getBlockDOMNode( clientId ) {
return document.querySelector( '[data-block="' + clientId + '"]' );
export function getBlockDOMNode( clientId, scope = document ) {
return scope.querySelector( '[data-block="' + clientId + '"]' );
}

export function getBlockPreviewContainerDOMNode( clientId, scope ) {
const domNode = getBlockDOMNode( clientId, scope );

if ( ! domNode ) {
return;
}

return domNode.firstChild || domNode;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/button/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ import {
const { getComputedStyle } = window;

const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => {
if ( node ) {
node.classList.add( 'wp-block-button-wrapper' );
}

const { textColor, backgroundColor } = ownProps;
const backgroundColorValue = backgroundColor && backgroundColor.color;
const textColorValue = textColor && textColor.color;
Expand Down
Loading