Study session
Run a timed study session from createStudySession.
Renders a timed agenda from createStudySession(). Pass session.content (StudySessionContent). The component walks blocks, shows a per-block countdown, and mounts the matching material UI from materials (Quiz, Flashcards, StudyGuide, PracticeProblems, or notes).
Generation stays in edu-sdk. This component does not call createStudySession. Persistence of progress is also app-owned — use onBlockComplete / onSessionComplete if you need hooks.
Generated materials may include optional topics; quiz grades may include byTopic. This runner does not display those fields yet. Pass learnerContext at generation time — see Personalization.
Usage
import { createStudySession } from "edu-sdk";
import { StudySession } from "@edu-sdk/react";
import "@edu-sdk/react/styles.css";
const session = await createStudySession({
model: "google/gemini-3.6-flash",
content,
durationMinutes: 45,
difficulty: "medium",
});
<StudySession
session={session.content}
onBlockComplete={(block, index) => {
// Optional: persist progress
}}
onSessionComplete={() => {
// Optional: mark the session finished
}}
/>Props
type StudySessionProps = {
session: StudySessionContent;
className?: string;
classNames?: StudySessionClassNames;
allowSkip?: boolean; // default true
autoAdvance?: boolean; // default false
renderNotes?: (markdown: string) => ReactNode;
renderQuiz?: (questions: QuizQuestion[]) => ReactNode;
renderFlashcards?: (flashcards: Flashcard[]) => ReactNode;
renderPracticeProblems?: (problems: PracticeProblem[]) => ReactNode;
renderStudyGuide?: (studyGuide: Artifact<StudyGuideContent>) => ReactNode;
quizProps?: Omit<QuizProps, "questions">;
flashcardsProps?: Omit<FlashcardsProps, "flashcards">;
practiceProblemsProps?: Omit<PracticeProblemsProps, "problems">;
studyGuideProps?: Omit<StudyGuideProps, "studyGuide">;
onBlockComplete?: (block: StudySessionBlock, index: number) => void;
onSessionComplete?: () => void;
};allowSkip— whentrue(default), a Skip control advances without waiting for the timer.autoAdvance— whentrue, moving to the next block (or finishing) happens when the block timer hits zero. Default isfalse.renderNotes— optional Markdown renderer formaterials.notes. Without it, notes render as plain preformatted text.renderQuiz/renderFlashcards/renderPracticeProblems/renderStudyGuide— replace the default nested material UI for that type. When set, the matching*Propsare ignored.quizProps/flashcardsProps/practiceProblemsProps/studyGuideProps— passed through to the default nested component (excluding the data prop, which StudySession supplies). Use for styling or callbacks likeonCompletewithout replacing the UI.onBlockComplete— fires once per block when the learner leaves it (Next / Skip / Finish) or when the timer expires.onSessionComplete— fires once when the last block is finished (or auto-advanced through).
Empty blocks renders nothing.
Customizing nested materials
Style or wire the default quiz without replacing it:
<StudySession
session={session.content}
quizProps={{
className: "my-session-quiz",
onComplete: (result) => {
// Persist GradeQuizResult (may include byTopic)
},
}}
/>Or swap in your own UI:
<StudySession
session={session.content}
renderQuiz={(questions) => <MyQuiz questions={questions} />}
renderFlashcards={(cards) => <MyCards cards={cards} />}
/>classNames
| Key | Part |
|---|---|
root | Root container |
header | Topic / goals / tips header |
topic | Session topic |
goals | Goals list |
goal | Each goal item |
tips | Tips list |
tip | Each tip item |
progress | Block index row |
timer | Countdown |
blockTitle | Current block title |
blockType | Current block type |
instructions | Fallback instructions |
body | Material / instructions body |
notes | Notes wrapper |
controls | Button row |
previousButton | Previous button |
nextButton | Next / Finish button |
skipButton | Skip button |
Example
<StudySession
session={session.content}
allowSkip
className="my-session"
classNames={{
topic: "my-topic",
timer: "my-timer",
}}
renderNotes={(markdown) => <Markdown>{markdown}</Markdown>}
onSessionComplete={() => {
// App-owned persistence
}}
/>For a fully custom runner (own timers / navigation), see Study session flow. See Styling for styles.css and CSS variables.