Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ components that can be used to build user interfaces for freeCodeCamp projects.

## Installation

- Run the following command to install the library in your app:
- Run the following command to install the library:

```bash
pnpm install @freecodecamp/ui
Expand Down
22 changes: 11 additions & 11 deletions src/quiz-question/quiz-question.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { RadioGroup } from "@headlessui/react";

import type { QuizQuestionAnswer, QuizQuestionProps } from "./types";
import { Answer } from "./answer";
import { QuestionLabel } from "../quiz/question-label";
import { OptionLabel } from "../quiz/option-label";

const QuestionText = ({
question,
Expand All @@ -17,9 +19,7 @@ const QuestionText = ({

return (
<span className="text-foreground-primary flex items-baseline">
<span>{position}.</span>
&nbsp;
{question}
<span>{position}.</span>&nbsp;{question}
</span>
);
};
Expand All @@ -32,7 +32,7 @@ const QuestionText = ({
* but instead, it provides a `selectedAnswer` and an `onChange` props,
* giving the parent component full control over the selection handling logic.
*/
export const QuizQuestion = <AnswerT extends number | string>({
const QuizQuestion = <AnswerT extends number | string>({
question,
answers,
required,
Expand All @@ -44,10 +44,7 @@ export const QuizQuestion = <AnswerT extends number | string>({
const handleChange = (
selectedOption: QuizQuestionAnswer<AnswerT>["value"],
) => {
if (!onChange) {
return;
}

if (!onChange) return;
onChange(selectedOption);
};

Expand All @@ -56,9 +53,6 @@ export const QuizQuestion = <AnswerT extends number | string>({
onChange={handleChange}
aria-required={required}
disabled={disabled}
// `selectedAnswer` should not be `undefined`
// or React will automatically consider QuizQuestion an uncontrolled component
// Ref: https://react.dev/reference/react-dom/components/input#im-getting-an-error-a-component-is-changing-an-uncontrolled-input-to-be-controlled
value={selectedAnswer ?? null}
>
<RadioGroup.Label className="block mb-[20px]">
Expand All @@ -67,6 +61,7 @@ export const QuizQuestion = <AnswerT extends number | string>({

{answers.map(({ value, label, feedback, validation }) => {
const checked = selectedAnswer === value;

return (
<Answer
key={value}
Expand All @@ -82,3 +77,8 @@ export const QuizQuestion = <AnswerT extends number | string>({
</RadioGroup>
);
};

QuizQuestion.QuestionLabel = QuestionLabel;
QuizQuestion.OptionLabel = OptionLabel;

export { QuizQuestion };
19 changes: 19 additions & 0 deletions src/quiz/option-label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { PrismFormatted } from "../prism-formatted";

interface OptionLabelProps {
questionText: string;
}

const removeParagraphTags = (html: string) => html.replace(/^<p>|<\/p>$/g, "");

export const OptionLabel = ({ questionText }: OptionLabelProps) => {
return (
<PrismFormatted
text={removeParagraphTags(questionText)}
useSpan
noAria
getCodeBlockAriaLabel={() => ""}
/>
);
};
10 changes: 10 additions & 0 deletions src/quiz/question-label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";
import { PrismFormatted } from "../prism-formatted";

interface QuestionLabelProps {
question: string;
}

export const QuestionLabel = ({ question }: QuestionLabelProps) => {
return <PrismFormatted text={question} getCodeBlockAriaLabel={() => ""} />;
};
9 changes: 8 additions & 1 deletion src/quiz/quiz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React from "react";

import { QuizQuestion } from "../quiz-question";
import { type QuizProps } from "./types";
import { QuestionLabel } from "./question-label";
import { OptionLabel } from "./option-label";

export const Quiz = <AnswerT extends number | string>({
const Quiz = <AnswerT extends number | string>({
questions,
disabled,
required,
Expand All @@ -23,3 +25,8 @@ export const Quiz = <AnswerT extends number | string>({
</ul>
);
};

Quiz.QuestionLabel = QuestionLabel;
Quiz.OptionLabel = OptionLabel;

export { Quiz };