Skip to content

Commit

Permalink
Block theme: Add drag handles to resize pattern preview (#650)
Browse files Browse the repository at this point in the history
* Block theme: Add drag handles to resize pattern preview

* Remove throttle and use separate `dragPos` variable

This helps prevent the cursor from coming out of sync with the drag handle

* Reduce max scaling width to 1400

Still larger than the 1200 preview width, but more realistic than 2400

* Run the resize handler when the drag change happens

* Add a class while dragging, only block pointer events then

* Ensure the resize happens on toggles

* Update styles

* Hide text so it's only read when on the relevant button

* Hide drag buttons on small tablet/phone sizes
  • Loading branch information
ryelle authored Apr 11, 2024
1 parent 81c9db6 commit 867542d
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
$p->remove_attribute( 'data-wp-context' );
$content = $p->get_updated_html();

$html_id = wp_unique_id( 'pattern-preview-help-' );

?>
<div
<?php echo get_block_wrapper_attributes(); // phpcs:ignore ?>
data-wp-interactive="wporg/patterns/preview"
data-wp-context="<?php echo esc_attr( $encoded_state ); ?>"
data-wp-class--is-mobile-view="state.isWidthNarrow"
data-wp-class--is-dragging="state.isDrag"
data-wp-on-window--mousemove="actions.onDrag"
data-wp-on-window--mouseup="actions.onDragEnd"
>
<section class="wporg-pattern-view-control__controls wp-block-buttons" aria-label="<?php esc_attr_e( 'Preview width', 'wporg-patterns' ); ?>">
<div class="wp-block-button is-style-toggle is-small">
Expand Down Expand Up @@ -66,8 +71,37 @@ class="wp-block-button__link wp-element-button"
</div>
</section>

<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content from child blocks.
echo $content;
?>
<div class="wporg-pattern-preview__drag-container">
<div class="wporg-pattern-preview__drag-handle">
<button
class="wporg-pattern-view-control__drag-handle is-left"
aria-label="<?php esc_attr( 'Drag to resize', 'wporg-patterns' ); ?>"
aria-describedby="<?php echo esc_attr( $html_id ); ?>-left"
data-direction="left"
data-wp-on--keydown="actions.onLeftKeyDown"
data-wp-on--mousedown="actions.onDragStart"
></button>
</div>
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content from child blocks.
echo $content;
?>
<div class="wporg-pattern-preview__drag-handle">
<button
class="wporg-pattern-view-control__drag-handle is-right"
aria-label="<?php esc_attr( 'Drag to resize', 'wporg-patterns' ); ?>"
aria-describedby="<?php echo esc_attr( $html_id ); ?>-right"
data-direction="right"
data-wp-on--keydown="actions.onRightKeyDown"
data-wp-on--mousedown="actions.onDragStart"
></button>
</div>
</div>

<span id="<?php echo esc_attr( $html_id ); ?>-left" hidden>
<?php esc_attr_e( 'Drag or use arrow keys to resize the pattern preview. Left to make larger, right to make smaller.', 'wporg-patterns' ); ?>
</span>
<span id="<?php echo esc_attr( $html_id ); ?>-right" hidden>
<?php esc_attr_e( 'Drag or use arrow keys to resize the pattern preview. Right to make larger, left to make smaller.', 'wporg-patterns' ); ?>
</span>
</div>
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use "sass:math";

.wp-block-wporg-pattern-view-control {
position: relative;
width: 100%;
Expand All @@ -7,7 +9,7 @@
.wp-block-wporg-pattern-preview {
box-sizing: content-box;
border: none;
width: calc(100% - var(--wp--custom--wporg-pattern-preview--border--width) * 2);
width: auto;
padding: var(--wp--custom--wporg-pattern-preview--border--width);
display: flex;
justify-content: center;
Expand All @@ -24,12 +26,11 @@
margin: 0;
display: block;
border-radius: var(--wp--custom--wporg-pattern-preview--border--radius);
pointer-events: none;
}
}

&.is-mobile-view .wp-block-wporg-pattern-preview__container > iframe {
pointer-events: auto;
&.is-dragging .wp-block-wporg-pattern-preview__container > iframe {
pointer-events: none;
}
}

Expand All @@ -54,3 +55,59 @@
}
}
}

.wporg-pattern-preview__drag-container {
display: flex;
align-items: center;
justify-content: center;
}

