diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js b/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js index de0c1cfa16ec6..a696295266193 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js @@ -48,7 +48,7 @@ function CollectionFontDetails( { /> ) ) } - + > ); } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index 4a14ee245694b..6236ea8fe3f24 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -1,11 +1,18 @@ /** * WordPress dependencies */ -import { useContext, useEffect, useState, useMemo } from '@wordpress/element'; +import { + useContext, + useEffect, + useState, + useMemo, + createInterpolateElement, +} from '@wordpress/element'; import { __experimentalSpacer as Spacer, __experimentalInputControl as InputControl, __experimentalText as Text, + __experimentalHStack as HStack, SelectControl, Spinner, Icon, @@ -14,7 +21,7 @@ import { Button, } from '@wordpress/components'; import { debounce } from '@wordpress/compose'; -import { __, _x } from '@wordpress/i18n'; +import { sprintf, __, _x } from '@wordpress/i18n'; import { search, closeSmall } from '@wordpress/icons'; /** @@ -22,7 +29,6 @@ import { search, closeSmall } from '@wordpress/icons'; */ import TabPanelLayout from './tab-panel-layout'; import { FontLibraryContext } from './context'; -import FontsGrid from './fonts-grid'; import FontCard from './font-card'; import filterFonts from './utils/filter-fonts'; import CollectionFontDetails from './collection-font-details'; @@ -48,6 +54,7 @@ function FontCollection( { slug } ) { const [ selectedFont, setSelectedFont ] = useState( null ); const [ fontsToInstall, setFontsToInstall ] = useState( [] ); + const [ page, setPage ] = useState( 1 ); const [ filters, setFilters ] = useState( {} ); const [ renderConfirmDialog, setRenderConfirmDialog ] = useState( requiresPermission && ! getGoogleFontsPermissionFromStorage() @@ -109,22 +116,34 @@ function FontCollection( { slug } ) { [ collectionFonts, filters ] ); + // NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px + // The height of each font family item is 61px. + const pageSize = Math.floor( ( window.innerHeight - 417 ) / 61 ); + const totalPages = Math.ceil( fonts.length / pageSize ); + const itemsStart = ( page - 1 ) * pageSize; + const itemsLimit = page * pageSize; + const items = fonts.slice( itemsStart, itemsLimit ); + const handleCategoryFilter = ( category ) => { setFilters( { ...filters, category } ); + setPage( 1 ); }; const handleUpdateSearchInput = ( value ) => { setFilters( { ...filters, search: value } ); + setPage( 1 ); }; const debouncedUpdateSearchInput = debounce( handleUpdateSearchInput, 300 ); const resetFilters = () => { setFilters( {} ); + setPage( 1 ); }; const resetSearch = () => { setFilters( { ...filters, search: '' } ); + setPage( 1 ); }; const handleUnselectFont = () => { @@ -186,6 +205,24 @@ function FontCollection( { slug } ) { resetFontsToInstall(); }; + let footerComponent = null; + if ( selectedFont ) { + footerComponent = ( + + ); + } else if ( ! renderConfirmDialog && totalPages > 1 ) { + footerComponent = ( + + ); + } + return ( - } + footer={ footerComponent } > { renderConfirmDialog && ( <> @@ -275,8 +307,8 @@ function FontCollection( { slug } ) { ) } { ! renderConfirmDialog && ! selectedFont && ( - - { fonts.map( ( font ) => ( + + { items.map( ( font ) => ( ) ) } - + ) } ); } -function Footer( { handleInstall, isDisabled } ) { +function PaginationFooter( { page, totalPages, setPage } ) { + return ( + + setPage( 1 ) } + disabled={ page === 1 } + __experimentalIsFocusable + > + « + + setPage( page - 1 ) } + disabled={ page === 1 } + __experimentalIsFocusable + > + ‹ + + + { createInterpolateElement( + sprintf( + // translators: %s: Total number of pages. + _x( 'Page of %s', 'paging' ), + totalPages + ), + { + CurrenPageControl: ( + { + return { + label: i + 1, + value: i + 1, + }; + } + ) } + onChange={ ( newPage ) => + setPage( parseInt( newPage ) ) + } + size={ 'compact' } + __nextHasNoMarginBottom + /> + ), + } + ) } + + setPage( page + 1 ) } + disabled={ page === totalPages } + __experimentalIsFocusable + > + › + + setPage( totalPages ) } + disabled={ page === totalPages } + __experimentalIsFocusable + > + » + + + ); +} + +function InstallFooter( { handleInstall, isDisabled } ) { const { isInstalling } = useContext( FontLibraryContext ); return ( diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js b/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js deleted file mode 100644 index 9700831a7adef..0000000000000 --- a/packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * WordPress dependencies - */ -import { - __experimentalVStack as VStack, - __experimentalText as Text, - __experimentalSpacer as Spacer, -} from '@wordpress/components'; -import { useState, useEffect } from '@wordpress/element'; - -function FontsGrid( { title, children, pageSize = 32 } ) { - const [ lastItem, setLastItem ] = useState( null ); - const [ page, setPage ] = useState( 1 ); - const itemsLimit = page * pageSize; - const items = children.slice( 0, itemsLimit ); - - useEffect( () => { - if ( lastItem ) { - const observer = new window.IntersectionObserver( ( [ entry ] ) => { - if ( entry.isIntersecting ) { - setPage( ( prevPage ) => prevPage + 1 ); - } - } ); - - observer.observe( lastItem ); - - return () => observer.disconnect(); - } - }, [ lastItem ] ); - - return ( - - - { title && ( - <> - - { title } - - - > - ) } - - { items.map( ( child, i ) => { - if ( i === itemsLimit - 1 ) { - return ( - - { child } - - ); - } - return { child }; - } ) } - - - - ); -} - -export default FontsGrid; diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js index 73ff17f25b9a6..99c99e44a43af 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js @@ -7,6 +7,7 @@ import { privateApis as componentsPrivateApis, __experimentalHStack as HStack, __experimentalSpacer as Spacer, + __experimentalText as Text, Button, Spinner, FlexItem, @@ -17,7 +18,6 @@ import { */ import TabPanelLayout from './tab-panel-layout'; import { FontLibraryContext } from './context'; -import FontsGrid from './fonts-grid'; import LibraryFontDetails from './library-font-details'; import LibraryFontCard from './library-font-card'; import ConfirmDeleteDialog from './confirm-delete-dialog'; @@ -123,36 +123,38 @@ function InstalledFonts() { ) } { baseCustomFonts.length > 0 && ( <> - - { baseCustomFonts.map( ( font ) => ( - { - handleSelectFont( font ); - } } - /> - ) ) } - + { baseCustomFonts.map( ( font ) => ( + { + handleSelectFont( font ); + } } + /> + ) ) } > ) } { baseThemeFonts.length > 0 && ( <> - - { baseThemeFonts.map( ( font ) => ( - { - handleSelectFont( font ); - } } - /> - ) ) } - + + { __( 'Theme Fonts' ) } + + + + { baseThemeFonts.map( ( font ) => ( + { + handleSelectFont( font ); + } } + /> + ) ) } > ) } + > ) } diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss index beb1ba46714ff..544e3ed63c988 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/style.scss +++ b/packages/edit-site/src/components/global-styles/font-library-modal/style.scss @@ -36,11 +36,8 @@ } } -.font-library-modal__fonts-grid { - .font-library-modal__fonts-grid__main { - display: flex; - flex-direction: column; - } +.font-library-modal__tabpanel-layout .components-base-control__field { + margin-bottom: 0; } .font-library-modal__font-card {