BricqsBricqs
Documentation
← Headless SDK

Slot Components

For teams that want headless control with pre-wired state management, the SDK provides slot-based components. These give you render props for each UI section while handling all state, navigation, and submission logic internally.

QuizProvider

Wraps quiz state and exposes render-prop slots for each UI region. You provide the JSX; the provider handles question flow, answer tracking, submission, and scoring.

import { QuizProvider, QuizQuestionSlot, QuizOptionsSlot,
  QuizProgressSlot, QuizActionsSlot, QuizCompletionSlot } from '@bricqs/sdk-react';

function MyQuiz({ config, onComplete }) {
  return (
    <QuizProvider config={config} onComplete={onComplete}>
      {/* Progress bar */}
      <QuizProgressSlot>
        {({ progress, currentIndex, totalQuestions }) => (
          <div className="w-full bg-gray-200 h-2 rounded">
            <div style={{ width: `${progress}%` }} className="bg-blue-500 h-2 rounded" />
          </div>
        )}
      </QuizProgressSlot>

      {/* Question text */}
      <QuizQuestionSlot>
        {({ question, questionIndex }) => (
          <h2 className="text-xl font-bold">{question}</h2>
        )}
      </QuizQuestionSlot>

      {/* Answer options */}
      <QuizOptionsSlot>
        {({ options, selectedIndex, onSelect, showResult, isCorrect }) => (
          <div className="flex flex-col gap-2">
            {options.map((opt, i) => (
              <button key={i} onClick={() => onSelect(i)}
                className={selectedIndex === i ? 'bg-blue-100 border-blue-500' : ''}
              >
                {opt}
              </button>
            ))}
          </div>
        )}
      </QuizOptionsSlot>

      {/* Navigation / submit */}
      <QuizActionsSlot>
        {({ canGoBack, canGoNext, canSubmit, onBack, onNext, onSubmit }) => (
          <div className="flex gap-2">
            {canGoBack && <button onClick={onBack}>Back</button>}
            {canGoNext && <button onClick={onNext}>Next</button>}
            {canSubmit && <button onClick={onSubmit}>Submit</button>}
          </div>
        )}
      </QuizActionsSlot>

      {/* Results screen */}
      <QuizCompletionSlot>
        {({ result, onRestart }) => (
          <div>
            <h3>Score: {result.score}/{result.maxScore}</h3>
            <button onClick={onRestart}>Try Again</button>
          </div>
        )}
      </QuizCompletionSlot>
    </QuizProvider>
  );
}

// Access internal state from any child component:
// const ctx = useQuizContext();
When to use slots vs hooks: Use QuizProvider slots when you want to customize the look but keep the built-in question flow logic. Use useQuiz() directly when you need full control over navigation, timing, or conditional rendering.