Skip to main content

Introducing Workflow Engine, try for FREE workflowengine.io.

Designer customization

Customizing the FormBuilder interface

Using the customization FormBuilder prop, you can hide, style, or replace any parts of the FormBuilder interface. A customization map object is passed to this property, in which the options of the desired component are set using its customizable key.

You can manage the FormBuilder and get its state in custom components using useFormBuilder. It provides access to IFormBuilder. The management options are limited at the moment, but they will be expanded in the future.

Another option for customizing the component is to use pure CSS. Each component has a static CSS class named with the component's name prefixed by FE_. This class is applied to the same element as the style or className attributes, utilizing the customization map.

The components palette in the left panel also has some additional rules for CSS customization.

A list of customizable components is also available as a Set.

Example

import {type CustomizationMap, FormBuilder, useFormBuilder} from '@react-form-builder/designer'
import {useCallback} from 'react'

const CustomToggleModeButton = () => {
const builder = useFormBuilder()
const label = builder.builderMode === 'builder' ? 'PreviewMode' : 'EditMode'

const toggleMode = useCallback(() => {
builder.builderMode = builder.builderMode === 'builder' ? 'viewer' : 'builder'
}, [builder])

return <button onClick={toggleMode}>{label}</button>
}

const simpleCustomization: CustomizationMap = {
// Hiding the "Download" item in the main menu by using nested CSS selectors.
MainMenu_Dropdown: {
style: `
#menuitem-\\:r5\\: {
display: none;
}
`
},

// Customizing Header styles
Header: {
className: 'MyClassName',
style: {
backgroundColor: 'rgba(52,152,255,.25)',
borderRadius: '10px',
margin: 5,
marginBottom: 10,
padding: '8px!important'
}
},

// Adding a custom button to the header toolbar.
Header_Toolbar: {
customRenderer: defaultElement => <div style={{display: 'flex', gap: 10}}>
{defaultElement}
<button className={'rs-btn rs-btn-sm'}>My button</button>
</div>
},

// Component toolbar (the toolbar on each selected component in the canvas): add a custom button and hide the default remove (trash) button.
Component_Toolbar: {
customRenderer: defaultElement => (
<div>
{defaultElement}
<span style={{marginLeft: 4, padding: '2px 6px', fontSize: 24}}>
Custom
</span>
</div>
)
},

// Changing the "Toggle mode" button to a custom component.
ToggleModeButton: {
customRenderer: () => <CustomToggleModeButton/>
},

// Hiding the localization dropdown.
LocalizationSelect: {
hidden: true
},

// Hiding the "Json view" button
JsonViewButton: {
hidden: true
},

// Hiding the property code button
PropertyCodeButton: {
hidden: true
}
}

const FormBuilderApp = () => {
return <FormBuilder
customization={simpleCustomization}
// other props
/>
}

Customization 03

Complete list of customizable component keys

Customization 01

#NameclassName
1MainContainerFE_MainContainer
2LeftPanelFE_LeftPanel
3CentralPanelFE_CentralPanel
4RightPanelFE_RightPanel
5LeftPanel_NavFE_LeftPanel_Nav
6LeftPanel_ContentFE_LeftPanel_Content
7HeaderFE_Header
8FormContainerFE_FormContainer
9RightPanel_NavFE_RightPanel_Nav
10RightPanel_ContentFE_RightPanel_Content
11MainMenu_DropdownFE_MainMenu_Dropdown
12MainMenu_ButtonFE_MainMenu_Button
13Header_ToolbarFE_Header_Toolbar
14Component_ToolbarFE_Component_Toolbar
15Component_Toolbar_ItemsFE_Component_Toolbar_Items
16Component_Toolbar_TitleFE_Component_Toolbar_Title
17Component_Toolbar_AddButtonFE_Component_Toolbar_AddButton
18Component_Toolbar_CloneButtonFE_Component_Toolbar_CloneButton
19Component_Toolbar_PresetComponentButtonFE_Component_Toolbar_PresetComponentButton
20Component_Toolbar_RemoveButtonFE_Component_Toolbar_RemoveButton
21ToggleModeButtonFE_ToggleModeButton
22ResolutionSelectFE_ResolutionSelect
23LocalizationSelectFE_LocalizationSelect
24JsonViewButtonFE_JsonViewButton
25ToggleThemeButtonFE_ToggleThemeButton

