From ea4261abb874dea98d3f4db6a3b2fcb440a7f4ac Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 13 Jul 2023 19:31:42 +1200 Subject: [PATCH] Patterns: Add client side pagination to patterns list (#52538) Co-authored-by: Saxon Fletcher --- .../src/components/page-patterns/grid.js | 117 +++++++++++++++--- .../components/page-patterns/patterns-list.js | 7 +- .../src/components/page-patterns/style.scss | 22 +++- 3 files changed, 125 insertions(+), 21 deletions(-) diff --git a/packages/edit-site/src/components/page-patterns/grid.js b/packages/edit-site/src/components/page-patterns/grid.js index 1902b36982c14..47bcdc8a1f768 100644 --- a/packages/edit-site/src/components/page-patterns/grid.js +++ b/packages/edit-site/src/components/page-patterns/grid.js @@ -1,26 +1,115 @@ /** * WordPress dependencies */ -import { __experimentalText as Text } from '@wordpress/components'; -import { useRef } from '@wordpress/element'; -import { __, sprintf } from '@wordpress/i18n'; +import { + __experimentalHStack as HStack, + __experimentalText as Text, + Button, +} from '@wordpress/components'; +import { useRef, useState, useMemo } from '@wordpress/element'; +import { __, _x, _n, sprintf } from '@wordpress/i18n'; +import { useAsyncList } from '@wordpress/compose'; /** * Internal dependencies */ import GridItem from './grid-item'; -const PAGE_SIZE = 100; +const PAGE_SIZE = 20; + +function Pagination( { currentPage, numPages, changePage, totalItems } ) { + return ( + + + { + // translators: %s: Total number of patterns. + sprintf( + // translators: %s: Total number of patterns. + _n( '%s item', '%s items', totalItems ), + totalItems + ) + } + + + + + + + { sprintf( + // translators: %1$s: Current page number, %2$s: Total number of pages. + _x( '%1$s of %2$s', 'paging' ), + currentPage, + numPages + ) } + + + + + + + ); +} export default function Grid( { categoryId, items, ...props } ) { + const [ currentPage, setCurrentPage ] = useState( 1 ); const gridRef = useRef(); + const totalItems = items.length; + const pageIndex = currentPage - 1; - if ( ! items?.length ) { + const list = useMemo( + () => + items.slice( + pageIndex * PAGE_SIZE, + pageIndex * PAGE_SIZE + PAGE_SIZE + ), + [ pageIndex, items ] + ); + + const asyncList = useAsyncList( list, { step: 10 } ); + + if ( ! list?.length ) { return null; } - const list = items.slice( 0, PAGE_SIZE ); - const restLength = items.length - PAGE_SIZE; + const numPages = Math.ceil( items.length / PAGE_SIZE ); + const changePage = ( page ) => { + const scrollContainer = document.querySelector( '.edit-site-patterns' ); + scrollContainer?.scrollTo( 0, 0 ); + + setCurrentPage( page ); + }; return ( <> @@ -30,7 +119,7 @@ export default function Grid( { categoryId, items, ...props } ) { { ...props } ref={ gridRef } > - { list.map( ( item ) => ( + { asyncList.map( ( item ) => ( ) ) } - { restLength > 0 && ( - - { sprintf( - /* translators: %d: number of patterns */ - __( '+ %d more patterns discoverable by searching' ), - restLength - ) } - + { numPages > 1 && ( + ) } ); diff --git a/packages/edit-site/src/components/page-patterns/patterns-list.js b/packages/edit-site/src/components/page-patterns/patterns-list.js index 7bf2a9d506584..f4fefed4a2d3e 100644 --- a/packages/edit-site/src/components/page-patterns/patterns-list.js +++ b/packages/edit-site/src/components/page-patterns/patterns-list.js @@ -15,7 +15,7 @@ import { import { __, isRTL } from '@wordpress/i18n'; import { chevronLeft, chevronRight } from '@wordpress/icons'; import { privateApis as routerPrivateApis } from '@wordpress/router'; -import { useViewportMatch, useAsyncList } from '@wordpress/compose'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -70,7 +70,6 @@ export default function PatternsList( { categoryId, type } ) { const hasPatterns = patterns.length; const title = SYNC_FILTERS[ syncFilter ]; const description = SYNC_DESCRIPTIONS[ syncFilter ]; - const shownPatterns = useAsyncList( patterns ); return ( @@ -132,7 +131,7 @@ export default function PatternsList( { categoryId, type } ) { { syncFilter !== 'all' && ( - + { title } { description ? ( @@ -145,7 +144,7 @@ export default function PatternsList( { categoryId, type } ) { { hasPatterns && ( diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss index 79731999f46ef..d1fbedb141f70 100644 --- a/packages/edit-site/src/components/page-patterns/style.scss +++ b/packages/edit-site/src/components/page-patterns/style.scss @@ -1,6 +1,8 @@ .edit-site-patterns { - background: rgba(0, 0, 0, 0.15); + border: 1px solid $gray-800; + background: none; margin: $header-height 0 0; + border-radius: 0; .components-base-control { width: 100%; @include break-medium { @@ -59,6 +61,23 @@ background: $gray-700; color: $gray-100; } + + .edit-site-patterns__grid-pagination { + width: fit-content; + .components-button.is-tertiary { + width: $button-size-compact; + height: $button-size-compact; + color: $gray-100; + background-color: $gray-800; + &:disabled { + color: $gray-600; + background: none; + } + &:hover:not(:disabled) { + background-color: $gray-700; + } + } + } } .edit-site-patterns__section-header { @@ -74,6 +93,7 @@ // Small top padding required to avoid cutting off the visible outline // when hovering items. padding-top: $border-width-focus-fallback; + margin-top: 0; margin-bottom: $grid-unit-40; @include break-large { grid-template-columns: 1fr 1fr;