Skip to content

UNILOOP/react-survey-builder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

React Survey Builder

A comprehensive React-based survey builder and renderer ecosystem featuring a powerful visual drag-and-drop interface for creating dynamic, interactive surveys and forms with advanced conditional logic, multiple layout options, and extensive customization capabilities.

πŸš€ Features

Visual Survey Builder

  • Drag-and-Drop Interface: Intuitive visual editor with real-time preview
  • 18+ Unified Block Types: Text inputs, radio buttons, checkboxes, file uploads, matrices, date pickers, and more
  • Unified Block System: Single-file block definitions combining builder and renderer components
  • Custom Block Support: Easily extend with your own unified block definitions using registerBlock()
  • Node-Based Architecture: Hierarchical survey structure with sections and pages
  • Live Preview: See your survey as you build it

Advanced Logic & Conditional Features

  • Conditional Logic: Show/hide blocks based on user responses with complex condition rules
  • Navigation Rules: Custom routing between survey sections based on user input
  • Calculated Fields: Dynamic field calculations and computed values
  • Branching Logic: Smart survey flow with condition-based page navigation
  • BMI Calculator: Built-in health calculators and custom computation blocks
  • Validation Rules: Field-level validation with custom error messages

Multiple Layout Options

  • Page-by-Page: Traditional multi-page survey experience
  • Continuous Scroll: Single-page scrollable layout
  • Accordion: Collapsible sections for better organization
  • Tabs: Tabbed interface for easy navigation
  • Stepper: Step-by-step progression with visual indicators
  • Full Page: Immersive full-screen survey experience

Comprehensive Theming System

  • 7 Built-in Themes: Default, Minimal, Colorful, Modern, Corporate, Dark, and Custom
  • Complete Customization: Control every aspect of styling from colors to typography
  • Dark Mode Support: Built-in dark/light mode toggle
  • Responsive Design: Mobile-first approach with touch-friendly interactions
  • CSS-in-JS: Tailwind CSS integration with theme variables

Mobile-First Experience

  • Swipe Navigation: Touch gestures for mobile navigation
  • Responsive Layouts: Optimized for all screen sizes
  • Mobile-Specific Controls: Touch-friendly buttons and interactions
  • Progressive Web App: Offline capability and app-like experience

Developer-Friendly

  • TypeScript Support: Full type safety and IntelliSense
  • Workspace Architecture: Monorepo with separate builder and renderer packages
  • Unified Block System: Single-file block definitions with renderBlock for unified rendering
  • Block Registry: Global block registration with registerBlock() and getBlockDefinition()
  • Extensible Architecture: Easy to add custom block types with full builder/renderer support
  • Theme System: Comprehensive theming with CSS variables
  • Modern Stack: React 19, Next.js 15, Tailwind CSS 4

πŸ—οΈ Architecture

This project follows a monorepo structure with two main components:

Main Application (/src/app/)

  • Builder Interface (/builder/) - Visual survey creation with drag-and-drop
  • Demo Interface (/demo/) - Interactive survey renderer with JSON upload
  • Landing Page (/) - Project overview and sample survey demonstration

Survey Form Package (/src/packages/survey-form-package/)

  • Builder Components (/src/builder/) - Visual survey creation interface
  • Renderer Components (/src/renderer/) - Survey form rendering engine
  • Block Definitions (/src/builder/blocks/) - Individual form element types
  • Layout System (/src/renderer/layouts/) - Different survey presentation modes
  • Theme Engine (/src/themes/) - Comprehensive styling system

🎯 Block Types

The survey builder includes 18+ predefined block types:

Input Blocks

  • Text Input: Single-line text fields with validation
  • Textarea: Multi-line text areas
  • Select Dropdown: Single and multi-select dropdowns
  • Radio Buttons: Single-choice selection
  • Checkboxes: Multiple-choice selection
  • Selectable Boxes: Visual selection cards with auto-continue
  • Range Slider: Numeric range selection
  • Date Picker: Date/time selection with calendar
  • File Upload: File attachment with type validation