.wporg-pattern-view-control__drag-handle {
$height: 52px;
$width: 4px;
height: $height;
width: $width;
box-sizing: content-box;
padding: 0;
z-index: 2;
border: none;
background-color: transparent;
cursor: col-resize;

&::before {
content: "";
display: block;
height: $height;
width: $width;
border-radius: math.div($width, 2);
background: var(--wp--preset--color--charcoal-5);
}

&:hover::before {
background: var(--wp--preset--color--charcoal-4);
}

&:focus {
box-shadow: none;

&::before {
background: var(--wp--preset--color--charcoal-4);
}
}

&:focus-visible::before {
box-shadow: 0 0 0 1.5px var(--wp--custom--link--color--text);
}

&.is-right {
padding-left: 10px;
}

&.is-left {
padding-right: 10px;
}

@media (max-width: 782px) {
display: none;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { getContext, getElement, store } from '@wordpress/interactivity';
import { getContext, getElement, store, withScope } from '@wordpress/interactivity';

const { actions, state } = store( 'wporg/patterns/preview', {
state: {
Expand All @@ -23,20 +23,80 @@ const { actions, state } = store( 'wporg/patterns/preview', {
return `scale(${ state.scale })`;
},
get isWidthWide() {
return 1200 === getContext().previewWidth;
return getContext().previewWidth >= 1200;
},
get isWidthMedium() {
return 800 === getContext().previewWidth;
return getContext().previewWidth >= 800 && getContext().previewWidth < 1200;
},
get isWidthNarrow() {
return 400 === getContext().previewWidth;
return getContext().previewWidth < 800;
},
dragPos: 0,
isDrag: false,
throttleTimeout: 0,
prevX: 0,
direction: '',
},
actions: {
updatePreviewWidth( newWidth ) {
const context = getContext();
if ( newWidth > 320 && newWidth < 1400 ) {
context.previewWidth = newWidth;
}
},
onWidthChange() {
const { ref } = getElement();
const context = getContext();
context.previewWidth = parseInt( ref.dataset.width, 10 );
setTimeout(
withScope( () => actions.handleOnResize() ),
0
);
},
onLeftKeyDown( event ) {
const context = getContext();
if ( 'ArrowLeft' === event.code ) {
actions.updatePreviewWidth( context.previewWidth + 20 );
} else if ( 'ArrowRight' === event.code ) {
actions.updatePreviewWidth( context.previewWidth - 20 );
}
},
onRightKeyDown( event ) {
const context = getContext();
if ( 'ArrowRight' === event.code ) {
actions.updatePreviewWidth( context.previewWidth + 20 );
} else if ( 'ArrowLeft' === event.code ) {
actions.updatePreviewWidth( context.previewWidth - 20 );
}
},
onDragStart( event ) {
const { ref } = getElement();
state.isDrag = true;
state.prevX = event.x;
state.direction = ref.dataset.direction;
state.dragPos = getContext().previewWidth;
},
onDrag( event ) {
if ( ! state.isDrag ) {
return;
}

const delta = event.x - state.prevX;
if ( ( delta < 0 && 'left' === state.direction ) || ( delta > 0 && 'right' === state.direction ) ) {
state.dragPos += 2 * Math.abs( delta );
actions.updatePreviewWidth( state.dragPos );
} else {
state.dragPos -= 2 * Math.abs( delta );
actions.updatePreviewWidth( state.dragPos );
}
actions.handleOnResize();

state.prevX = event.x;
},
onDragEnd() {
state.throttleTimeout = 0;
state.isDrag = false;
state.direction = '';
},
*onLoad() {
const { ref } = getElement();
Expand All @@ -50,27 +110,19 @@ const { actions, state } = store( 'wporg/patterns/preview', {
},
updatePreviewHeight() {
const context = getContext();
const { ref } = getElement();

// If this is the "narrow" (mobile) view, it should use a fixed height.
if ( state.isWidthNarrow ) {
context.previewHeight = 600;
return;
}

// Need to "use" previewWidth so that `data-wp-watch` will re-run this action when it changes.
context.previewWidth; // eslint-disable-line no-unused-expressions

const iframeDoc = ref.contentDocument;
const height = iframeDoc.querySelector( '.entry-content' )?.clientHeight;
if ( height ) {
context.previewHeight = height * state.scale;
}
context.previewHeight = 600;
},
handleOnResize() {
const context = getContext();
const { ref } = getElement();
context.pageWidth = ref.querySelector( 'div' )?.clientWidth;

// Back up to the block container, so that this works regardless
// of which element interaction triggered it.
const container = ref.closest( '.wp-block-wporg-pattern-view-control' );
if ( container ) {
const preview = container.querySelector( '.wp-block-wporg-pattern-preview__container' );
context.pageWidth = preview?.clientWidth;
}
},
},
} );

0 comments on commit 867542d

Please sign in to comment.