Skip to content

gawryco/reactquiz-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

ReactQuiz Engine (use-quiz)

⚠️ WARNING: This is a Proof of Concept (POC) library and is not production-ready. It has not been thoroughly tested and may contain bugs or breaking changes. Use at your own risk.

Live Docs CI Deploy Docs npm version npm downloads Bundle size Size Limit License: MIT TypeScript React Tailwind CSS Coverage Dependencies PRs Welcome

ReactQuiz Engine is a comprehensive React quiz component library with TypeScript support, multiple question types, and advanced features. Perfect for creating interactive surveys, assessments, lead generation forms, and onboarding flows.

Features

  • 🎯 9 Question Types: Single choice, multiple choice, scale, slider, text input, image selection, date picker, matrix, and ranking
  • πŸ“± Mobile Optimized: Touch gestures, responsive design, and mobile-first approach
  • 🎨 Customizable: Full control over branding, colors, styling, and button text with Tailwind CSS
  • πŸ”„ Progress Persistence: Save and restore quiz progress with localStorage
  • 🧠 Conditional Logic: Show/hide questions based on previous answers
  • πŸ“Š Result Strategies: Scoring, weighted, conditional, and custom calculation
  • πŸ“ Lead Capture: Built-in form with validation for collecting user information
  • 🌍 i18n-ready: Pluggable translation layer with language switch support
  • β™Ώ Accessible: WCAG-compliant semantics and keyboard navigation
  • 🎭 Animations: Smooth transitions and micro-interactions (slide, fade, scale, bounce)
  • πŸ“¦ TypeScript: Full type safety and IntelliSense support
  • πŸŽ›οΈ Grid Layouts: BuzzFeed-style grid layouts for question options
  • πŸ”€ Custom Button Text: Customize all button labels for better UX
  • πŸ“Έ Shareable Results: Generate beautiful result images with html-to-image (lazy loaded) for social sharing

Table of Contents

Installation

npm install @gawryco/reactquiz-engine
# or
yarn add @gawryco/reactquiz-engine 
# or
pnpm add @gawryco/reactquiz-engine 

Documentation

πŸš€ Live Documentation on GitHub Pages

To see ReactQuiz Engine in action, you can either:

Option 1: View Live Documentation

Visit the live documentation hosted on GitHub Pages to see all features in action.

Option 2: Run Locally

Clone and run the documentation locally:

# Clone the repository
git clone https://github.com/gawryco/reactquiz-engine.git
cd reactquiz-engine

# Install dependencies
pnpm install

# Run the documentation
pnpm dev

The documentation includes five examples:

  • Simple Quiz: Love language assessment with basic question types
  • Advanced Quiz: Calculator finder with image selection, sliders, matrix, weighted scoring
  • Timer Quiz: Quiz-level and question-level timers with warning thresholds and auto-advance
  • Animation Showcase: Demonstrates all transition types, timings, and effects
  • Conditional Logic Demo: Questions appear dynamically based on previous answers

Open http://localhost:5173 to view the local documentation.

Quick Start

import React from 'react';
import { Quiz } from '@gawryco/reactquiz-engine';
import { Heart, User, Mail, Phone } from 'lucide-react';

const MyQuiz = () => {
  const quizConfig = {
    title: "What's Your Love Language? πŸ’•",
    subtitle: "Discover how you express and receive love",

    branding: {
      colors: {
        primary: "from-pink-500 to-rose-600",
        secondary: "from-purple-500 to-pink-600",
        accent: "pink-500"
      },
      icon: Heart
    },

    behavior: {
      autoAdvance: true,
      showProgress: true,
      allowBack: true,
      saveProgress: false
    },

    questions: [
      {
        id: 1,
        question: "How do you prefer to show affection?",
        type: "single-choice",
        required: true,
        options: [
          { value: "words", label: "Saying 'I love you' and compliments" },
          { value: "touch", label: "Hugs, kisses, and physical contact" },
          { value: "time", label: "Spending quality time together" },
          { value: "gifts", label: "Giving thoughtful presents" },
          { value: "acts", label: "Doing helpful things for them" }
        ]
      }
    ],

    resultLogic: { type: "scoring" },
    results: {
      words: {
        title: "Words of Affirmation πŸ’¬",
        description: "You feel most loved when people express their feelings for you through words.",
        color: "from-blue-400 to-indigo-600"
      }
    },

    leadCapture: {
      enabled: true,
      title: "Get Your Results!",
      subtitle: "Enter your details to receive personalized insights",
      fields: [
        {
          key: 'name',
          label: 'Your Name',
          type: 'text',
          required: true,
          icon: User,
          placeholder: 'Enter your full name',
          validation: {
            minLength: 2,
            maxLength: 50,
            pattern: '^[a-zA-Z\\s\'-]+$',
            message: 'Please enter a valid name'
          }
        },
        {
          key: 'email',
          label: 'Email Address',
          type: 'email',
          required: true,
          icon: Mail,
          placeholder: 'your.email@example.com'
        },
        {
          key: 'phone',
          label: 'Phone Number (Optional)',
          type: 'tel',
          required: false,
          icon: Phone,
          placeholder: '(555) 123-4567',
          validation: {
            pattern: '^(\\(?([0-9]{3})\\)?[-.\\s]?([0-9]{3})[-.\\s]?([0-9]{4}))$',
            message: 'Please enter a valid US phone number'
          }
        }
      ],
      privacyText: "πŸ”’ We respect your privacy and won't spam you."
    },

    onSubmit: (leadData, answers, result) => {
      console.log('Quiz completed!', { leadData, answers, result });
    }
  };

  return <Quiz quizConfig={quizConfig} quizId="love-language-quiz" />;
};