Advanced Blocks

  • Matrix: Grid-based questions (Likert scales, rating matrices)
  • Conditional: Dynamic blocks that appear based on logic
  • Calculated Field: Computed values based on other responses
  • BMI Calculator: Health assessment with automatic BMI calculation
  • Checkout: Contact information and payment collection
  • Authentication: User login/registration forms

Content Blocks

  • HTML: Rich content with custom HTML
  • Markdown: Formatted text with Markdown support
  • Script: Custom JavaScript execution

🎨 Theming System

Comprehensive theming with 7 built-in themes:

// Available themes
type SurveyTheme = 
  | "default"     // Clean, professional gray theme
  | "minimal"     // Simplified, typography-focused
  | "colorful"    // Vibrant, engaging colors
  | "modern"      // Contemporary design with gradients
  | "corporate"   // Professional business theme
  | "dark"        // Dark mode optimized
  | "custom";     // Fully customizable

Each theme controls:

  • Colors: Primary, secondary, accent, background, text, borders
  • Typography: Font sizes, weights, line heights
  • Spacing: Margins, padding, component sizing
  • Components: Buttons, inputs, cards, progress bars
  • Animations: Transitions and interactive effects

πŸš€ Getting Started

Prerequisites

  • Node.js 18+
  • npm, yarn, or bun package manager

Installation

  1. Clone the repository
git clone https://github.com/UNISELL-DEV/react-survey-builder.git
cd react-survey-builder
  1. Install dependencies
bun install
  1. Start the development server
bun dev
  1. Open your browser Navigate to http://localhost:3000

Development Commands

Main Application

bun run dev      # Start development server with Turbopack
bun run build    # Build the application
bun run start    # Start production server
bun run lint     # Run Next.js linting

Survey Form Package

cd src/packages/survey-form-package
bun run build    # Build the package using tsup
bun run dev      # Build package in watch mode
bun run lint     # Run Biome linting

πŸ“– Usage Examples

Basic Survey Renderer

import { SurveyForm } from 'survey-form-package';

function MyApp() {
  const surveyData = {
    rootNode: {
      type: "section",
      name: "Customer Feedback",
      items: [
        {
          type: "set",
          name: "Contact Information",
          items: [
            {
              type: "textfield",
              fieldName: "name",
              label: "Full Name",
              placeholder: "Enter your full name"
            },
            {
              type: "selectablebox",
              fieldName: "rating",
              label: "How satisfied are you?",
              options: [
                { id: "very-satisfied", label: "Very Satisfied", value: "5" },
                { id: "satisfied", label: "Satisfied", value: "4" },
                { id: "neutral", label: "Neutral", value: "3" },
                { id: "dissatisfied", label: "Dissatisfied", value: "2" },
                { id: "very-dissatisfied", label: "Very Dissatisfied", value: "1" }
              ]
            }
          ]
        }
      ]
    }
  };

  return (
    <SurveyForm
      survey={surveyData}
      theme="modern"
      layout="page-by-page"
      progressBar={{
        type: 'percentage',
        showPercentage: true,
        position: 'top'
      }}
      onSubmit={(data) => console.log('Survey submitted:', data)}
      onChange={(data) => console.log('Data changed:', data)}
    />
  );
}

Unified Block System

The survey package now uses a unified block architecture where each block contains both builder and renderer components in a single definition. This makes it easier to create, maintain, and extend blocks.

Creating Custom Blocks

import React, { useEffect } from 'react';
import { BlockDefinition, registerBlock } from 'survey-form-package';

