diff options
| -rw-r--r-- | src/components/PostsList/PostsList.module.scss | 5 | ||||
| -rw-r--r-- | src/components/PostsList/PostsList.tsx | 52 | ||||
| -rw-r--r-- | src/pages/blog/index.tsx | 14 | ||||
| -rw-r--r-- | src/pages/recherche/index.tsx | 15 |
4 files changed, 65 insertions, 21 deletions
diff --git a/src/components/PostsList/PostsList.module.scss b/src/components/PostsList/PostsList.module.scss index c0f8062..6c3f93e 100644 --- a/src/components/PostsList/PostsList.module.scss +++ b/src/components/PostsList/PostsList.module.scss @@ -33,9 +33,12 @@ } li.item { - margin: 0 0 var(--spacing-md) 0; border-bottom: fun.convert-px(1) solid var(--color-border-light); + &:not(:last-of-type) { + margin: 0 0 var(--spacing-md) 0; + } + &:first-of-type { margin-top: var(--spacing-sm); diff --git a/src/components/PostsList/PostsList.tsx b/src/components/PostsList/PostsList.tsx index f401d83..df9dfe4 100644 --- a/src/components/PostsList/PostsList.tsx +++ b/src/components/PostsList/PostsList.tsx @@ -2,22 +2,31 @@ import { t } from '@lingui/macro'; import { PostsList as PostsListData } from '@ts/types/blog'; import styles from './PostsList.module.scss'; import PostPreview from '@components/PostPreview/PostPreview'; -import { Fragment } from 'react'; +import { ForwardedRef, forwardRef, Fragment } from 'react'; import { sortPostsByYear } from '@utils/helpers/sort'; -const PostsList = ({ - data, - showYears, -}: { - data: PostsListData[]; - showYears: boolean; -}) => { +const PostsList = ( + { + data, + showYears, + }: { + data: PostsListData[]; + showYears: boolean; + }, + ref: ForwardedRef<HTMLSpanElement> +) => { const titleLevel = showYears ? 3 : 2; const getPostsListByYear = () => { const posts = sortPostsByYear(data); const years = Object.keys(posts).reverse(); + const getLastPostId = () => { + const oldestYear = Object.keys(posts)[0]; + const lastPost = posts[oldestYear][posts[oldestYear].length - 1]; + return lastPost.id; + }; + return years.map((year) => { return ( <section key={year} className={styles.section}> @@ -29,10 +38,14 @@ const PostsList = ({ )} <ol className={styles.list}> {posts[year].map((post) => { + const isLastPost = post.id === getLastPostId(); return ( - <li key={post.id} className={styles.item}> - <PostPreview post={post} titleLevel={titleLevel} /> - </li> + <Fragment key={post.id}> + <li className={styles.item}> + <PostPreview post={post} titleLevel={titleLevel} /> + </li> + {isLastPost && <span ref={ref} tabIndex={-1} />} + </Fragment> ); })} </ol> @@ -43,6 +56,11 @@ const PostsList = ({ const getPostsList = () => { return data.map((page) => { + const getLastPostId = () => { + const lastPost = page.posts[page.posts.length - 1]; + return lastPost.id; + }; + if (page.posts.length === 0) { return <p key="no-result">{t`No results found.`}</p>; } else { @@ -50,10 +68,14 @@ const PostsList = ({ <Fragment key={page.pageInfo.endCursor}> <ol className={styles.list}> {page.posts.map((post) => { + const isLastPost = post.id === getLastPostId(); return ( - <li key={post.id} className={styles.item}> - <PostPreview post={post} titleLevel={titleLevel} /> - </li> + <Fragment key={post.id}> + <li key={post.id} className={styles.item}> + <PostPreview post={post} titleLevel={titleLevel} /> + </li> + {isLastPost && <span ref={ref} tabIndex={-1} />} + </Fragment> ); })} </ol> @@ -66,4 +88,4 @@ const PostsList = ({ return <div>{showYears ? getPostsListByYear() : getPostsList()}</div>; }; -export default PostsList; +export default forwardRef(PostsList); diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx index faadd6f..e0d35cd 100644 --- a/src/pages/blog/index.tsx +++ b/src/pages/blog/index.tsx @@ -15,8 +15,11 @@ import PostHeader from '@components/PostHeader/PostHeader'; import { ThematicsList, TopicsList } from '@components/Widget'; import Sidebar from '@components/Sidebar/Sidebar'; import styles from '@styles/pages/Page.module.scss'; +import { useRef } from 'react'; const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => { + const lastPostRef = useRef<HTMLSpanElement>(null); + const getKey = (pageIndex: number, previousData: PostsListData) => { if (previousData && !previousData.posts) return null; @@ -44,6 +47,13 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => { const hasNextPage = data && data[data.length - 1].pageInfo.hasNextPage; + const loadMorePosts = () => { + if (lastPostRef.current) { + lastPostRef.current.focus(); + } + setSize(size + 1); + }; + return ( <> <Head> @@ -55,11 +65,11 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => { > <PostHeader title={t`Blog`} /> <div className={styles.body}> - <PostsList data={data} showYears={true} /> + <PostsList ref={lastPostRef} data={data} showYears={true} /> {hasNextPage && ( <Button isDisabled={isLoadingMore} - clickHandler={() => setSize(size + 1)} + clickHandler={loadMorePosts} position="center" >{t`Load more?`}</Button> )} diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx index c8a7b9b..57f40e2 100644 --- a/src/pages/recherche/index.tsx +++ b/src/pages/recherche/index.tsx @@ -11,7 +11,7 @@ import { loadTranslation } from '@utils/helpers/i18n'; import { GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import useSWRInfinite from 'swr/infinite'; import Sidebar from '@components/Sidebar/Sidebar'; import { ThematicsList, TopicsList } from '@components/Widget'; @@ -20,6 +20,7 @@ import styles from '@styles/pages/Page.module.scss'; const Search: NextPageWithLayout = () => { const [query, setQuery] = useState(''); const router = useRouter(); + const lastPostRef = useRef<HTMLSpanElement>(null); useEffect(() => { if (!router.isReady) return; @@ -69,6 +70,13 @@ const Search: NextPageWithLayout = () => { message: 'Search', }); + const loadMorePosts = () => { + if (lastPostRef.current) { + lastPostRef.current.focus(); + } + setSize(size + 1); + }; + return ( <> <Head> @@ -80,11 +88,12 @@ const Search: NextPageWithLayout = () => { > <PostHeader title={title} /> <div className={styles.body}> - <PostsList data={data} showYears={false} /> + <PostsList ref={lastPostRef} data={data} showYears={false} /> {hasNextPage && ( <Button isDisabled={isLoadingMore} - clickHandler={() => setSize(size + 1)} + clickHandler={loadMorePosts} + position="center" >{t`Load more?`}</Button> )} </div> |
