an open-source education platform

Quizzes and Tabs

Two more built-in components: <question> for multiple-choice quizzes and surveys, and <tabs-container> for grouped content with switchable views.


Quizzes

A quiz is a <question> block with one or more <answer> children. Marking an answer as correct makes it the right answer.

Single-choice (radio buttons)

<question id="q-single-demo" type="single">
  <p>Which keyword defines a function in Python?</p>
  <answer>function</answer>
  <answer correct>def</answer>
  <answer>fn</answer>
  <answer>lambda</answer>
</question>

Renders as:

Students see a list with radio buttons; can pick one. Click Check to see if it's right.

Multi-choice (checkboxes)

<question id="q-multi-demo" type="multi">
  <p>Which of these are immutable in Python?</p>
  <answer correct>tuple</answer>
  <answer>list</answer>
  <answer correct>str</answer>
  <answer correct>frozenset</answer>
  <answer>dict</answer>
</question>

Renders as:

Students must pick all and only the correct answers to be marked correct.

Free-text answer

<question id="q-text-demo" type="text">
  <p>What is the output of <code>print(2 ** 10)</code>?</p>
  <answer correct>1024</answer>
</question>

Renders as:

Student types an answer; case-insensitive comparison against the correct answer(s). You can list multiple <answer correct> to accept variations:

<question id="q-text-variants-demo" type="text">
  <p>What is the capital of Switzerland?</p>
  <answer correct>Bern</answer>
  <answer correct>Berne</answer>
</question>

Renders as:

A different free-text mechanism exists too

This is exact/variant string matching for short factual answers. For grading a student's predicted output of a piece of code — with partial credit and a diff, rather than exact match — see the predict-output variant of <question type="text"> in Code Editors & Scoring. Same tag, different purpose.

Question attributes

AttributeValuesEffect
idstringUnique ID per page; used to track student responses
typesingle / multi / text / number / rangeQuestion style
pointsnumber (default 1)Score weight
feedback-correctstringCustom message shown on correct answer
feedback-incorrectstringCustom message shown on incorrect answer
<question id="q-feedback-demo" type="single" points="2"
          feedback-correct="Genau! In Python ist `def` das Schlüsselwort."
          feedback-incorrect="Hinweis: Die Antwort beginnt mit dem Buchstaben d.">
  <p>Welches Schlüsselwort definiert eine Funktion in Python?</p>
  <answer>function</answer>
  <answer correct>def</answer>
  <answer>fn</answer>
</question>

Renders as:

Welches Schlüsselwort definiert eine Funktion in Python?

function def fn

What students see

  • Question text + answer choices
  • Check button to submit
  • ✓ green or ✗ red feedback after submitting
  • Custom feedback message (if set)
  • Score for that question

Their answer is saved per-student-per-page; coming back later shows their previous response.


Scoring options

points (default 1) sets a question's score weight — the max points it contributes. How a question earns those points depends on its type:

  • single / multi auto-score full points on an exact match against the correct answer(s) — no partial credit for choice questions.
  • text auto-scores on a case-insensitive match against any <answer correct> variant.
  • Sliders (number / range) auto-grade against a target, with banded partial credit:
<question id="q-slope-demo" type="number" points="2" expected="-1" tolerance="0.15">
  <p>What is the slope of the line shown in the plot?</p>
  <answer from="0.9" feedback="Exact, or close enough to count as exact."></answer>
  <answer from="0.5" feedback="Right direction, but check your calculation."></answer>
</question>

type="number" expected="-1" tolerance="0.15" sets a single target value with a tolerance band; type="range" expected="-1..1" instead accepts any answer in that range. <answer from="..."> bands go from best to worst — the first one the student's answer clears (reading top to bottom) determines their feedback and partial score.

All auto-scored results are teacher-overridable when scoring — see below.


Surveys (ungraded questions)

Not every question needs a right answer. A <question> with no <answer correct> (or no scored slider target) collects a response without grading it — useful for opinion polls, "how confident do you feel about this topic," or exit tickets. Students still see their own past response when they return; there's just no ✓/✗ feedback because there's nothing to be right or wrong about.


What you can see as the teacher

For students signed in to a class, quiz responses feed into the same submissions view as auto-scored code (see Code Editors & Scoring):

  • Submissions interface (Dashboard → Classes → Submissions) — each student's answers and score, per question
  • Per-student detail — see exactly what they selected or typed
  • Numeric overrides — adjust the auto-scored points for a question, e.g. to award partial credit a slider band didn't quite capture
  • Comments — leave feedback per submission

Auto-scored quiz results sit alongside python-check and predict-output results in the same review flow, so you get one place to see how a student did across an entire page rather than jumping between component types.


Tabs

Tabbed containers group related content with switchable views. Useful for: language alternatives, OS-specific instructions, beginner/advanced versions of the same content, before/after comparisons.

Basic syntax

<tabs-container>
  <tab-item label="Python">
    Standard Python solution.

    ```python
    print("Hello")
    ```
  </tab-item>

  <tab-item label="JavaScript">
    JavaScript equivalent.

    ```javascript
    console.log("Hello")
    ```
  </tab-item>

  <tab-item label="Rust">
    Rust version (compiled).

    ```rust
    println!("Hello");
    ```
  </tab-item>
</tabs-container>

Renders as:

Standard Python solution.

print("Hello")

JavaScript equivalent.

console.log("Hello")

Rust version (compiled).

println!("Hello");

Students see a tab bar at the top with the three labels; clicking switches between them.

Tabs can hold any content

Markdown, code blocks, code editors, callouts, images, math — anything that works in the body of a page works inside a <tab-item>.

<tabs-container>
  <tab-item label="Description">
    The Pythagorean theorem states that for a right triangle:
    $a^2 + b^2 = c^2$
  </tab-item>

  <tab-item label="Try it">
    ```python editor id="pythagoras"
    a, b = 3, 4
    c = (a**2 + b**2) ** 0.5
    print(f"c = {c}")
    ```
  </tab-item>

  <tab-item label="Proof">
    > [!example] Geometric proof
    > Take four right triangles with legs $a$ and $b$ ...
  </tab-item>
</tabs-container>

Default open tab

Add default to one tab to make it open initially (otherwise the first tab is open by default):

<tabs-container>
  <tab-item label="macOS">macOS instructions</tab-item>
  <tab-item label="Windows" default>Windows instructions</tab-item>
  <tab-item label="Linux">Linux instructions</tab-item>
</tabs-container>

Tabs cheat sheet

GoalSyntax
Tabbed container<tabs-container>...</tabs-container>
Individual tab<tab-item label="Label">content</tab-item>
Default open tab<tab-item label="..." default>
Embed a code editor in a tabStandard ```python editor inside the <tab-item>

When to use which

SituationUse
Test a student's recall of a fact<question type="single"> or type="text">
Test programming behaviorpython editor + python-check (Code Editors & Scoring)
Test tracing/predicting code output<question type="text"> with an ```expected block (Code Editors & Scoring)
Collect opinion, no right answer<question> with no correct answer (survey)
Show the same content in multiple flavors<tabs-container>
Hide hint until clickedCollapsed callout (> [!tip]-)
Hide a long solutionCollapsed callout with code block

For self-scoring code exercises, python-check is much more powerful than <question>. For factual recall and discrete-answer questions, <question> is faster to write.