A powerful and flexible form-builder component for React applications that generates forms dynamically from JSON configurations.
- Node.js >= 14.x
- React ^16.8.0 || ^17.0.0 || ^18.0.0
- React-DOM ^16.8.0 || ^17.0.0 || ^18.0.0
- Tailwind CSS >= 3.x
npm install @your-org/dynamic-form-builder
npm install react react-dom
-
tailwind.config.js
module.exports = { content: [ './src/**/*.{js,jsx,ts,tsx}', './node_modules/@your-org/dynamic-form-builder/dist/style.css' ], theme: { extend: {} }, plugins: [] };
-
postcss.config.js
module.exports = { plugins: [require('tailwindcss'), require('autoprefixer')] };
-
src/index.css
@tailwind base; @tailwind components; @tailwind utilities; @import '@your-org/dynamic-form-builder/dist/style.css';
import React, { useState } from 'react';
import { FormBuilder, FormConfig, QuestionConfig } from '@your-org/dynamic-form-builder';
import '@your-org/dynamic-form-builder/dist/style.css';
import sampleConfig from './form_config.json';
function App() {
const [config, setConfig] = useState<FormConfig>(sampleConfig);
const handleSubmit = (data: Record<string, any>) => {
console.log('Form data:', data);
};
const handleAddOption = (questionId: string) => {
// Show modal/dialog to collect new option details then update config
};
const handleQuestionUpdate = (updated: QuestionConfig) => {
setConfig((cfg) => ({
...cfg,
questions: cfg.questions.map((q) =>
q.question_id === updated.question_id ? updated : q
)
}));
};
return (
<FormBuilder
config={config}
onSubmit={handleSubmit}
onAddOption={handleAddOption}
onQuestionUpdate={handleQuestionUpdate}
/>
);
}
Configure the form via form_config.json
. All properties:
Property | Type | Description | Default |
---|---|---|---|
style |
string | Layout: "tabs" or "subheadings"
|
"subheadings" |
showHeader |
boolean | Whether to display the header | true |
submitText |
string | Submit button text | "Submit" |
headerTitle |
string | Header title | ― |
headerSubTitle |
string | Header subtitle | ― |
buttons.primary buttons.secondary
|
object | Button colors { backgroundColor, hoverBackgroundColor, textColor, focusRingColor }
|
Tailwind defaults |
+Optional subsections
: array of objects to group questions within a section.
+
+```json
+{
- "section_id": "personal_info",
- "section_name": "Personal Information",
- "order": 1,
- "description": "Basic details about you",
- "icon": "user-circle",
- "subsections": [
- {
-
"subsection_id": "contact",
-
"subsection_name": "Contact Info",
-
"order": 1,
-
"description": "How to reach you",
-
"icon": "phone"
- }
- ] +} +```
interface QuestionConfig {
question_id: string; // required
question_text: string; // required
question_style: string; // see Input Types
mandatory?: boolean;
placeholder_text?: string;
help_text?: string;
default_value?: any;
validations?: Array<{ pattern: string; error_message: string }>;
dependency_question_id?: string;
dependency_answers?: any[];
dependency_logic?: 'AND' | 'OR';
options?: Array<{ label: string; value: any }>;
allowNew?: boolean;
badgeColor?: string; // hex for multi-select badges
icon?: string;
field_width?: 'full' | 'half';
visibility?: 'visible' | 'hidden';
on_change_action?: string;
order?: number;
section_id?: string;
+ subsection_id?: string; // optional: assign question to a subsection
}
text
textarea
dropdown
multi-select dropdown
checkbox
checkbox group
radio buttons
date picker
time picker
file upload
image upload
signature pad
slider
toggle switch
color picker
{
"form": {
"style": "subheadings",
"showHeader": true,
"submitText": "Submit Form",
"headerTitle": "Dynamic Form",
"headerSubTitle": "Please fill out the form",
"buttons": {
"primary": {
"backgroundColor": "#2563eb",
"hoverBackgroundColor": "#1d4ed8",
"textColor": "#ffffff",
"focusRingColor": "#3b82f6"
},
"secondary": {
"backgroundColor": "#f9fafb",
"hoverBackgroundColor": "#f3f4f6",
"textColor": "#374151",
"focusRingColor": "#6b7280"
}
}
},
"sections": [
{
"section_id": "personal_info",
"section_name": "Personal Information",
"order": 1,
"description": "Your details",
"icon": "user",
"subsections": [
{
"subsection_id": "contact",
"subsection_name": "Contact Info",
"order": 1,
"description": "How to reach you",
"icon": "phone"
}
]
},
{
"section_id": "preferences",
"section_name": "Preferences",
"order": 2,
"description": "Choose preferences",
"icon": "settings"
}
],
"questions": [
{
"question_id": "name",
"question_text": "Full Name",
"question_style": "text",
"mandatory": true,
"placeholder_text": "Enter full name",
"help_text": "Legal name",
"validations": [
{"pattern": "^[A-Za-z\\s]+$", "error_message": "Only letters allowed"},
{"pattern": "^.{3,}$", "error_message": "Min 3 chars"}
],
"order": 1,
"field_width": "full",
"section_id": "personal_info",
"subsection_id": "contact"
},
{
"question_id": "color",
"question_text": "Favorite Color",
"question_style": "dropdown",
"options": [
{"label": "Red", "value": "red"},
{"label": "Blue", "value": "blue"}
],
"order": 2,
"section_id": "preferences"
},
{
"question_id": "skills",
"question_text": "Skills",
"question_style": "multi-select dropdown",
"allowNew": true,
"options": [
{"label": "JS", "value": "js"},
{"label": "Python", "value": "py"}
],
"order": 3,
"badgeColor": "#f87171",
"section_id": "preferences"
},
{
"question_id": "subscribe",
"question_text": "Subscribe to newsletter",
"question_style": "toggle switch",
"default_value": false,
"order": 4,
"section_id": "preferences"
}
]
}
onSubmit(data: Record<string, any>): void
onAddOption(questionId: string): void
onQuestionUpdate(updatedQuestion: QuestionConfig): void
git clone <repo-url>
cd dynamicformv2-main
npm install
npm run dev
npm run build:lib
npm run build:css
npm run preview
- react ^16.8.0 || ^17.0.0 || ^18.0.0
- react-dom ^16.8.0 || ^17.0.0 || ^18.0.0
MIT