Customize React Bricks
Create custom visual components
Use the useVisualEdit hook to build advanced custom editing components beyond Text, RichText, Image, and File.
In this how-to, you'll learn how to create a custom visual editing component in React Bricks.
This is an advanced technique.
For most projects, the built-in visual components like Text, RichText, Image, Link, File, and Repeater are the right choice.
Use a custom visual component only when you need an editing experience that React Bricks does not provide out of the box.
Docs reference: useVisualEdit
When custom visual components are useful
The useVisualEdit hook is the escape hatch for advanced editing UI.
It is useful when you want to create things like:
- a code editor
- a JSON editor
- a color palette picker
- a canvas or drawing area
- a custom form-like editor for one complex prop
The hook lets your component read a brick prop and write back to that prop, while rendering a different UI depending on whether you are:
- in the Admin editor
- in Preview mode
- on the public frontend
What useVisualEdit returns
The hook takes a prop name and returns:
const [value, setValue, isReadOnly] = useVisualEdit('myProp')The returned values mean:
value: the current value of the propsetValue: updates the propisReadOnly:trueon the frontend and in Preview mode,falsein the Admin editor
That means your component usually has 2 render paths:
- an editable UI for the Admin editor
- a read-only UI for preview and frontend rendering
A simple example: a custom code editor
Here is a minimal example using a textarea.
In a real project, you could swap this with Monaco, CodeMirror, a color picker, or another interactive editor.
If you're using Next.js App Router, keep this editor as a client component.
'use client'
import { useVisualEdit } from 'react-bricks/frontend'
interface CodeEditorProps {
propName: string
}
const CodeEditor = ({ propName }: CodeEditorProps) => {
const [value, setValue, isReadOnly] = useVisualEdit(propName)
if (isReadOnly) {
return (
<pre className="overflow-x-auto rounded-lg bg-slate-950 p-4 text-sm text-slate-100">
<code>{value || ''}</code>
</pre>
)
}
return (
<textarea
value={value || ''}
onChange={(e) => setValue(e.target.value)}
className="min-h-[240px] w-full rounded-lg border border-slate-300 bg-slate-950 p-4 font-mono text-sm text-slate-100"
spellCheck={false}
/>
)
}
export default CodeEditorThis component:
- reads the prop value with
useVisualEdit - renders a
textareain the Admin editor - renders read-only formatted output in preview and on the frontend
Use the custom editor inside a brick
Then you can render that component inside a brick.
import { types } from 'react-bricks/rsc'
import CodeEditor from './CodeEditor'
interface CodeSnippetProps {
code: string
}
const CodeSnippet: types.Brick<CodeSnippetProps> = () => {
return <CodeEditor propName="code" />
}
CodeSnippet.schema = {
name: 'code-snippet',
label: 'Code Snippet',
getDefaultProps: () => ({
code: "console.log('Hello React Bricks')",
}),
}
export default CodeSnippetIn this example, the code prop is not edited with a built-in React Bricks component.
Instead, your own CodeEditor handles both editing and rendering.
Why this pattern is powerful
The important idea is that useVisualEdit does not care what UI library you use.
As long as your component:
- reads
value - calls
setValue - respects
isReadOnly
you can build a fully custom editing experience around a brick prop.
That means you can integrate:
- third-party editors
- design-system controls
- domain-specific widgets
- internal tools your team already uses
A good rule of thumb
Use useVisualEdit when the editing experience itself needs to be custom.
If you only need:
- simple text
- rich text
- images
- files
- standard sidebar controls
then the normal React Bricks components are simpler and usually better.
Related reading
Summary
useVisualEdit is the advanced hook for creating new visual editing components in React Bricks.
Use it when you need a custom editor UI for a prop, and keep the built-in visual components for everything that does not need this extra flexibility.