Skip to content

Commit

Permalink
Patterns: Add user pattern categories to post editor inserter pattern…
Browse files Browse the repository at this point in the history
…s tab (#53933)

Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Co-authored-by: James Koster <james@jameskoster.co.uk>
  • Loading branch information
3 people committed Sep 14, 2023
1 parent 359d1da commit 81876cd
Show file tree
Hide file tree
Showing 30 changed files with 833 additions and 396 deletions.
39 changes: 32 additions & 7 deletions packages/block-editor/src/components/block-patterns-list/index.js
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand All @@ -8,9 +13,11 @@ import {
__unstableUseCompositeState as useCompositeState,
__unstableCompositeItem as CompositeItem,
Tooltip,
__experimentalHStack as HStack,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import { Icon, symbol } from '@wordpress/icons';

/**
* Internal dependencies
Expand Down Expand Up @@ -63,14 +70,20 @@ function BlockPattern( {
} }
>
<WithToolTip
showTooltip={ showTooltip }
showTooltip={ showTooltip && ! pattern.id }
title={ pattern.title }
>
<CompositeItem
role="option"
as="div"
{ ...composite }
className="block-editor-block-patterns-list__item"
className={ classnames(
'block-editor-block-patterns-list__item',
{
'block-editor-block-patterns-list__list-item-synced':
pattern.id && ! pattern.syncStatus,
}
) }
onClick={ () => {
onClick( pattern, blocks );
onHover?.( null );
Expand All @@ -91,11 +104,23 @@ function BlockPattern( {
blocks={ blocks }
viewportWidth={ viewportWidth }
/>
{ ! showTooltip && (
<div className="block-editor-block-patterns-list__item-title">
{ pattern.title }
</div>
) }

<HStack className="block-editor-patterns__pattern-details">
{ pattern.id && ! pattern.syncStatus && (
<div className="block-editor-patterns__pattern-icon-wrapper">
<Icon
className="block-editor-patterns__pattern-icon"
icon={ symbol }
/>
</div>
) }
{ ( ! showTooltip || pattern.id ) && (
<div className="block-editor-block-patterns-list__item-title">
{ pattern.title }
</div>
) }
</HStack>

{ !! pattern.description && (
<VisuallyHidden id={ descriptionId }>
{ pattern.description }
Expand Down
Expand Up @@ -11,7 +11,7 @@
min-height: 100px;
}

&[draggable="true"] .block-editor-block-preview__container {
&[draggable="true"] {
cursor: grab;
}
}
Expand All @@ -27,22 +27,39 @@
}

.block-editor-block-patterns-list__item-title {
padding-top: $grid-unit-10;
font-size: 12px;
text-align: center;
text-align: left;
flex-grow: 1;
}

&:hover .block-editor-block-preview__container {
box-shadow: 0 0 0 2px var(--wp-admin-theme-color);
box-shadow: 0 0 0 2px $gray-900;
}

&:focus .block-editor-block-preview__container {
@include button-style-outset__focus(var(--wp-admin-theme-color));
@include button-style-outset__focus($gray-900);
}

&.block-editor-block-patterns-list__list-item-synced {
&:hover,
&:focus {
.block-editor-block-preview__container {
box-shadow:
0 0 0 2px var(--wp-block-synced-color),
0 15px 25px rgb(0 0 0 / 7%);
}
}
}

.block-editor-patterns__pattern-details {
align-items: center;
margin-top: $grid-unit-10;
}

&:hover .block-editor-block-patterns-list__item-title,
&:focus .block-editor-block-patterns-list__item-title {
color: var(--wp-admin-theme-color);
.block-editor-patterns__pattern-icon-wrapper {
min-width: 24px;
height: 24px;
.block-editor-patterns__pattern-icon {
fill: var(--wp-block-synced-color);
}
}
}
@@ -0,0 +1,92 @@
/**
* WordPress dependencies
*/
import {
__experimentalVStack as VStack,
__experimentalHStack as HStack,
__experimentalText as Text,
Button,
} from '@wordpress/components';
import { __, _x, _n, sprintf } from '@wordpress/i18n';

export default function Pagination( {
currentPage,
numPages,
changePage,
totalItems,
} ) {
return (
<VStack>
<Text variant="muted">
{
// translators: %s: Total number of patterns.
sprintf(
// translators: %s: Total number of patterns.
_n( '%s item', '%s items', totalItems ),
totalItems
)
}
</Text>
<HStack
expanded={ false }
spacing={ 3 }
justify="flex-start"
className="block-editor-patterns__grid-pagination"
>
<HStack
expanded={ false }
spacing={ 1 }
className="block-editor-patterns__grid-pagination-previous"
>
<Button
variant="tertiary"
onClick={ () => changePage( 1 ) }
disabled={ currentPage === 1 }
aria-label={ __( 'First page' ) }
>
<span>«</span>
</Button>
<Button
variant="tertiary"
onClick={ () => changePage( currentPage - 1 ) }
disabled={ currentPage === 1 }
aria-label={ __( 'Previous page' ) }
>
<span></span>
</Button>
</HStack>
<Text variant="muted">
{ sprintf(
// translators: %1$s: Current page number, %2$s: Total number of pages.
_x( '%1$s of %2$s', 'paging' ),
currentPage,
numPages
) }
</Text>
<HStack
expanded={ false }
spacing={ 1 }
className="block-editor-patterns__grid-pagination-next"
>
<Button
variant="tertiary"
onClick={ () => changePage( currentPage + 1 ) }
disabled={ currentPage === numPages }
aria-label={ __( 'Next page' ) }
>
<span></span>
</Button>
<Button
variant="tertiary"
onClick={ () => changePage( numPages ) }
disabled={ currentPage === numPages }
aria-label={ __( 'Last page' ) }
size="default"
>
<span>»</span>
</Button>
</HStack>
</HStack>
</VStack>
);
}
@@ -0,0 +1,42 @@
.block-editor-patterns__grid-pagination {
border-top: 1px solid $gray-800;
padding: $grid-unit-05;

.components-button.is-tertiary {
width: auto;
height: $button-size-compact;
justify-content: center;

&:disabled {
color: $gray-600;
background: none;
}

&:hover:not(:disabled) {
color: $white;
background-color: $gray-700;
}
}
}

.show-icon-labels {
.block-editor-patterns__grid-pagination {
flex-direction: column;
.block-editor-patterns__grid-pagination-previous,
.block-editor-patterns__grid-pagination-next {
flex-direction: column;
}
.components-button {
width: auto;
// Hide the button icons when labels are set to display...
span {
display: none;
}
// ... and display labels.
// Uses ::before as ::after is already used for active tab styling.
&::before {
content: attr(aria-label);
}
}
}
}
Expand Up @@ -2,33 +2,69 @@
* WordPress dependencies
*/
import { Modal } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { usePrevious } from '@wordpress/compose';

/**
* Internal dependencies
*/
import PatternExplorerSidebar from './sidebar';
import PatternList from './patterns-list';
import { usePatternsCategories } from '../block-patterns-tab';
import { store as blockEditorStore } from '../../../store';

function PatternsExplorer( { initialCategory, patternCategories } ) {
const [ filterValue, setFilterValue ] = useState( '' );
function PatternsExplorer( { initialCategory, rootClientId } ) {
const [ searchValue, setSearchValue ] = useState( '' );
const [ patternSourceFilter, setPatternSourceFilter ] = useState( 'all' );
const patternSyncFilter = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
const settings = getSettings();
return settings.patternsSyncFilter || 'all';
}, [] );
const [ selectedCategory, setSelectedCategory ] = useState(
initialCategory?.name
);

const previousSyncFilter = usePrevious( patternSyncFilter );

// If the sync filter changes, we need to select the "All" category to avoid
// showing a confusing no results screen.
useEffect( () => {
if ( patternSyncFilter && patternSyncFilter !== previousSyncFilter ) {
setSelectedCategory( initialCategory?.name );
}
}, [
patternSyncFilter,
previousSyncFilter,
patternSourceFilter,
initialCategory?.name,
] );

const patternCategories = usePatternsCategories(
rootClientId,
patternSourceFilter,
patternSyncFilter
);

return (
<div className="block-editor-block-patterns-explorer">
<PatternExplorerSidebar
selectedCategory={ selectedCategory }
patternCategories={ patternCategories }
onClickCategory={ setSelectedCategory }
filterValue={ filterValue }
setFilterValue={ setFilterValue }
searchValue={ searchValue }
setSearchValue={ setSearchValue }
patternSourceFilter={ patternSourceFilter }
setPatternSourceFilter={ setPatternSourceFilter }
/>
<PatternList
filterValue={ filterValue }
searchValue={ searchValue }
selectedCategory={ selectedCategory }
patternCategories={ patternCategories }
patternSourceFilter={ patternSourceFilter }
patternSyncFilter={ patternSyncFilter }
/>
</div>
);
Expand Down

0 comments on commit 81876cd

Please sign in to comment.