Skip to content

Commit 7420c2e

Browse files
pbkingpbkingcarolinanmatiasbenedettot-hamano
authored andcommitted
Font Library: Replace infinite scroll by pagination (#58794)
* Eliminate and render fonts with pagination instead of as a large list Co-authored-by: pbking <pbking@git.wordpress.org> Co-authored-by: carolinan <poena@git.wordpress.org> Co-authored-by: matiasbenedetto <mmaattiiaass@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: afercia <afercia@git.wordpress.org> Co-authored-by: colorful-tones <colorful-tones@git.wordpress.org> Co-authored-by: jasmussen <joen@git.wordpress.org> Co-authored-by: okmttdhr <okat@git.wordpress.org>
1 parent 730beb7 commit 7420c2e

File tree

5 files changed

+146
-101
lines changed

5 files changed

+146
-101
lines changed

packages/edit-site/src/components/global-styles/font-library-modal/collection-font-details.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function CollectionFontDetails( {
4848
/>
4949
) ) }
5050
</VStack>
51-
<Spacer margin={ 8 } />
51+
<Spacer margin={ 16 } />
5252
</>
5353
);
5454
}

packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js

+118-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
/**
22
* WordPress dependencies
33
*/
4-
import { useContext, useEffect, useState, useMemo } from '@wordpress/element';
4+
import {
5+
useContext,
6+
useEffect,
7+
useState,
8+
useMemo,
9+
createInterpolateElement,
10+
} from '@wordpress/element';
511
import {
612
__experimentalSpacer as Spacer,
713
__experimentalInputControl as InputControl,
814
__experimentalText as Text,
15+
__experimentalHStack as HStack,
916
SelectControl,
1017
Spinner,
1118
Icon,
@@ -14,15 +21,14 @@ import {
1421
Button,
1522
} from '@wordpress/components';
1623
import { debounce } from '@wordpress/compose';
17-
import { __, _x } from '@wordpress/i18n';
24+
import { sprintf, __, _x } from '@wordpress/i18n';
1825
import { search, closeSmall } from '@wordpress/icons';
1926

2027
/**
2128
* Internal dependencies
2229
*/
2330
import TabPanelLayout from './tab-panel-layout';
2431
import { FontLibraryContext } from './context';
25-
import FontsGrid from './fonts-grid';
2632
import FontCard from './font-card';
2733
import filterFonts from './utils/filter-fonts';
2834
import CollectionFontDetails from './collection-font-details';
@@ -48,6 +54,7 @@ function FontCollection( { slug } ) {
4854

4955
const [ selectedFont, setSelectedFont ] = useState( null );
5056
const [ fontsToInstall, setFontsToInstall ] = useState( [] );
57+
const [ page, setPage ] = useState( 1 );
5158
const [ filters, setFilters ] = useState( {} );
5259
const [ renderConfirmDialog, setRenderConfirmDialog ] = useState(
5360
requiresPermission && ! getGoogleFontsPermissionFromStorage()
@@ -109,22 +116,34 @@ function FontCollection( { slug } ) {
109116
[ collectionFonts, filters ]
110117
);
111118

119+
// NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px
120+
// The height of each font family item is 61px.
121+
const pageSize = Math.floor( ( window.innerHeight - 417 ) / 61 );
122+
const totalPages = Math.ceil( fonts.length / pageSize );
123+
const itemsStart = ( page - 1 ) * pageSize;
124+
const itemsLimit = page * pageSize;
125+
const items = fonts.slice( itemsStart, itemsLimit );
126+
112127
const handleCategoryFilter = ( category ) => {
113128
setFilters( { ...filters, category } );
129+
setPage( 1 );
114130
};
115131

116132
const handleUpdateSearchInput = ( value ) => {
117133
setFilters( { ...filters, search: value } );
134+
setPage( 1 );
118135
};
119136

120137
const debouncedUpdateSearchInput = debounce( handleUpdateSearchInput, 300 );
121138

122139
const resetFilters = () => {
123140
setFilters( {} );
141+
setPage( 1 );
124142
};
125143

126144
const resetSearch = () => {
127145
setFilters( { ...filters, search: '' } );
146+
setPage( 1 );
128147
};
129148

130149
const handleUnselectFont = () => {
@@ -186,6 +205,24 @@ function FontCollection( { slug } ) {
186205
resetFontsToInstall();
187206
};
188207

208+
let footerComponent = null;
209+
if ( selectedFont ) {
210+
footerComponent = (
211+
<InstallFooter
212+
handleInstall={ handleInstall }
213+
isDisabled={ fontsToInstall.length === 0 }
214+
/>
215+
);
216+
} else if ( ! renderConfirmDialog && totalPages > 1 ) {
217+
footerComponent = (
218+
<PaginationFooter
219+
page={ page }
220+
totalPages={ totalPages }
221+
setPage={ setPage }
222+
/>
223+
);
224+
}
225+
189226
return (
190227
<TabPanelLayout
191228
title={
@@ -198,12 +235,7 @@ function FontCollection( { slug } ) {
198235
}
199236
notice={ notice }
200237
handleBack={ !! selectedFont && handleUnselectFont }
201-
footer={
202-
<Footer
203-
handleInstall={ handleInstall }
204-
isDisabled={ fontsToInstall.length === 0 }
205-
/>
206-
}
238+
footer={ footerComponent }
207239
>
208240
{ renderConfirmDialog && (
209241
<>
@@ -275,8 +307,8 @@ function FontCollection( { slug } ) {
275307
) }
276308

277309
{ ! renderConfirmDialog && ! selectedFont && (
278-
<FontsGrid>
279-
{ fonts.map( ( font ) => (
310+
<div className="font-library-modal__fonts-grid__main">
311+
{ items.map( ( font ) => (
280312
<FontCard
281313
key={ font.font_family_settings.slug }
282314
font={ font.font_family_settings }
@@ -285,13 +317,86 @@ function FontCollection( { slug } ) {
285317
} }
286318
/>
287319
) ) }
288-
</FontsGrid>
320+
</div>
289321
) }
290322
</TabPanelLayout>
291323
);
292324
}
293325

294-
function Footer( { handleInstall, isDisabled } ) {
326+
function PaginationFooter( { page, totalPages, setPage } ) {
327+
return (
328+
<Flex justify="center">
329+
<Button
330+
label={ __( 'First page' ) }
331+
size="compact"
332+
onClick={ () => setPage( 1 ) }
333+
disabled={ page === 1 }
334+
__experimentalIsFocusable
335+
>
336+
<span>«</span>
337+
</Button>
338+
<Button
339+
label={ __( 'Previous page' ) }
340+
size="compact"
341+
onClick={ () => setPage( page - 1 ) }
342+
disabled={ page === 1 }
343+
__experimentalIsFocusable
344+
>
345+
<span></span>
346+
</Button>
347+
<HStack justify="flex-start" expanded={ false } spacing={ 2 }>
348+
{ createInterpolateElement(
349+
sprintf(
350+
// translators: %s: Total number of pages.
351+
_x( 'Page <CurrenPageControl /> of %s', 'paging' ),
352+
totalPages
353+
),
354+
{
355+
CurrenPageControl: (
356+
<SelectControl
357+
aria-label={ __( 'Current page' ) }
358+
value={ page }
359+
options={ [ ...Array( totalPages ) ].map(
360+
( e, i ) => {
361+
return {
362+
label: i + 1,
363+
value: i + 1,
364+
};
365+
}
366+
) }
367+
onChange={ ( newPage ) =>
368+
setPage( parseInt( newPage ) )
369+
}
370+
size={ 'compact' }
371+
__nextHasNoMarginBottom
372+
/>
373+
),
374+
}
375+
) }
376+
</HStack>
377+
<Button
378+
label={ __( 'Next page' ) }
379+
size="compact"
380+
onClick={ () => setPage( page + 1 ) }
381+
disabled={ page === totalPages }
382+
__experimentalIsFocusable
383+
>
384+
<span></span>
385+
</Button>
386+
<Button
387+
label={ __( 'Last page' ) }
388+
size="compact"
389+
onClick={ () => setPage( totalPages ) }
390+
disabled={ page === totalPages }
391+
__experimentalIsFocusable
392+
>
393+
<span>»</span>
394+
</Button>
395+
</Flex>
396+
);
397+
}
398+
399+
function InstallFooter( { handleInstall, isDisabled } ) {
295400
const { isInstalling } = useContext( FontLibraryContext );
296401

297402
return (

packages/edit-site/src/components/global-styles/font-library-modal/fonts-grid.js

-59
This file was deleted.

packages/edit-site/src/components/global-styles/font-library-modal/installed-fonts.js

+25-23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
privateApis as componentsPrivateApis,
88
__experimentalHStack as HStack,
99
__experimentalSpacer as Spacer,
10+
__experimentalText as Text,
1011
Button,
1112
Spinner,
1213
FlexItem,
@@ -17,7 +18,6 @@ import {
1718
*/
1819
import TabPanelLayout from './tab-panel-layout';
1920
import { FontLibraryContext } from './context';
20-
import FontsGrid from './fonts-grid';
2121
import LibraryFontDetails from './library-font-details';
2222
import LibraryFontCard from './library-font-card';
2323
import ConfirmDeleteDialog from './confirm-delete-dialog';
@@ -123,36 +123,38 @@ function InstalledFonts() {
123123
) }
124124
{ baseCustomFonts.length > 0 && (
125125
<>
126-
<FontsGrid>
127-
{ baseCustomFonts.map( ( font ) => (
128-
<LibraryFontCard
129-
font={ font }
130-
key={ font.slug }
131-
onClick={ () => {
132-
handleSelectFont( font );
133-
} }
134-
/>
135-
) ) }
136-
</FontsGrid>
126+
{ baseCustomFonts.map( ( font ) => (
127+
<LibraryFontCard
128+
font={ font }
129+
key={ font.slug }
130+
onClick={ () => {
131+
handleSelectFont( font );
132+
} }
133+
/>
134+
) ) }
137135
<Spacer margin={ 8 } />
138136
</>
139137
) }
140138

141139
{ baseThemeFonts.length > 0 && (
142140
<>
143-
<FontsGrid title={ __( 'Theme Fonts' ) }>
144-
{ baseThemeFonts.map( ( font ) => (
145-
<LibraryFontCard
146-
font={ font }
147-
key={ font.slug }
148-
onClick={ () => {
149-
handleSelectFont( font );
150-
} }
151-
/>
152-
) ) }
153-
</FontsGrid>
141+
<Text className="font-library-modal__subtitle">
142+
{ __( 'Theme Fonts' ) }
143+
</Text>
144+
145+
<Spacer margin={ 2 } />
146+
{ baseThemeFonts.map( ( font ) => (
147+
<LibraryFontCard
148+
font={ font }
149+
key={ font.slug }
150+
onClick={ () => {
151+
handleSelectFont( font );
152+
} }
153+
/>
154+
) ) }
154155
</>
155156
) }
157+
<Spacer margin={ 16 } />
156158
</>
157159
) }
158160

packages/edit-site/src/components/global-styles/font-library-modal/style.scss

+2-5
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,8 @@
3636
}
3737
}
3838

39-
.font-library-modal__fonts-grid {
40-
.font-library-modal__fonts-grid__main {
41-
display: flex;
42-
flex-direction: column;
43-
}
39+
.font-library-modal__tabpanel-layout .components-base-control__field {
40+
margin-bottom: 0;
4441
}
4542

4643
.font-library-modal__font-card {

0 commit comments

Comments
 (0)