Start prev/next navigation

This commit is contained in:
Samy Pessé
2023-10-24 18:48:37 +02:00
parent cfb197067a
commit cde014a355
3 changed files with 101 additions and 0 deletions
+2
View File
@@ -1,6 +1,7 @@
import { Revision, RevisionPageDocument, Space } from '@gitbook/api';
import { PageHeader } from './PageHeader';
import { PageDocument } from './PageDocument';
import { PageFooterNavigation } from './PageFooterNavigation';
export function PageBody(props: { space: Space; revision: Revision; page: RevisionPageDocument }) {
const { space, revision, page } = props;
@@ -9,6 +10,7 @@ export function PageBody(props: { space: Space; revision: Revision; page: Revisi
<main>
<PageHeader page={page} />
<PageDocument space={space} revision={revision} page={page} />
<PageFooterNavigation revision={revision} page={page} />
</main>
);
}
@@ -0,0 +1,60 @@
import { pageHref } from "@/lib/links";
import { resolvePrevNextPages } from "@/lib/pages";
import { tcls } from "@/lib/tailwind";
import { Revision, RevisionPageDocument } from "@gitbook/api";
import Link from "next/link";
/**
* Show cards to go to previous/next pages at the bottom.
*/
export function PageFooterNavigation(props: {
revision: Revision;
page: RevisionPageDocument;
}) {
const { revision, page } = props;
const { previous, next } = resolvePrevNextPages(revision, page);
return (
<div className={tcls('flex', 'flex-row', 'mt-6', 'gap-2')}>
{previous ? (
<NavigationCard
icon="P"
label="Previous"
title={previous.title}
href={pageHref(previous.path)}
reversed
/>
) : null}
{next ? (
<NavigationCard
icon="N"
label="Next"
title={next.title}
href={pageHref(next.path)}
/>
) : null}
</div>
)
}
function NavigationCard(props: {
icon: React.ReactNode;
label: string;
title: string;
href: string;
reversed?: boolean;
}) {
const { icon, label, title, href, reversed } = props;
return (
<Link href={href} className={tcls('group', 'flex', 'flex-1', reversed ? 'flex-row-reverse': 'flex-row', 'align-center', 'p-4', 'border', 'border-slate-200', 'rounded', 'hover:shadow', 'hover:border-primary-500')}>
<span className={tcls('flex', 'flex-col', 'flex-1', reversed ? 'text-right' : null)}>
<span className={tcls('text-xs', 'text-slate-400')}>{label}</span>
<span className={tcls('text-base', 'text-slate-700', 'group-hover:text-primary-600')}>{title}</span>
</span>
<span className={tcls('group-hover:text-primary-600')}>
{icon}
</span>
</Link>
)
}
+39
View File
@@ -73,6 +73,29 @@ export function resolvePageId(
return iteratePages(revision.pages, []);
}
/**
* Resolve the next/previous page before another one.
*/
export function resolvePrevNextPages(
revision: Revision,
page: RevisionPageDocument
): { previous?: RevisionPageDocument; next?: RevisionPageDocument } {
const flat = flattenPages(revision.pages);
const currentIndex = flat.findIndex((p) => p.id === page.id);
if (currentIndex === -1) {
return {};
}
const previous = flat[currentIndex - 1];
const next = flat[currentIndex + 1];
return {
previous, next
};
}
function resolveFirstDocument(
pages: RevisionPage[],
ancestors: AncestorRevisionPage[],
@@ -105,3 +128,19 @@ function resolvePageDocument(
return { page, ancestors };
}
function flattenPages(pages: RevisionPage[]): RevisionPageDocument[] {
const result: RevisionPageDocument[] = [];
for (const page of pages) {
if (page.type === 'link') {
continue;
}
if (page.type === 'document') {
result.push(page);
}
result.push(...flattenPages(page.pages));
}
return result;
}