diff --git a/beta/src/components/MDX/Challenges/Challenge.tsx b/beta/src/components/MDX/Challenges/Challenge.tsx
index 82b3535ce..24e99541c 100644
--- a/beta/src/components/MDX/Challenges/Challenge.tsx
+++ b/beta/src/components/MDX/Challenges/Challenge.tsx
@@ -9,6 +9,7 @@ import {ChallengeContents} from './Challenges';
import {IconHint} from '../../Icon/IconHint';
import {IconSolution} from '../../Icon/IconSolution';
import {IconArrowSmall} from '../../Icon/IconArrowSmall';
+import {H4} from '../Heading';
interface ChallengeProps {
isRecipes?: boolean;
@@ -45,14 +46,16 @@ export function Challenge({
return (
-
+
{isRecipes ? 'Example' : 'Challenge'} {currentChallenge.order} of{' '}
{totalChallenges}
:
{currentChallenge.name}
-
+
{currentChallenge.content}
diff --git a/beta/src/components/MDX/Challenges/Challenges.tsx b/beta/src/components/MDX/Challenges/Challenges.tsx
index 70df4228b..25b1979fd 100644
--- a/beta/src/components/MDX/Challenges/Challenges.tsx
+++ b/beta/src/components/MDX/Challenges/Challenges.tsx
@@ -9,6 +9,7 @@ import {H2} from 'components/MDX/Heading';
import {H4} from 'components/MDX/Heading';
import {Challenge} from './Challenge';
import {Navigation} from './Navigation';
+import {useRouter} from 'next/router';
interface ChallengesProps {
children: React.ReactElement[];
@@ -67,6 +68,11 @@ const parseChallengeContents = (
return contents;
};
+enum QueuedScroll {
+ INIT = 'init',
+ NEXT = 'next',
+}
+
export function Challenges({
children,
isRecipes,
@@ -76,19 +82,32 @@ export function Challenges({
const challenges = parseChallengeContents(children);
const totalChallenges = challenges.length;
const scrollAnchorRef = useRef(null);
- const queuedScrollRef = useRef(false);
+ const queuedScrollRef = useRef(QueuedScroll.INIT);
const [activeIndex, setActiveIndex] = useState(0);
const currentChallenge = challenges[activeIndex];
+ const {asPath} = useRouter();
useEffect(() => {
- if (queuedScrollRef.current === true) {
- queuedScrollRef.current = false;
+ if (queuedScrollRef.current === QueuedScroll.INIT) {
+ const initIndex = challenges.findIndex(
+ (challenge) => challenge.id === asPath.split('#')[1]
+ );
+ if (initIndex === -1) {
+ queuedScrollRef.current = undefined;
+ } else if (initIndex !== activeIndex) {
+ setActiveIndex(initIndex);
+ }
+ }
+ if (queuedScrollRef.current) {
scrollAnchorRef.current!.scrollIntoView({
block: 'start',
- behavior: 'smooth',
+ ...(queuedScrollRef.current === QueuedScroll.NEXT && {
+ behavior: 'smooth',
+ }),
});
+ queuedScrollRef.current = undefined;
}
- });
+ }, [activeIndex, asPath, challenges]);
const handleChallengeChange = (index: number) => {
setActiveIndex(index);
@@ -129,7 +148,7 @@ export function Challenges({
hasNextChallenge={activeIndex < totalChallenges - 1}
handleClickNextChallenge={() => {
setActiveIndex((i) => i + 1);
- queuedScrollRef.current = true;
+ queuedScrollRef.current = QueuedScroll.NEXT;
}}
/>
diff --git a/beta/src/components/MDX/ExpandableExample.tsx b/beta/src/components/MDX/ExpandableExample.tsx
index 2baf9b4ec..5cb731532 100644
--- a/beta/src/components/MDX/ExpandableExample.tsx
+++ b/beta/src/components/MDX/ExpandableExample.tsx
@@ -9,6 +9,8 @@ import {IconDeepDive} from '../Icon/IconDeepDive';
import {IconCodeBlock} from '../Icon/IconCodeBlock';
import {Button} from '../Button';
import {H4} from './Heading';
+import {useRouter} from 'next/router';
+import {useEffect, useRef, useState} from 'react';
interface ExpandableExampleProps {
children: React.ReactNode;
@@ -17,15 +19,29 @@ interface ExpandableExampleProps {
}
function ExpandableExample({children, excerpt, type}: ExpandableExampleProps) {
- const [isExpanded, setIsExpanded] = React.useState(false);
- const isDeepDive = type === 'DeepDive';
- const isExample = type === 'Example';
-
if (!Array.isArray(children) || children[0].type.mdxName !== 'h4') {
throw Error(
`Expandable content ${type} is missing a corresponding title at the beginning`
);
}
+ const isDeepDive = type === 'DeepDive';
+ const isExample = type === 'Example';
+ const id = children[0].props.id;
+
+ const queuedExpandRef = useRef
(true);
+ const {asPath} = useRouter();
+ // init as expanded to prevent flash
+ const [isExpanded, setIsExpanded] = useState(true);
+
+ // asPath would mismatch between server and client, reset here instead of put it into init state
+ useEffect(() => {
+ if (queuedExpandRef.current) {
+ queuedExpandRef.current = false;
+ if (id !== asPath.split('#')[1]) {
+ setIsExpanded(false);
+ }
+ }
+ }, [asPath, id]);
return (
{children[0].props.children}