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

Theme previewer: Use listbox for theme patterns & style variation lists to improve selection UX #126

Merged
merged 13 commits into from
Jun 17, 2024
70 changes: 70 additions & 0 deletions source/wp-content/themes/wporg-themes-2024/src/style/_listbox.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* Screenshot block styles */
.wp-block-wporg-screenshot-preview {
border-color: var(--wp--preset--color--light-grey-1);
}

.wp-block-wporg-screenshot-preview:not(.is-preview-image):hover img {
Copy link

@adamwoodnz adamwoodnz Jun 18, 2024

Choose a reason for hiding this comment

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

I find it a bit strange when hovering not to get a pointer style cursor, for elements I can interact with.

Goes for both variations and patterns.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, the cursor was raised in #128, so that'll be fixed.

transform: scale(1.15);
}

/* Listbox interaction styles */
.wporg-theme-listbox:focus {
outline: none;
}

.wporg-theme-listbox .wp-block-wporg-screenshot-preview {
position: relative;
border: none;
}

.wporg-theme-listbox .wp-block-wporg-screenshot-preview::after {
content: "";
position: absolute;
z-index: 1;
inset: 0;
border-color: var(--wp--preset--color--light-grey-1);
border-style: solid;
border-width: 1.5px;
border-radius: 3px;
}

.wporg-theme-listbox:where(:focus) .is-focus .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--blueberry-1);
box-shadow: inset 0 0 0 1.5px var(--wp--preset--color--light-grey-1);
}

.wporg-theme-listbox [aria-selected="true"] .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--charcoal-1);
box-shadow: inset 0 0 0 3px var(--wp--preset--color--light-grey-1);
}

.wporg-theme-listbox:where(:focus) [aria-selected="true"].is-focus .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--blueberry-1);
box-shadow: inset 0 0 0 3px var(--wp--preset--color--light-grey-1);
}

/* Screenshot & listbox in the Previewer */
:where(body.wporg-theme-preview) {
.wp-block-wporg-screenshot-preview {
background-color: var(--wp--preset--color--white);
}

.wporg-theme-listbox .wp-block-wporg-screenshot-preview::after {
border-color: transparent;
}

.wporg-theme-listbox:where(:focus) .is-focus .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--blueberry-2);
box-shadow: inset 0 0 0 1.5px var(--wp--preset--color--charcoal-1);
}

.wporg-theme-listbox [aria-selected="true"] .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--white);
box-shadow: inset 0 0 0 3px var(--wp--preset--color--charcoal-1);
}

