mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-22 10:33:22 +00:00
Fix scroll to hash and update next to 14.1.3 (#286)
* Update next to 14.1.3 * Scroll to hash when url changes * Simplify tests * Lint and format * Fix TS * Dummy comment * Try async function
This commit is contained in:
@@ -111,15 +111,16 @@ export function Block<T extends DocumentBlock>(props: BlockProps<T>) {
|
||||
|
||||
function BlockPlaceholder(props: { block: DocumentBlock; style: ClassValue }) {
|
||||
const { block, style } = props;
|
||||
const id = 'meta' in block && block.meta && 'id' in block.meta ? block.meta.id : undefined;
|
||||
|
||||
switch (block.type) {
|
||||
case 'heading-1':
|
||||
case 'heading-2':
|
||||
case 'heading-3':
|
||||
case 'file':
|
||||
return <SkeletonHeading style={style} />;
|
||||
return <SkeletonHeading id={id} style={style} />;
|
||||
case 'paragraph':
|
||||
return <SkeletonSmall style={style} />;
|
||||
return <SkeletonSmall id={id} style={style} />;
|
||||
case 'list-ordered':
|
||||
case 'list-unordered':
|
||||
case 'list-tasks':
|
||||
@@ -129,7 +130,7 @@ function BlockPlaceholder(props: { block: DocumentBlock; style: ClassValue }) {
|
||||
case 'hint':
|
||||
case 'tabs':
|
||||
case 'synced-block':
|
||||
return <SkeletonParagraph style={style} />;
|
||||
return <SkeletonParagraph id={id} style={style} />;
|
||||
case 'expandable':
|
||||
case 'table':
|
||||
case 'swagger':
|
||||
@@ -137,17 +138,17 @@ function BlockPlaceholder(props: { block: DocumentBlock; style: ClassValue }) {
|
||||
case 'divider':
|
||||
case 'content-ref':
|
||||
case 'integration':
|
||||
return <SkeletonCard style={style} />;
|
||||
return <SkeletonCard id={id} style={style} />;
|
||||
case 'embed':
|
||||
case 'images':
|
||||
case 'drawing':
|
||||
return <SkeletonImage style={style} />;
|
||||
return <SkeletonImage id={id} style={style} />;
|
||||
case 'image':
|
||||
case 'code-line':
|
||||
case 'tabs-item':
|
||||
throw new Error('Blocks should be directly rendered by parent');
|
||||
case 'integration':
|
||||
return <SkeletonCard style={style} />;
|
||||
return <SkeletonCard id={id} style={style} />;
|
||||
default:
|
||||
assertNever(block);
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './useScrollActiveId';
|
||||
export * from './useScrollToHash';
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useParams } from 'next/navigation';
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Scroll to the current URL hash everytime the URL changes.
|
||||
*/
|
||||
export function useScrollToHash() {
|
||||
const params = useParams();
|
||||
|
||||
const scrollToHash = React.useCallback(() => {
|
||||
const hash = window.location.hash;
|
||||
if (hash) {
|
||||
const element = document.getElementById(hash.slice(1));
|
||||
if (element) {
|
||||
element.scrollIntoView({
|
||||
block: 'start',
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
// With next.js, the hashchange event is not triggered when the hash changes
|
||||
// Instead a hack is to use the `useParams` hook to listen to changes in the hash
|
||||
// https://github.com/vercel/next.js/discussions/49465#discussioncomment-5845312
|
||||
React.useEffect(() => {
|
||||
scrollToHash();
|
||||
}, [params, scrollToHash]);
|
||||
}
|
||||
@@ -6,10 +6,10 @@ import { LoadingPane } from './LoadingPane';
|
||||
* Placeholder to be used when a content is not yet loaded (in a React.Suspense boundary).
|
||||
* It's used when streaming the content of a page.
|
||||
*/
|
||||
export function SkeletonParagraph(props: { style?: ClassValue }) {
|
||||
const { style } = props;
|
||||
export function SkeletonParagraph(props: { id?: string; style?: ClassValue }) {
|
||||
const { id, style } = props;
|
||||
return (
|
||||
<div role="status" aria-busy className="skeleton-paragraph">
|
||||
<div id={id} role="status" aria-busy className="skeleton-paragraph">
|
||||
<LoadingPane
|
||||
style={[
|
||||
'rounded-md',
|
||||
@@ -25,10 +25,10 @@ export function SkeletonParagraph(props: { style?: ClassValue }) {
|
||||
/**
|
||||
* Placeholder when loading a title.
|
||||
*/
|
||||
export function SkeletonHeading(props: { style?: ClassValue }) {
|
||||
const { style } = props;
|
||||
export function SkeletonHeading(props: { id?: string; style?: ClassValue }) {
|
||||
const { id, style } = props;
|
||||
return (
|
||||
<div role="status" aria-busy className="skeleton-heading">
|
||||
<div id={id} role="status" aria-busy className="skeleton-heading">
|
||||
<LoadingPane
|
||||
tile={12}
|
||||
style={['rounded-md', 'h-[47px]', '[max-width:calc(48rem-1px)]', style]}
|
||||
@@ -40,10 +40,10 @@ export function SkeletonHeading(props: { style?: ClassValue }) {
|
||||
/**
|
||||
* Placeholder when loading an asset (image, video, etc.)
|
||||
*/
|
||||
export function SkeletonImage(props: { style?: ClassValue }) {
|
||||
const { style } = props;
|
||||
export function SkeletonImage(props: { id?: string; style?: ClassValue }) {
|
||||
const { id, style } = props;
|
||||
return (
|
||||
<div role="status" aria-busy className="skeleton-image">
|
||||
<div id={id} role="status" aria-busy className="skeleton-image">
|
||||
<LoadingPane
|
||||
tile={96}
|
||||
style={[
|
||||
@@ -61,10 +61,15 @@ export function SkeletonImage(props: { style?: ClassValue }) {
|
||||
/**
|
||||
* Placeholder when loading a card
|
||||
*/
|
||||
export function SkeletonCard(props: { style?: ClassValue }) {
|
||||
const { style } = props;
|
||||
export function SkeletonCard(props: { id?: string; style?: ClassValue }) {
|
||||
const { id, style } = props;
|
||||
return (
|
||||
<div role="status" aria-busy className={tcls('skeleton-card', 'flex', 'gap-[25px]', style)}>
|
||||
<div
|
||||
id={id}
|
||||
role="status"
|
||||
aria-busy
|
||||
className={tcls('skeleton-card', 'flex', 'gap-[25px]', style)}
|
||||
>
|
||||
<LoadingPane tile={24} delay={0} style={['rounded-md', 'aspect-[1/1.2]', 'w-full']} />
|
||||
<LoadingPane tile={24} delay={1} style={['rounded-md', 'aspect-[1/1.2]', 'w-full']} />
|
||||
<LoadingPane tile={24} delay={2} style={['rounded-md', 'aspect-[1/1.2]', 'w-full']} />
|
||||
@@ -75,10 +80,10 @@ export function SkeletonCard(props: { style?: ClassValue }) {
|
||||
/**
|
||||
* Placeholder when loading small elements
|
||||
*/
|
||||
export function SkeletonSmall(props: { style?: ClassValue }) {
|
||||
const { style } = props;
|
||||
export function SkeletonSmall(props: { id?: string; style?: ClassValue }) {
|
||||
const { id, style } = props;
|
||||
return (
|
||||
<div role="status" aria-busy className="skeleton-small">
|
||||
<div id={id} role="status" aria-busy className="skeleton-small">
|
||||
<LoadingPane
|
||||
tile={12}
|
||||
style={['rounded-md', 'h-[35px]', '[max-width:calc(48rem-1px)]', style]}
|
||||
|
||||
Reference in New Issue
Block a user