const CustomRatingBlock: BlockDefinition = {
  type: 'star-rating',
  name: 'Star Rating',
  description: 'Visual star rating component',
  icon: <StarIcon className="w-4 h-4" />,
  defaultData: {
    type: 'star-rating',
    fieldName: 'rating',
    label: 'Rate your experience',
    maxStars: 5,
    allowHalfStars: true
  },
  
  // BUILDER COMPONENTS
  renderItem: ({ data }) => (
    // How block appears in builder preview
    <StarRatingComponent maxStars={data.maxStars} disabled />
  ),
  renderFormFields: ({ data, onUpdate }) => (
    // Configuration form in builder
    <div className="space-y-4">
      <div>
        <label>Label</label>
        <input 
          value={data.label || ''}
          onChange={(e) => onUpdate?.({ ...data, label: e.target.value })}
        />
      </div>
      <div>
        <label>Maximum Stars</label>
        <input 
          type="number"
          value={data.maxStars || 5}
          onChange={(e) => onUpdate?.({ ...data, maxStars: parseInt(e.target.value) })}
        />
      </div>
    </div>
  ),
  renderPreview: () => (
    // Small preview in block library
    <div className="flex justify-center">
      <StarRatingComponent maxStars={5} value={3} disabled />
    </div>
  ),
  
  // RENDERER COMPONENT - NEW UNIFIED APPROACH
  renderBlock: ({ block, value, onChange, error, disabled }) => (
    // How block renders in actual surveys
    <div className="space-y-2">
      {block.label && (
        <label className="block text-sm font-medium">
          {block.label}
        </label>
      )}
      <StarRatingComponent
        value={value || 0}
        maxStars={block.maxStars || 5}
        allowHalfStars={block.allowHalfStars}
        onChange={onChange}
        disabled={disabled}
      />
      {error && <div className="text-red-500 text-sm">{error}</div>}
    </div>
  ),
  
  // VALIDATION
  validate: (data) => {
    if (!data.fieldName) return "Field name is required";
    return null;
  },
  validateValue: (value, data) => {
    if (data.required && !value) return "Rating is required";
    return null;
  },
};

// Register the custom block
function MyApp() {
  useEffect(() => {
    registerBlock(CustomRatingBlock);
  }, []);

  return (
    <SurveyBuilder
      blockDefinitions={[...StandardBlocks, CustomRatingBlock]}
      // ... other props
    />
  );
}

Unified Block Benefits

  • βœ… Single Source of Truth: One file defines both builder and renderer behavior
  • βœ… Easier Maintenance: Changes only need to be made in one place
  • βœ… Better Type Safety: Shared interfaces ensure consistency
  • βœ… Simplified Extension: Custom blocks only need one implementation
  • βœ… Validation Consolidation: Both config and value validation in one place

Available Block Types (18 Built-in)

All blocks use the unified system and support both builder and renderer functionality:

Block Type Description Input Type
textfield Single line text input Text
textarea Multi-line text area Text
radio Single choice selection Option
checkbox Multiple choice selection Array
select Dropdown selection Option
range Slider/range input Number
datepicker Date selection Date
fileupload File upload File
matrix Grid/table questions Object
selectablebox Visual selection boxes Option
markdown Rich text content N/A
html Raw HTML content N/A
script Custom JavaScript N/A
auth Authentication forms Object
bmiCalculator BMI calculation Number
calculated Dynamic calculations Number
conditional Conditional logic Any
checkout Payment forms Object

Block Registration

import { registerBlock, unregisterBlock, getBlockDefinition } from 'survey-form-package';

// Register a custom block
registerBlock(MyCustomBlock);

// Get a registered block
const blockDef = getBlockDefinition('my-custom-type');

// Unregister a block
unregisterBlock('my-custom-type');

Documentation

Advanced Conditional Logic