export default MyQuiz;

Question Types

Single Choice

{
  id: 1,
  question: "What's your favorite color?",
  type: "single-choice",
  required: true,
  options: [
    { value: "red", label: "Red" },
    { value: "blue", label: "Blue" },
    { value: "green", label: "Green" }
  ]
}

Slider

{
  id: 2,
  question: "Rate your satisfaction",
  type: "slider",
  min: 0,
  max: 10,
  step: 1,
  unit: "points"
}

Note: Slider questions always show a continue button for better UX.

Multiple Choice

{
  id: 2,
  question: "Which activities do you enjoy?",
  type: "multi-choice",
  description: "Select all that apply",
  options: [
    { value: "reading", label: "Reading" },
    { value: "sports", label: "Sports" },
    { value: "music", label: "Music" }
  ]
}

Scale (1-5 Rating)

{
  id: 3,
  question: "How satisfied are you?",
  type: "scale",
  scaleMax: 5,
  scaleLabels: { min: "Not satisfied", max: "Very satisfied" },
  required: true
}

Slider

{
  id: 4,
  question: "What's your budget range?",
  type: "slider",
  min: 1000,
  max: 10000,
  step: 500,
  unit: "USD"
}

Text Input

{
  id: 5,
  question: "Tell us about yourself",
  type: "text-input",
  placeholder: "Share your thoughts...",
  maxLength: 500,
  required: true
}

Image Selection

{
  id: 6,
  question: "Which style appeals to you?",
  type: "image-selection",
  options: [
    { 
      value: "modern", 
      label: "Modern", 
      image: "https://example.com/modern.jpg" 
    },
    { 
      value: "classic", 
      label: "Classic", 
      image: "https://example.com/classic.jpg" 
    }
  ]
}

Date Picker

{
  id: 7,
  question: "When is your event?",
  type: "date-picker",
  minDate: "2024-01-01",
  maxDate: "2024-12-31",
  required: true
}

Matrix (Grid)

{
  id: 8,
  question: "Rate each feature",
  type: "matrix",
  columns: ["Poor", "Fair", "Good", "Excellent"],
  rows: ["Ease of use", "Performance", "Design", "Support"]
}

Advanced Features

Conditional Logic

Show questions based on previous answers:

{
  conditionalLogic: [
    {
      questionId: 5, // Show this question only if...
      dependsOn: 1,  // ...answer to question 1...
      operator: 'equals', // ...equals...
      value: 'yes' // ...'yes'
    }
  ]
}

Weighted Scoring

Assign different weights to questions and answers:

{
  resultLogic: {
    type: "weighted",
    weights: {
      1: 3, // Question 1 has 3x weight
      2: 1, // Question 2 has normal weight
      3: 2  // Question 3 has 2x weight
    }
  }
}

Custom Result Calculation

{
  resultLogic: {
    type: "custom",
    calculation: (answers) => {
      // Your custom logic here
      const score = calculateCustomScore(answers);
      return score > 80 ? 'expert' : 'beginner';
    }
  }
}

Progress Persistence

{
  behavior: {
    saveProgress: true, // Automatically save progress
    allowBack: true,    // Allow users to go back
    autoAdvance: false, // Manual navigation
    showProgress: true  // Show progress bar
  }
}

Timers

Support quiz-level and question-level timers with warning thresholds and callbacks.

{
  behavior: {
    timer: {
      enabled: true,
      duration: 120,
      showDisplay: true,
      autoAdvanceOnExpiry: true,
      warningThreshold: 30,
      onExpiry: () => console.log('Quiz timer expired')
    }
  }
}

Question-level timer example:

{
  id: 2,
  question: 'Rate your programming experience',
  type: 'slider',
  timer: {
    enabled: true,
    duration: 30,
    showDisplay: true,
    autoAdvanceOnExpiry: true,
    warningThreshold: 10
  }
}

Animations

Fine-tune transitions, timings, and interactive effects.

{
  behavior: {
    animations: {
      transitions: { slideLeft: true, fadeIn: true, bounce: false, scale: true, slideUp: true },
      timing: { questionTransition: 350, optionHover: 150, buttonHover: 200, progressUpdate: 300 },
      effects: { pulseOnSelect: true, shakeOnError: true, glowOnFocus: true }
    }
  }
}

Shareable Results

Generate beautiful result images for social sharing using html-to-image (lazy loaded):

{
  onExportImage: (blob: Blob, options: { aspect: 'square' | 'story' | 'tweet' }) => {
    // Handle the generated image blob
    const url = URL.createObjectURL(blob);
    // Share or download the image
  }
}