Customization 02

#NameclassNameaux classes
1Components_TabFE_Components_Tab
2Components_Tab_ContentFE_Components_Tab_Content
3Tree_TabFE_Tree_Tab
4Tree_Tab_ContentFE_Tree_Tab_Content
5Settings_TabFE_Settings_Tab
6Settings_Tab_ContentFE_Settings_Tab_Content
7Forms_TabFE_Forms_Tab
8Forms_Tab_ContentFE_Forms_Tab_Content
9Main_TabFE_Main_Tab
10Style_TabFE_Style_Tab
11Actions_TabFE_Actions_Tab
12Rules_TabFE_Rules_Tab
13Main_Tab_Content,
Style_Tab_Content,
Actions_Tab_Content,
Rules_Tab_Content
FE_Main_Tab_Content,
FE_Style_Tab_Content,
FE_Actions_Tab_Content,
FE_Rules_Tab_Content
14LabeledPropertyFE_LabeledPropertyvalueModified
15PropertyCodeButtonFE_PropertyCodeButton
16PropertyLabelFE_PropertyLabel
17PropertyInputFE_PropertyInput

Components palette

Each group and component receives a set of classes composed of its name and type.

When defining a component, you can specify its category. Components with the same category are merged into component groups on the palette.

export const richTextEditor = define(RichTextEditor, 'RichTextEditor')
.name('Rich text editor')
.category('fields')
.props({
//...
})

Components group

A component group is assigned the static class FE_Palette_ComponentGroup along with a category name prefixed with FE_. If a component group is not defined, components appear at the top of the list without a title and within container with additional class FE_top.

Groups classes

Single component

A component receives the static class FE_Palette_Component composed with its title and name, both prefixed with FE_.

export const rsCalendar = define(RsCalendar, 'RsCalendar')
.name('Calendar')
.props({
// ...
})

Component classes

Custom property editors

Using the propertyEditors FormBuilder prop, you can override existing component property editors or set editor for your custom property.

Example

import type {AnnotationEditorProps} from '@react-form-builder/designer'
import {FormBuilder} from '@react-form-builder/designer'
import {RgbaColorPicker} from 'react-colorful'

const MyKeyInput = (props: AnnotationEditorProps) => {
const {value, onChange} = props
return <input value={value} onChange={(event) => onChange(event.target.value)}/>
}

/**
* Converts the string containing a rgba color value into an object.
* @param value the string containing a rgba color.
* @returns the object with properties '{r, g, b, a}'.
*/
export function rgbFromString(value: string): RgbaColor {
const matchColors = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/
const [, r, g, b, a] = matchColors.exec(value) || []
return {r: Number(r), g: Number(g), b: Number(b), a: Number(a)}
}

const MyColorInput = (props: AnnotationEditorProps) => {
const {value, onChange, onClean, showError, annotation} = props

const onColorChange = useCallback((newColor?: RgbaColor) => {
if (newColor) {
const {r, g, b, a} = newColor
onChange(`rgba(${r}, ${g}, ${b}, ${a})`)
return
}
onChange(newColor)
}, [onChange])

const color = rgbFromString(value ?? 'rgba(255, 255, 255, 0)')

return <div>
<label>{annotation.name}</label>
<RgbaColorPicker color={color} onChange={onColorChange}/>
<label>{showError?.()}</label>
<button onClick={onClean}>Clean</button>
</div>
}

const FormBuilderApp = () => {
return <FormBuilder
propertyEditors={{
// Overriding the default key property editor
key: MyKeyInput,

// Setting the property editor for your own custom property
customColor: MyColorInput
}}
// other props
/>
}