// Example: Show different questions based on user type
const conditionalSurvey = {
  rootNode: {
    type: "section",
    name: "User Assessment",
    items: [
      {
        type: "set",
        name: "User Type",
        items: [
          {
            type: "selectablebox",
            fieldName: "userType",
            label: "What type of user are you?",
            options: [
              { id: "beginner", label: "Beginner", value: "beginner" },
              { id: "intermediate", label: "Intermediate", value: "intermediate" },
              { id: "advanced", label: "Advanced", value: "advanced" }
            ],
            navigationRules: [
              {
                condition: "userType == 'beginner'",
                target: "beginner-questions-page-id",
                isPage: true
              },
              {
                condition: "userType == 'advanced'",
                target: "advanced-questions-page-id",
                isPage: true
              }
            ]
          }
        ]
      }
    ]
  }
};

πŸ”§ Configuration

Survey Form Props

interface SurveyFormProps {
  survey: {
    rootNode: NodeData;
    localizations?: LocalizationMap;
    theme?: ThemeDefinition;
  };
  onSubmit?: (data: Record<string, any>) => void;
  onChange?: (data: Record<string, any>) => void;
  onPageChange?: (pageIndex: number, totalPages: number) => void;
  defaultValues?: Record<string, any>;
  language?: string;
  theme?: SurveyTheme;
  layout?: SurveyLayout;
  progressBar?: ProgressBarOptions;
  navigationButtons?: NavigationButtonsOptions;
  autoScroll?: boolean;
  autoFocus?: boolean;
  showSummary?: boolean;
  className?: string;
  logo?: ReactNode;
  enableDebug?: boolean;
}

Layout Options

type SurveyLayout = 
  | "page-by-page"  // Traditional multi-page navigation
  | "continuous"    // Single scrollable page
  | "accordion"     // Collapsible sections
  | "tabs"          // Tabbed interface
  | "stepper"       // Step-by-step with progress
  | "fullpage";     // Full-screen experience

Progress Bar Configuration

interface ProgressBarOptions {
  type?: "bar" | "dots" | "numbers" | "percentage";
  showPercentage?: boolean;
  showStepInfo?: boolean;
  showStepTitles?: boolean;
  position?: "top" | "bottom";
  animation?: boolean;
}

🎯 Sample Survey Structure

The project includes a comprehensive sample survey demonstrating:

  • Multi-page navigation with conditional routing
  • Selectable box questions with auto-continue functionality
  • Conditional logic based on user responses
  • Custom HTML result pages with tailored recommendations
  • Checkout integration for lead capture
  • Professional styling with consistent theming

Key features demonstrated:

  • Career assessment with personalized recommendations
  • Educational background evaluation
  • Skills and interests mapping
  • Dynamic page routing based on responses
  • Custom result pages with actionable advice

πŸ› οΈ Development

Project Structure

react-survey-builder/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                          # Next.js application
β”‚   β”‚   β”œβ”€β”€ builder/                  # Visual survey builder
β”‚   β”‚   β”œβ”€β”€ demo/                     # Interactive demo
β”‚   β”‚   └── page.tsx                  # Landing page with sample survey
β”‚   β”œβ”€β”€ packages/
β”‚   β”‚   └── survey-form-package/      # Core survey package
β”‚   β”‚       β”œβ”€β”€ src/
β”‚   β”‚       β”‚   β”œβ”€β”€ builder/          # Survey builder components
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ blocks/       # Block definitions
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ survey/       # Builder interface
β”‚   β”‚       β”‚   β”‚   └── common/       # Shared components
β”‚   β”‚       β”‚   β”œβ”€β”€ renderer/         # Survey renderer
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ layouts/      # Layout components
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ renderers/    # Block renderers
β”‚   β”‚       β”‚   β”œβ”€β”€ components/       # UI components
β”‚   β”‚       β”‚   β”œβ”€β”€ context/          # React contexts
β”‚   β”‚       β”‚   β”œβ”€β”€ hooks/            # Custom hooks
β”‚   β”‚       β”‚   |── themes/           # Theme definitions
β”‚   β”‚       β”‚   β”œβ”€β”€ utils/            # Utility functions
β”‚   β”‚       β”‚   └── types.ts          # TypeScript definitions
β”‚   β”‚       └── package.json
β”‚   └── components/                   # Shared UI components
β”œβ”€β”€ public/                           # Static assets
└── package.json                      # Main package configuration

