diff --git a/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx b/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx index f64bf7cad..61df6d708 100644 --- a/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx +++ b/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx @@ -17,7 +17,9 @@ import { totalRoadmapNodes } from '../../stores/roadmap.ts'; type FlowRoadmapRendererProps = { isEmbed?: boolean; - roadmap: RoadmapDocument; + roadmap: RoadmapDocument & { + canManage?: boolean + }; }; export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) { @@ -159,7 +161,7 @@ export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) { {hideRenderer && ( <EmptyRoadmap roadmapId={roadmapId} - canManage={roadmap.canManage} + canManage={roadmap.canManage || false} className="grow" /> )} diff --git a/src/components/RoadmapTitleQuestion.tsx b/src/components/RoadmapTitleQuestion.tsx index fc14bb0e2..82096a0f0 100644 --- a/src/components/RoadmapTitleQuestion.tsx +++ b/src/components/RoadmapTitleQuestion.tsx @@ -8,24 +8,43 @@ import { import { useRef, useState } from 'react'; import { useOutsideClick } from '../hooks/use-outside-click'; import { markdownToHtml } from '../lib/markdown'; +import { cn } from '../lib/classname'; +import { useScrollPosition } from '../hooks/use-scroll-position'; type RoadmapTitleQuestionProps = { question: string; answer: string; + roadmapId?: string; }; export function RoadmapTitleQuestion(props: RoadmapTitleQuestionProps) { - const { question, answer } = props; + const { question, answer, roadmapId } = props; const [isAnswerVisible, setIsAnswerVisible] = useState(false); const ref = useRef<HTMLDivElement>(null); + const h2Ref = useRef<HTMLHeadingElement>(null); useOutsideClick(ref, () => { setIsAnswerVisible(false); }); + const { y: scrollY } = useScrollPosition(); + return ( - <div className="relative hidden rounded-b-[5px] border-t bg-white text-sm font-medium hover:bg-gray-50 sm:block"> + <div + className={cn( + 'relative hidden rounded-b-[5px] border-t bg-white text-sm font-medium hover:bg-gray-50 sm:block', + { + 'rounded-0 -mx-4 sm:mx-0': isAnswerVisible, + // @FIXME: + // The line below is to keep the question hidden on mobile devices except for + // the frontend roadmap. This is because we did not use to have the question + // on mobile devices before and we don't want to cause any SEO issues. It will + // be enabled on other roadmaps in the future. + block: roadmapId === 'frontend', + }, + )} + > {isAnswerVisible && ( <div className="fixed left-0 right-0 top-0 z-[100] h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50"></div> )} @@ -47,15 +66,25 @@ export function RoadmapTitleQuestion(props: RoadmapTitleQuestionProps) { </h2> <div - className={`absolute left-0 right-0 top-0 z-[100] mt-0 rounded-md border bg-white ${ - isAnswerVisible ? 'block' : 'hidden' + className={`absolute left-0 right-0 top-0 z-[100] mt-0 border bg-white ${ + isAnswerVisible ? 'rounded-0 block sm:rounded-md' : 'hidden' }`} ref={ref} > {isAnswerVisible && ( <h2 - className="flex cursor-pointer select-none items-center border-b px-[7px] py-[9px] text-base font-medium" - onClick={() => setIsAnswerVisible(false)} + className={cn( + 'sticky top-0 flex cursor-pointer select-none items-center rounded-t-md border-b bg-white px-[7px] py-[9px] text-base font-medium', + )} + onClick={() => { + setIsAnswerVisible(false); + if ( + scrollY > (h2Ref?.current?.getBoundingClientRect().top || 0) + ) { + ref.current?.scrollIntoView(); + } + }} + ref={h2Ref} > <span className="flex flex-grow items-center"> <Info className="mr-2 inline-block h-4 w-4" strokeWidth={2.5} /> @@ -67,7 +96,7 @@ export function RoadmapTitleQuestion(props: RoadmapTitleQuestionProps) { </h2> )} <div - className="bg-gray-100 p-3 text-base [&>h2]:mb-2 [&>h2]:mt-5 [&>h2]:text-[17px] [&>h2]:font-medium [&>p:last-child]:mb-0 [&>p>a]:font-semibold [&>p>a]:underline [&>p>a]:underline-offset-2 [&>p]:mb-3 [&>p]:font-normal [&>p]:leading-relaxed [&>p]:text-gray-800" + className="bg-gray-100 p-3 text-base [&>h2]:mb-2 [&>h2]:mt-5 [&>h2]:text-[17px] [&>h2]:font-medium [&>p:last-child]:mb-0 [&>p>a]:font-semibold [&>p>a]:underline [&>p>a]:underline-offset-2 [&>p]:mb-3 [&>p]:font-normal [&>p]:leading-relaxed [&>p]:text-gray-800 [&>ul>li]:mb-2 [&>ul>li]:font-normal" dangerouslySetInnerHTML={{ __html: markdownToHtml(answer, false) }} ></div> </div> diff --git a/src/pages/[roadmapId]/index.astro b/src/pages/[roadmapId]/index.astro index 78d4c926a..524508bcb 100644 --- a/src/pages/[roadmapId]/index.astro +++ b/src/pages/[roadmapId]/index.astro @@ -123,6 +123,7 @@ const projects = await getProjectsByRoadmapId(roadmapId); question?.title && ( <RoadmapTitleQuestion client:load + roadmapId={roadmapId} question={question?.title} answer={question?.description} />