Quiz
Quiz
The Quiz component displays an interactive quiz with multiple-choice questions. It supports random question selection, immediate feedback, explanations, and score tracking. Perfect for educational content and knowledge testing.
Basic Usage
import Quiz from '@site/src/components/Quiz';
import quizData from '@site/src/data/quiz-demo.json';
<Quiz quizData={quizData} />
Live Preview:
Cardano Basics Quiz
Test your Cardano knowledge with this short quiz.
What is an address on Cardano?
Props
| Prop | Type | Default | Description |
|---|---|---|---|
quizData | object | required | Quiz data object containing questions and metadata |
questionCount | number | 5 | Number of questions to randomly select from the quiz |
allowRetry | boolean | true | Whether users can retry an incorrect answer before moving to the next question |
passingScore | number | 60 | Minimum percentage required to pass (0-100) |
onRecord | function | null | (correct, total) => void, called once when the quiz finishes. Passing a function switches the component into hub mode, see Hub Mode below |
academyCta | object | null | {href, label, certifiedLabel, ariaLabel} shown as a follow-up link on the hub mode result screen. Build it with getAcademyCta(academyKey, quizId) from src/data/quiz/academy.js. label (with ariaLabel naming the destination) is used for a learning or bronze result, certifiedLabel for silver and gold. Ignored outside hub mode |
Quiz Data Format
The quiz component expects a JSON file with the following structure:
{
"title": "Quiz Title",
"description": "Optional description of the quiz",
"questions": [
{
"id": 1,
"question": "What is a dapp?",
"options": [
"A decentralized application running on a blockchain",
"A car company",
"A database error",
"A food delivery service"
],
"correctAnswer": 0,
"explanation": "A dapp is a decentralized application..."
}
]
}
Field Descriptions
- title (string, optional): Main title displayed above the quiz
- description (string, optional): Brief description shown below the title
- questions (array, required): Array of question objects
- id (number): Unique identifier for the question
- question (string): The question text
- options (array of strings): 3 to 4 answer choices (displayed as A, B, C, D)
- correctAnswer (number): Index of the correct option, 0-based
- explanation (string, optional): Explanation shown after answering
- sourceUrl (string, optional): Link rendered as "Learn more" under the explanation, opens in a new tab. Required for hub quizzes, see the pipeline for the allowed hosts
Features
Random Question Selection
- Automatically selects random questions from the provided data
- Control the number of questions with
questionCountprop - Each quiz session shows different questions (if pool is large enough)
Interactive Feedback
- Visual states: Questions cards change color based on correct/incorrect answers
- Immediate feedback: Shows whether answer is correct or incorrect
- Explanations: Optional detailed explanations after each answer
- Try again: Allows retry on incorrect answers (configurable via
allowRetryprop)
Progress Tracking
- Progress bar: Visual indicator showing current question position
- Score tracking: Calculates final score as percentage
- Results screen: Shows final score with pass/fail indication (configurable via
passingScoreprop)
Answer Randomization
- Shuffled options: Answer positions vary for each question to prevent pattern memorization
- Shuffled questions: Random question selection from the pool each session
Visual Design
- Color-coded states:
- Green: Correct answers
- Red: Incorrect answers
- Purple: Selected (before checking)
- Gray: Unselected
- Icons: Checkmark for correct, X for incorrect
- Smooth transitions: All state changes are animated
Examples
Basic Quiz (5 Questions)
<Quiz quizData={quizData} questionCount={5} />
Full Quiz (All Questions)
To show all available questions, set questionCount to a high number:
<Quiz quizData={quizData} questionCount={100} />
Quiz Without Retry Option
Disable the retry button for incorrect answers:
<Quiz quizData={quizData} allowRetry={false} />
Cardano Basics Quiz
Test your Cardano knowledge with this short quiz.
What is a "dapp"?
Custom Passing Score
Set a higher passing threshold (e.g., 80%):
<Quiz quizData={quizData} passingScore={80} />
Cardano Basics Quiz
Test your Cardano knowledge with this short quiz.
What does "immutable ledger" mean?
Strict Quiz Mode
Combine no retry with a high passing score:
<Quiz quizData={quizData} allowRetry={false} passingScore={80} />
Cardano Basics Quiz
Test your Cardano knowledge with this short quiz.
What does "immutable ledger" mean?
Scam Awareness Quiz
Using the scam awareness quiz (10 questions):
import scamQuiz from '@site/src/data/quiz-scams.json';
<Quiz quizData={scamQuiz} questionCount={5} passingScore={80} />
Common Scams Awareness Quiz
Test your knowledge about common scams in the blockchain space and how to protect yourself.
Once you send ada to a scammer, what are your chances of recovery?
Hub Mode
Passing an onRecord function switches Quiz into hub mode. The results screen always shows the segmented green and red progress bar every result screen uses. On top of that, a run scoring 60 percent or higher also gets a rendered result badge image (bronze, silver, or gold), a share button for that badge, and an optional academy call-to-action. A run below 60 percent gets a fourth "learning" state instead: no badge and no share button, but the "Keep learning" tier pill, the score text, the bar, and an encouragement to try again.
import Quiz from '@site/src/components/Quiz';
import useQuizProgress from '@site/src/utils/useQuizProgress';
import { getQuizCatalog } from '@site/src/data/quiz/catalog';
import { getAcademyCta } from '@site/src/data/quiz/academy';
const { record } = useQuizProgress();
const entry = getQuizCatalog()[0];
const quizData = entry.getData();
<Quiz
quizData={quizData}
questionCount={quizData.questionCount}
allowRetry={false}
onRecord={(correct, total) => record(entry.id, correct, total)}
academyCta={getAcademyCta(entry.academyKey, entry.id)}
/>
The owner pattern
useQuizProgress reads and writes a single localStorage entry that covers every quiz on the hub. Instantiate it exactly once, in the page or hub component that owns the overall progress state, never inside Quiz itself, which stays unaware of storage or quiz identity entirely. The QuizHub component is the reference implementation: it holds the one useQuizProgress instance and hands each quiz card its own scoped callback:
onRecord={(correct, total) => record(entry.id, correct, total)}
Quiz only ever reports a result up through whatever callback its owner gave it. This keeps the engine reusable and testable without pulling storage concerns into it.
Why hub quizzes disable retry
Hub quizzes pass allowRetry={false}. The allowRetry prop lets a user retry a single question immediately after answering it wrong, before moving on, within the same run. If that were allowed in hub mode, a user could keep retrying every missed question until they got it right and always walk away with a perfect score, which would make the gold tier meaningless. Classic (non-hub) usage keeps allowRetry at its default of true, since there is no tier or share step to protect there.
Classic usage is unchanged
Outside hub mode, Quiz behaves exactly as it always has: onRecord and academyCta default to null, no tier badge or share button appears, and restarting the quiz reuses the same sampled question set rather than drawing a new one. Hub mode resamples on restart instead, so a repeat attempt at gold pulls a fresh set of questions from the pool.