Adding Custom Blocks

  1. Create block definition
// src/packages/survey-form-package/src/builder/blocks/YourCustomBlock.tsx
import { BlockDefinition } from '../../types';

export const YourCustomBlock: BlockDefinition = {
  type: 'your-custom-type',
  name: 'Your Custom Block',
  description: 'Description of your block',
  icon: <YourIcon />,
  defaultData: {
    type: 'your-custom-type',
    // default properties
  },
  renderItem: ({ data, value, onChange }) => {
    // Render logic for the actual form
  },
  renderFormFields: ({ data, onUpdate }) => {
    // Render configuration form for the builder
  },
  renderPreview: () => {
    // Render preview in block library
  }
};
  1. Add corresponding renderer
// src/packages/survey-form-package/src/renderer/renderers/YourCustomRenderer.tsx
export const YourCustomRenderer: React.FC<BlockRendererProps> = ({ 
  block, 
  value, 
  onChange 
}) => {
  // Render logic for the survey form
};
  1. Register in index files
// Add to src/packages/survey-form-package/src/builder/blocks/index.ts
export { YourCustomBlock } from './YourCustomBlock';

// Add to BlockRenderer.tsx
import { YourCustomRenderer } from './YourCustomRenderer';

Tech Stack

  • Framework: React 19 with Next.js 15
  • Build Tool: Turbopack for fast development
  • Styling: Tailwind CSS 4 with CSS-in-JS
  • UI Components: Radix UI primitives
  • Animations: Framer Motion
  • Drag & Drop: @dnd-kit
  • Type Safety: TypeScript 5
  • Package Management: bun workspaces
  • Bundling: tsup for package builds

Performance Optimizations

  • Tree Shaking: Modular imports and exports
  • Code Splitting: Dynamic imports for layouts and renderers
  • Memoization: React.memo and useMemo for expensive calculations
  • Lazy Loading: Components loaded on demand
  • Bundle Analysis: Optimized package sizes

πŸ“š API Reference

Core Components

SurveyForm

Main component for rendering surveys.

<SurveyForm
  survey={surveyData}
  theme="modern"
  layout="page-by-page"
  onSubmit={handleSubmit}
  onChange={handleChange}
  progressBar={{ type: 'percentage', position: 'top' }}
  navigationButtons={{ showPrevious: true, showNext: true }}
/>

SurveyBuilder

Visual builder component for creating surveys.

<SurveyBuilder
  blockDefinitions={[...StandardBlocks, ...customBlocks]}
  nodeDefinitions={StandardNodes}
  onDataChange={handleDataChange}
  initialData={existingSurvey}
/>

Hooks

useSurveyForm

const {
  values,
  errors,
  currentPage,
  totalPages,
  goToPage,
  goToNextPage,
  goToPreviousPage,
  submit,
  isValid
} = useSurveyForm(survey, options);

useMobileNavigation

const {
  enableSwipe,
  handleSwipeLeft,
  handleSwipeRight,
  swipeDirection
} = useMobileNavigation({
  onSwipeLeft: goToNextPage,
  onSwipeRight: goToPreviousPage
});

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Run linting: bun run lint
  6. Submit a pull request

πŸ“„ License

This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.

  • βœ… Permitted: Open source projects, educational use, personal projects
  • ❌ Requires License: Commercial use, SaaS products, client projects

For commercial licensing, please contact the maintainers.

πŸ™ Acknowledgments

  • Radix UI for accessible component primitives
  • Tailwind CSS for utility-first styling
  • Framer Motion for smooth animations
  • @dnd-kit for drag-and-drop functionality
  • React and Next.js teams for excellent frameworks

πŸ“ž Support


License

This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. You may use the code for open source or other non-commercial purposes. For commercial use or projects where you will charge end users, please contact the maintainers to obtain a commercial license.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published