.wporg-theme-listbox:where(:focus) [aria-selected="true"].is-focus .wp-block-wporg-screenshot-preview::after {
border-color: var(--wp--preset--color--blueberry-2);
box-shadow: inset 0 0 0 3px var(--wp--preset--color--charcoal-1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* templates or theme.json settings.
*/

@import "listbox";

.wp-block-query-pagination.wp-block-query-pagination {
margin-bottom: 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
"editorScript": "file:./index.js",
"style": "file:./style-index.css",
"render": "file:./render.php",
"viewScriptModule": "file:./view.js"
"viewScript": "file:./view.js"
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,38 @@
function init() {
register_block_type( dirname( dirname( __DIR__ ) ) . '/build/theme-patterns' );
}

/**
* Convert a pattern object into a screenshot preview block.
*/
function get_pattern_preview_block( $pattern, $is_overflow = false, $is_selected = false ) {
$cache_buster = '20240522'; // To break out of cached image.
$view_url = add_query_arg( 'v', $cache_buster, $pattern->preview_link );

$args = array(
'src' => $view_url,
// translators: %s pattern name.
'alt' => sprintf( __( 'Pattern: %s', 'wporg-themes' ), $pattern->title ),
'width' => 275,
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Name comes from API.
'viewportWidth' => $pattern->viewportWidth ?? 1200,
'fullPage' => true,
'isHidden' => $is_overflow,
);

$image_markup = do_blocks( sprintf( '<!-- wp:wporg/screenshot-preview %s /-->', wp_json_encode( $args ) ) );

$instance_id = wp_unique_id( 'wporg-theme-patterns-item-' );

$extra_attrs = '';
$extra_attrs .= $is_overflow ? ' style="display:none;"' : '';
$extra_attrs .= $is_selected ? ' aria-selected="true"' : '';

return sprintf(
'<li role="option" id="%1$s" data-pattern_name="%2$s" %3$s>%4$s</li>',
$instance_id,
$pattern->name,
$extra_attrs,
$image_markup
);
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
<?php

use function WordPressdotorg\Theme\Theme_Directory_2024\get_theme_patterns;

/**
* Convert a pattern object into a screenshot preview block.
*/
function get_pattern_preview_block( $pattern, $is_overflow = false ) {
$preview_link = add_query_arg( 'pattern_name', $pattern->name, $pattern->preview_base );
$cache_buster = '20240522'; // To break out of cached image.
$view_url = add_query_arg( 'v', $cache_buster, $pattern->preview_link );

$args = array(
'src' => $view_url,
// translators: %s pattern name.
'alt' => sprintf( __( 'Pattern: %s', 'wporg-themes' ), $pattern->title ),
'href' => $preview_link,
'width' => 275,
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Name comes from API.
'viewportWidth' => $pattern->viewportWidth ?? 1200,
'fullPage' => true,
'isHidden' => $is_overflow,
);
return do_blocks( sprintf( '<!-- wp:wporg/screenshot-preview %s /-->', wp_json_encode( $args ) ) );
}
use function WordPressdotorg\Theme\Theme_Directory_2024\Theme_Patterns\get_pattern_preview_block;

$current_post_id = $block->context['postId'];
if ( ! $current_post_id ) {
Expand All @@ -35,42 +14,55 @@ function get_pattern_preview_block( $pattern, $is_overflow = false ) {
$theme = wporg_themes_theme_information( $theme_post->post_name );

$patterns = get_theme_patterns( $theme_post->post_name );
$initial_count = $show_all ? PHP_INT_MAX : 6;
$pattern_count = count( $patterns );
$initial_count = $show_all ? $pattern_count : 6;

if ( ! count( $patterns ) ) {
if ( ! $pattern_count ) {
return '';
}

// Initial state to pass to Interactivity API.
$selected_index = -1;
if ( isset( $_GET['pattern_name'] ) ) {
foreach ( $patterns as $i => $pattern ) {
if ( $pattern->name === $_GET['pattern_name'] ) {
$selected_index = $i;
break;
}
}
}

// Initial state to pass to JS (*not* Interactivty API).
$init_state = [
'hideOverflow' => true,
'allowUnselect' => true,
'initialCount' => $initial_count,
'totalCount' => $pattern_count,
'initialSelected' => $selected_index,
];
$encoded_state = wp_json_encode( $init_state );
?>
<div
<?php echo get_block_wrapper_attributes(); // phpcs:ignore ?>
data-wp-interactive="wporg/themes/theme-patterns"
data-wp-context="<?php echo esc_attr( $encoded_state ); ?>"
data-initial-state="<?php echo esc_attr( $encoded_state ); ?>"
>
<h2 class="wp-block-heading has-heading-4-font-size"><?php esc_html_e( 'Patterns', 'wporg-themes' ); ?></h2>
<h2 id="wporg-theme-patterns-heading" class="wp-block-heading has-heading-4-font-size"><?php esc_html_e( 'Patterns', 'wporg-themes' ); ?></h2>

<div class="wporg-theme-patterns__grid">
<ul
tabindex="0"
role="listbox"
aria-labelledby="wporg-theme-patterns-heading"
class="wporg-theme-patterns__grid wporg-theme-listbox"
>
<?php
foreach ( $patterns as $i => $pattern ) {
$pattern->preview_base = untrailingslashit( get_permalink( $theme_post ) ) . '/preview/';
echo get_pattern_preview_block( $pattern, $i >= $initial_count ); // phpcs:ignore
echo get_pattern_preview_block( $pattern, $i >= $initial_count, $i === $selected_index ); // phpcs:ignore
}
?>
</div>
</ul>

<?php if ( count( $patterns ) > $initial_count ) : ?>
<?php if ( $pattern_count > $initial_count ) : ?>
<div class="wporg-theme-patterns__button wp-block-button is-style-outline is-small">
<button
class="wp-block-button__link wp-element-button"
data-wp-on--click="actions.showAll"
data-wp-style--display="state.buttonCSS"
>
<button class="wp-block-button__link wp-element-button">
<?php esc_html_e( 'Show all patterns', 'wporg-themes' ); ?>
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,23 @@
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--wp--preset--spacing--20);
list-style: none;
padding-left: 0;

.wp-block-wporg-screenshot-preview {
padding: var(--wp--preset--spacing--20);
border-color: var(--wp--preset--color--light-grey-1);
background-color: var(--wp--preset--color--light-grey-2);

&:hover img {
transform: scale(1.08) !important;
}
}

:where(body.wporg-theme-preview) & {
grid-template-columns: repeat(2, 1fr);
gap: var(--wp--preset--spacing--10);

.wp-block-wporg-screenshot-preview {
padding: var(--wp--preset--spacing--10);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
/**
* WordPress dependencies
*/
import { getContext, getElement, store } from '@wordpress/interactivity';
import { addQueryArgs } from '@wordpress/url';

store( 'wporg/themes/theme-patterns', {
state: {
get buttonCSS() {
return getContext().hideOverflow ? false : 'none';
},
},
actions: {
showAll() {
const context = getContext();
const { ref } = getElement();
context.hideOverflow = false;
/**
* Internal dependencies
*/
import wporgListbox from '../utils/listbox';

const container = ref.closest( '.wp-block-wporg-theme-patterns' );
if ( ! container ) {
return;
}
window.addEventListener( 'load', () => {
const containers = document.querySelectorAll( '.wp-block-wporg-theme-patterns' );
if ( ! containers ) {
return;
}

// Trigger the custom "show" event on each image.
container.querySelectorAll( '.wp-block-wporg-screenshot-preview' ).forEach( ( element ) => {
const event = new Event( 'wporg-show' );
element.dispatchEvent( event );
} );
containers.forEach( ( container ) => {
const state = JSON.parse( container.dataset.initialState );
new wporgListbox( container, state );

// Move focus from the now-removed button to the first-visible element.
setTimeout( () => {
const firstNewElement = container.querySelectorAll( 'a' )[ context.initialCount ];
if ( firstNewElement ) {
firstNewElement.focus();
// Not in the previewer, use the select event to navigate to the previewer.
if ( ! container.closest( '.wp-block-wporg-theme-previewer' ) ) {
container.querySelector( '[role="listbox"]' ).addEventListener( 'wporg-select', ( event ) => {
const ref = event.selectedElement;
if ( ref && ref.dataset ) {
let url = window.location.toString();
url = url.replace( /\/$/, '' ) + '/preview/';
url = addQueryArgs( url, { pattern_name: ref.dataset.pattern_name } );
window.location = url;
}
}, 0 );
},
},
} );
}
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,6 @@
}
}

.wporg-theme-patterns__grid {
grid-template-columns: repeat(2, 1fr);
gap: var(--wp--preset--spacing--10);

.wp-block-wporg-screenshot-preview {
padding: calc(var(--wp--preset--spacing--10) * 0.5);
}
}

.wp-block-wporg-screenshot-preview {
border-color: var(--wp--preset--color--white-opacity-15);
border-width: 1.5px;

&:where(.is-linked-image):hover {
border-color: var(--wp--preset--color--blueberry-2) !important;
}

&:where(.is-linked-image):focus-within {
border-color: var(--wp--preset--color--blueberry-1);
border-width: 1.5px;
outline-color: var(--wp--preset--color--white);
outline-offset: 0;
}
}

@media (max-width: 781px) {
--wporg-theme-preview--sidebar--height: 80px;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,12 @@ class="wp-block-button__link wp-element-button"
</div>
</section>
<iframe
title="<?php esc_attr_e( 'Theme preview', 'wporg-themes' ); ?>"
src="<?php echo esc_url_raw( $url ); ?>"
data-wp-bind--src="wporg/themes/preview::context.url"
data-wp-style--width="state.iframeWidthCSS"
data-wp-style--height="state.iframeHeightCSS"
data-wp-on--load="wporg/themes/preview::actions.onLoad"
/>
></iframe>
<?php endif; ?>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ function Edit() {
registerBlockType( metadata.name, {
edit: Edit,
save: () => null,
} );
} );
Loading