Drag & Drop
The SurveyBuilder uses native HTML5 drag-and-drop to let users reorder questions within a page and move questions between pages — no external libraries required.
How It Works
Native HTML5 API
The builder leverages the browser's built-in Drag and Drop API via draggable, onDragStart, onDragOver, and onDrop events. No third-party dependencies like react-dnd or dnd-kit are needed.
Zero Configuration
Drag-and-drop is enabled automatically in the SurveyBuilder. Each question card has a drag handle that users can grab to initiate a drag operation.
Visual Feedback
During a drag operation, drop targets are highlighted and the dragged item shows a ghost preview. The builder state tracks isDragging for custom styling.
Reordering Questions
Drag a question within the same page to reorder it. The builder dispatches a REORDER_QUESTIONS action:
// Internal action dispatched by the builder
dispatch({
type: 'REORDER_QUESTIONS',
payload: {
pageId: 'page1',
fromIndex: 0, // original position
toIndex: 2, // new position
},
});Moving Between Pages
Drag a question from one page and drop it onto another page. The builder dispatches a MOVE_QUESTION action:
// Internal action dispatched by the builder
dispatch({
type: 'MOVE_QUESTION',
payload: {
fromPageId: 'page1',
toPageId: 'page2',
fromIndex: 1, // position in source page
toIndex: 0, // position in target page
},
});Reordering Pages
Pages themselves can also be reordered by dragging their tab headers:
dispatch({
type: 'REORDER_PAGES',
payload: {
fromIndex: 0,
toIndex: 1,
},
});Builder State
interface BuilderState {
schema: SurveySchema;
selectedQuestionId: string | null;
selectedPageId: string | null;
isDragging: boolean; // true during a drag operation
}All Builder Actions
type BuilderAction =
| { type: 'ADD_PAGE'; payload?: Partial<Page> }
| { type: 'REMOVE_PAGE'; payload: { pageId: string } }
| { type: 'UPDATE_PAGE'; payload: { pageId: string; updates: Partial<Page> } }
| { type: 'ADD_QUESTION'; payload: { pageId: string; question?: Partial<Question> } }
| { type: 'REMOVE_QUESTION'; payload: { pageId: string; questionId: string } }
| { type: 'UPDATE_QUESTION'; payload: { pageId: string; questionId: string; updates: Partial<Question> } }
| { type: 'REORDER_QUESTIONS'; payload: { pageId: string; fromIndex: number; toIndex: number } }
| { type: 'REORDER_PAGES'; payload: { fromIndex: number; toIndex: number } }
| { type: 'MOVE_QUESTION'; payload: { fromPageId: string; toPageId: string; fromIndex: number; toIndex: number } }
| { type: 'SELECT_QUESTION'; payload: { questionId: string | null } }
| { type: 'SELECT_PAGE'; payload: { pageId: string | null } }
| { type: 'SET_SCHEMA'; payload: SurveySchema }
| { type: 'SET_DRAGGING'; payload: boolean };Browser Support
HTML5 drag-and-drop is supported in all modern browsers. On touch devices, the browser's native touch-to-drag behaviour applies. For more advanced touch support, consider adding a polyfill like mobile-drag-drop.