S
Documentation

SurveyRenderer — API Reference

Complete reference for the SurveyRenderer component — a batteries-included survey UI built on top of the useSurvey hook.

Import

import { SurveyRenderer } from 'react-minimal-survey-builder';

Props

SurveyRendererPropstypescript
interface SurveyRendererProps {
  schema: SurveySchema;
  options?: SurveyOptions;
  components?: QuestionComponents;
  className?: string;
  children?: (survey: UseSurveyReturn) => React.ReactNode;
  disabled?: boolean;
  renderHeader?: (props: RenderHeaderProps) => React.ReactNode;
  renderFooter?: (props: RenderFooterProps) => React.ReactNode;
  renderComplete?: () => React.ReactNode;
}

Props Detail

PropTypeDefaultDescription
schemaSurveySchemaSurvey schema object (required)
optionsSurveyOptions{}Callbacks, initial answers, validators
componentsQuestionComponents{}Custom component overrides by question type
classNamestringCSS class for the survey container
children(survey) => ReactNodeRender prop for full layout control
disabledbooleanfalseDisable all inputs
renderHeader(props) => ReactNodeCustom header renderer
renderFooter(props) => ReactNodeCustom navigation footer
renderComplete() => ReactNodeCustom completion screen

renderHeader Props

RenderHeaderPropstypescript
interface RenderHeaderProps {
  title?: string;
  description?: string;
  progress: number;       // 0–100
  currentPage: number;    // zero-based page index
  totalPages: number;
}

renderFooter Props

RenderFooterPropstypescript
interface RenderFooterProps {
  hasPrevPage: boolean;
  hasNextPage: boolean;
  isLastPage: boolean;
  prevPage: () => void;
  nextPage: () => void;
  submit: () => void;
  isValid: boolean;
}

QuestionComponents

QuestionComponents & Propstypescript
type QuestionComponents = Partial<
  Record<QuestionType, React.ComponentType<QuestionComponentProps>>
>;

type QuestionComponentProps<V = AnswerValue> = {
  question: Question;
  value: V;
  onChange: (value: V) => void;
  error?: string;
  disabled?: boolean;
};

Rendering Modes

Default Mode

Renders header, questions, navigation, and completion screen using built-in components. Style via CSS class names (rmsb-*) or the className prop.

Custom Components Mode

Pass components to override specific question types. The layout and navigation remain the defaults.

Render Prop Mode

Pass a function as children for complete control. The function receives the fulluseSurvey return object.

Accessibility

All default question components are WCAG 2.1 AA compliant. Every form field includes:

  • aria-required and native required on mandatory fields
  • aria-invalid when validation fails
  • aria-describedby linking to description and error messages
  • Proper ARIA roles (radiogroup, group) on composite controls
  • aria-labelledby on grouped inputs (radio, checkbox, boolean, rating)
  • aria-checked / aria-pressed on rating buttons
  • aria-valuemin, aria-valuemax, aria-valuenow, aria-valuetext on sliders
  • role="alert" with aria-live="assertive" on error messages
  • Keyboard :focus-visible outlines on all interactive elements

Minimal Example

Minimaltsx
<SurveyRenderer
  schema={schema}
  options={{ onSubmit: (answers) => console.log(answers) }}
/>

Full-Featured Example

Full-Featured Exampletsx
<SurveyRenderer
  schema={schema}
  className="max-w-xl mx-auto"
  disabled={isReadOnly}
  components={{
    text: CustomTextInput,
    rating: StarRating,
  }}
  options={{
    initialAnswers: savedAnswers,
    onSubmit: async (answers) => {
      await api.post('/responses', answers);
    },
    onChange: (answers, id) => autosave(answers),
    validators: {
      email: (v) => (String(v).includes('@') ? null : 'Invalid email'),
    },
  }}
  renderHeader={({ title, progress }) => (
    <div>
      <h1>{title}</h1>
      <progress value={progress} max={100} />
    </div>
  )}
  renderFooter={({ isLastPage, prevPage, nextPage, submit, hasPrevPage }) => (
    <div className="flex gap-4">
      {hasPrevPage && <button onClick={prevPage}>Back</button>}
      <button onClick={isLastPage ? submit : nextPage}>
        {isLastPage ? 'Submit' : 'Next'}
      </button>
    </div>
  )}
  renderComplete={() => <p>Thanks for your response!</p>}
/>