Skip to content

Commit

Permalink
refactor: move nav to its own file
Browse files Browse the repository at this point in the history
avoids the Next.js RSC boundary warning
  • Loading branch information
aaronmcadam committed Aug 2, 2024
1 parent fc897e2 commit 53f0273
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 91 deletions.
89 changes: 89 additions & 0 deletions src/components/quiz-navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { cn } from "@/lib/utils";
import { CheckIcon } from "lucide-react";
import { QuizQuestion } from "./quiz";

type QuizNavigationProps = {
questions: QuizQuestion[];
onButtonClick: (questionIndex: number) => void;
};

export function QuizNavigation({
questions,
onButtonClick,
}: QuizNavigationProps) {
return (
<nav aria-label="Progress" className="flex flex-col items-center">
<ol role="list" className="flex items-center">
{questions.map((question, questionIndex) => (
<li
key={question.title}
className={cn(
questionIndex !== questions.length - 1 ? "pr-8 sm:pr-20" : "",
"relative",
)}
>
{question.status === "complete" ? (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-brand/50" />
</div>
<button
onClick={() => onButtonClick(questionIndex)}
className="relative flex h-8 w-8 items-center justify-center rounded-full bg-brand-600 hover:bg-brand-300"
>
<CheckIcon
aria-hidden="true"
className="h-5 w-5 text-white"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
) : question.status === "current" ? (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-gray-200" />
</div>
<button
onClick={() => onButtonClick(questionIndex)}
aria-current="step"
className="relative flex h-8 w-8 items-center justify-center rounded-full border-2 border-brand-600 bg-white"
>
<span
aria-hidden="true"
className="h-2.5 w-2.5 rounded-full bg-brand-600"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
) : (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-gray-200" />
</div>
<button
disabled={true}
className="group relative flex h-8 w-8 items-center justify-center rounded-full border-2 border-gray-300 bg-white"
>
<span
aria-hidden="true"
className="h-2.5 w-2.5 rounded-full bg-transparent"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
)}
</li>
))}
</ol>
</nav>
);
}
94 changes: 3 additions & 91 deletions src/components/quiz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import * as React from "react";
import { cn } from "@/lib/utils";
import { Button } from "./ui/button";
import { CheckIcon, CircleCheck } from "lucide-react";
import { CircleCheck } from "lucide-react";
import { QuizNavigation } from "./quiz-navigation";

type Option = {
display: string;
Expand All @@ -17,7 +18,7 @@ type Question = {
options: Option[];
};

type QuizQuestion = {
export type QuizQuestion = {
title: string;
options: Option[];
response: Option | null;
Expand Down Expand Up @@ -131,92 +132,3 @@ export function Quiz() {
</div>
);
}

type QuizNavigationProps = {
questions: QuizQuestion[];
onButtonClick: (questionIndex: number) => void;
};

export function QuizNavigation({
questions,
// This prop raises a warning from Next.js in tsc.
// We can safely ignore it for now as we're not trying to use a server component in this file.
// @see https://github.com/vercel/next.js/discussions/46795
onButtonClick,
}: QuizNavigationProps) {
return (
<nav aria-label="Progress" className="flex flex-col items-center">
<ol role="list" className="flex items-center">
{questions.map((question, questionIndex) => (
<li
key={question.title}
className={cn(
questionIndex !== questions.length - 1 ? "pr-8 sm:pr-20" : "",
"relative",
)}
>
{question.status === "complete" ? (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-brand/50" />
</div>
<button
onClick={() => onButtonClick(questionIndex)}
className="relative flex h-8 w-8 items-center justify-center rounded-full bg-brand-600 hover:bg-brand-300"
>
<CheckIcon
aria-hidden="true"
className="h-5 w-5 text-white"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
) : question.status === "current" ? (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-gray-200" />
</div>
<button
onClick={() => onButtonClick(questionIndex)}
aria-current="step"
className="relative flex h-8 w-8 items-center justify-center rounded-full border-2 border-brand-600 bg-white"
>
<span
aria-hidden="true"
className="h-2.5 w-2.5 rounded-full bg-brand-600"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
) : (
<>
<div
aria-hidden="true"
className="absolute inset-0 flex items-center"
>
<div className="h-0.5 w-full bg-gray-200" />
</div>
<button
disabled={true}
className="group relative flex h-8 w-8 items-center justify-center rounded-full border-2 border-gray-300 bg-white"
>
<span
aria-hidden="true"
className="h-2.5 w-2.5 rounded-full bg-transparent"
/>
<span className="sr-only">{`Question ${questionIndex + 1}`}</span>
</button>
</>
)}
</li>
))}
</ol>
</nav>
);
}

0 comments on commit 53f0273

Please sign in to comment.