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:
Samy Pessé
2024-03-18 07:55:30 +00:00
committed by GitHub
parent 9e8cde48d4
commit a27fa68ae6
10 changed files with 80 additions and 111 deletions
+7 -6
View File
@@ -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
View File
@@ -1 +1,2 @@
export * from './useScrollActiveId';
export * from './useScrollToHash';
+29
View File
@@ -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]);
}
+20 -15
View File
@@ -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]}