The library automatically generates high-quality PNG images with customizable aspect ratios:

  • Square (1080x1080): Perfect for Instagram posts
  • Story (1080x1920): Ideal for Instagram/Snapchat stories
  • Tweet (1600x900): Optimized for Twitter/X sharing

The html-to-image library is lazy loaded to keep the initial bundle size small.

Internationalization (i18n)

Import the i18n instance and switch languages dynamically. See the documentation for a full example.

import i18n from '@gawryco/reactquiz-engine/i18n';

i18n.changeLanguage('fr');
{
  behavior: {
    saveProgress: true, // Automatically save progress
    allowBack: true,    // Allow users to go back
    autoAdvance: false, // Manual navigation
    showProgress: true  // Show progress bar
  }
}

Lead Capture Validation

The library includes comprehensive validation for lead capture forms with built-in validation rules and custom validation support.

Built-in Validation

The library automatically applies validation rules based on field type:

  • Email fields: Validates email format using RFC-compliant regex
  • Phone fields: Validates phone number format (supports international and US formats)
  • Text fields: Applies name validation for fields with "name" in the key

Custom Validation

You can define custom validation rules for any field:

{
  key: 'name',
  label: 'Full Name',
  type: 'text',
  required: true,
  icon: User,
  placeholder: 'Enter your full name',
  validation: {
    minLength: 2,
    maxLength: 50,
    pattern: '^[a-zA-Z\\s\'-]+$',
    message: 'Please enter a valid name (letters, spaces, hyphens, and apostrophes only)'
  }
}

Validation Rules

Rule Type Description
minLength number Minimum character length
maxLength number Maximum character length
pattern string Regex pattern for validation
message string Custom error message
custom function Custom validation function that returns error message or null

Custom Validation Function

{
  key: 'website',
  label: 'Website',
  type: 'text',
  required: false,
  icon: Globe,
  validation: {
    custom: (value) => {
      if (value && !value.startsWith('http')) {
        return 'Website must start with http:// or https://';
      }
      return null; // Valid
    }
  }
}

Visual Feedback

The library provides real-time visual feedback for validation errors:

  • Red border and background for invalid fields
  • Error icons next to invalid inputs
  • Detailed error messages below each field
  • Form submission is disabled until all validation passes

Styling and Branding

Custom Colors

{
  branding: {
    colors: {
      primary: "from-blue-500 to-purple-600",    // Gradient for buttons
      secondary: "from-green-500 to-emerald-600", // Secondary actions
      accent: "blue-500"                          // Accent color for selections
    },
    icon: YourIcon // Lucide React icon
  }
}

Custom Button Text

{
  behavior: {
    buttonText: {
      next: 'Next Question',
      back: 'Previous',
      continue: 'Continue',
      submit: 'Get My Results',
      start: 'Start Quiz'
    }
  }
}

Grid Layouts

{
  id: 1,
  question: "What's your favorite color?",
  type: "single-choice",
  layout: {
    type: 'grid',        // 'list' or 'grid'
    columns: 2,          // 2, 3, or 4 columns
    gap: 'md'            // 'sm', 'md', or 'lg'
  },
  options: [
    { value: "red", label: "Red" },
    { value: "blue", label: "Blue" },
    { value: "green", label: "Green" },
    { value: "yellow", label: "Yellow" }
  ]
}

Custom CSS Classes

<Quiz 
  quizConfig={config} 
  className="my-custom-quiz" 
/>

API Reference

Quiz Component Props

Prop Type Required Description
quizConfig Partial<QuizConfig> βœ… Quiz configuration object
quizId string ❌ Unique identifier for progress persistence
className string ❌ Additional CSS classes

QuizConfig Interface

interface QuizConfig {
  title: string;
  subtitle: string;
  startButtonText?: string;
  welcomeFooter?: string;
  branding: QuizBranding;
  behavior: QuizBehavior;
  questions: QuizQuestion[];
  conditionalLogic?: ConditionalLogic[];
  resultLogic: ResultLogic;
  results: Record<string, QuizResult>;
  leadCapture: LeadCapture;
  thankYouMessage?: string;
  onSubmit: (
    leadData: Record<string, string>,
    answers: Record<string, QuizAnswer>,
    result: string
  ) => void;
}

useQuiz Hook

For advanced usage, you can use the useQuiz hook directly:

import { useQuiz } from '@gawryco/reactquiz-engine';

const MyCustomQuiz = () => {
  const {
    config,
    state,
    visibleQuestions,
    totalSteps,
    progress,
    handleAnswerSelect,
    handleNext,
    handleBack,
    handleSubmit,
    resetQuiz
  } = useQuiz(quizConfig, 'my-quiz');

  // Your custom implementation
  return <div>...</div>;
};

Requirements

  • React 16.8+ (hooks support)
  • Lucide React for icons
  • Tailwind CSS for styling

Browser Support

  • Chrome 60+
  • Firefox 60+
  • Safari 12+
  • Edge 79+

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT Β© Gawry&Co

Support

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages