An end-of-lesson knowledge check: a two-column header, a three-figure strip for questions, pass mark, and attempts, a graded quiz that swaps itself for a score and a per-question review, and a list of readings for whatever went wrong.
An end-of-lesson knowledge check: a two-column header, a three-figure strip for questions, pass mark and attempts, a graded quiz, and a list of readings for whatever went wrong.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/education102"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/education102"That installs the block file, the badge23 eyebrow and button21 action button it is built from, and the questionnaire primitive. The quiz, the grading, and the review all live in the block file itself, so there is nothing else to wire up.
import { Education102, education102Demo } from "@/components/beste/block/education102";
export default function Page() {
return <Education102 {...education102Demo} />;
}import { Education102 } from "@/components/beste/block/education102";
export default function Page() {
return (
<Education102
badge={{ label: "Module 3" }}
heading="Check what stuck before you move on"
description="You see the right answer and the reason for it as soon as you finish."
stats={[
{ title: "Questions", value: "5" },
{ title: "To pass", value: "60%" },
{ title: "Attempts", value: "No limit" },
]}
quizHeading="Lesson 3 check"
shortcuts="letters"
passingScore={60}
labels={{ submit: "Finish quiz", passed: "Passed. Lesson 4 is unlocked." }}
questions={[
{
name: "label",
title: "What gives a text input its accessible name?",
answer: "label",
explanation: "Only a label element is exposed as the field's name.",
choices: [
{ value: "label", label: "A label pointing at the input's id" },
{ value: "placeholder", label: "The placeholder attribute" },
],
},
{
name: "grouping",
title: "Which of these belong around a set of radio buttons?",
answer: ["fieldset", "legend"],
choices: [
{ value: "fieldset", label: "A fieldset element" },
{ value: "legend", label: "A legend element" },
{ value: "table", label: "A table element" },
],
},
]}
resourcesTitle="If a question caught you out"
resources={[
{
title: "Naming form controls",
description: "Labels, legends, and the three things that are not a name.",
href: "https://beste.co",
},
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | Badge | – | Eyebrow above the rule, rendered with Badge23. |
heading | string | – | Section heading. |
description | string | – | Section description under the heading. |
stats | StatItem[] | [] | The three-figure strip between the header and the quiz, each figure under its own hairline. |
quizHeading | string | – | Heading above the quiz. |
quizDescription | string | – | Description under that heading. |
questions | QuizQuestion[] | [] | The questions and their answer keys. |
shortcuts | "letters" | "numbers" | – | Prints a shortcut on every choice of the active question. |
passingScore | number | – | Percent needed to pass. Omit to grade without a pass or fail line. |
showAnswerKey | boolean | true | Prints the right answer and the explanation in the review. |
labels | QuizLabels | {} | Overrides for the navigation, score, and review copy. |
resourcesTitle | string | – | Heading above the readings list. |
resources | ResourceLink[] | [] | Hairline rows of follow-up reading below the quiz. |
className | string | – | Merged onto the section element. |
type Badge = { label: string };
type StatItem = { title: string; value: string };
type ResourceLink = { title: string; description: string; href: string };
type QuizQuestion = {
name: string;
title: string;
description?: string;
choices?: QuizChoice[];
answer: string | string[];
explanation?: string;
};
type QuizChoice = { value: string; label: string; description?: string };
type QuizLabels = {
previous?: string;
next?: string;
submit?: string;
retry?: string;
scoreTitle?: string;
passed?: string;
failed?: string;
yourAnswer?: string;
correctAnswer?: string;
noAnswer?: string;
};answer decides the shape of the question. A string renders radios and one of them has to match; an array renders checkboxes and the whole set has to match, in any order.explanation underneath.passingScore is set. Without it the quiz still scores, it just does not judge.education101
An academy section with an eyebrow over a hairline rule, a two-column heading, and three course cards that each float a live progress checklist above a category, title, and lesson count.
education13
A rich text lesson reader with structured content blocks including headings, paragraphs, lists, quotes, and code snippets. Perfect for text-based courses and educational documentation.
education25
A gamified leaderboard displaying top learners with rankings, scores, and badges across weekly, monthly, and all-time periods. Perfect for competitive learning platforms and student engagement.
education104
A pillar guide hub whose sticky left column carries the pitch, three facts on hairlines and a seal button, while the right column lists every chapter in numbered rows grouped by part.