Create a brick
Add a sidebar control
Add a sidebar control to let editors choose whether the image appears on the left or right.
What you'll build
In this how-to, you'll add a sidebar control to the TextImage brick so editors can choose whether the image is shown on the left or on the right.
You'll:
- add an
imageSideprop to the component interface - use
clsxto conditionally change the image column order - add
sideEditPropsto the schema - set a default value for the new prop
At the end, editors will be able to switch the image position from the React Bricks sidebar.
Start from the previous example
If you're starting from the brick used in the previous how-to, your TextImage should look like this:
import { Image, Link, RichText, Text, types } from 'react-bricks/rsc'
interface TextImageProps {
title: types.TextValue
description: types.TextValue
image: types.IImageSource
}
const TextImage: types.Brick<TextImageProps> = ({
title,
description,
image,
}) => {
return (
<div className="container">
<div className="grid lg:grid-cols-2 gap-12">
<div>
<Text
propName="title"
value={title}
placeholder="Type a title..."
renderBlock={({ children }) => (
<h2 className="text-3xl font-extrabold">{children}</h2>
)}
/>
<RichText
propName="description"
value={description}
placeholder="Type a description..."
renderBlock={({ children }) => (
<p className="text-lg text-slate-600">{children}</p>
)}
allowedFeatures={[
types.RichTextFeatures.Bold,
types.RichTextFeatures.Link,
]}
renderBold={({ children }) => (
<b className="text-pink-500">{children}</b>
)}
renderLink={({ children, href, target, rel }) => (
<Link
href={href}
target={target}
rel={rel}
className="text-sky-500 hover:text-sky-600 transition-colors"
>
{children}
</Link>
)}
/>
</div>
<div>
<Image
propName="image"
source={image}
alt="Image"
maxWidth={800}
aspectRatio={16 / 9}
/>
</div>
</div>
</div>
)
}
TextImage.schema = {
name: 'text-image',
label: 'Text Image',
getDefaultProps: () => ({
title: 'Thick as a brick',
description: 'Another brick in the wall',
}),
}
export default TextImageAdd the imageSide prop
First, add a new prop to the interface:
interface TextImageProps {
title: types.TextValue
description: types.TextValue
image: types.IImageSource
imageSide: 'left' | 'right'
}Then read it from the component props:
const TextImage: types.Brick<TextImageProps> = ({
title,
description,
image,
imageSide,
}) => {This prop will store the editor's choice for the image position.
Use clsx for conditional classes
Before using clsx, install it in your project:
pnpm add clsxTo conditionally change the order of the image column, import clsx:
import clsx from 'clsx'Now update the <div> that wraps the image:
<div className={clsx({ 'order-first': imageSide === 'left' })}>
<Image
propName="image"
source={image}
alt="Image"
maxWidth={800}
aspectRatio={16 / 9}
/>
</div>If imageSide === 'left', the order-first class is applied, so on large screens the image becomes the first column.
If imageSide === 'right', no extra class is added, so the text stays first and the image stays on the right.
Add sideEditProps to the schema
Now let's add a sidebar control to the schema:
TextImage.schema = {
name: 'text-image',
label: 'Text Image',
getDefaultProps: () => ({
title: 'Thick as a brick',
description: 'Another brick in the wall',
imageSide: 'right',
}),
sideEditProps: [
{
name: 'imageSide',
label: 'Image Side',
type: types.SideEditPropType.Select,
selectOptions: {
display: types.OptionsDisplay.Radio,
options: [
{ value: 'left', label: 'Left' },
{ value: 'right', label: 'Right' },
],
},
},
],
}sideEditProps defines controls shown in the React Bricks sidebar for the selected brick.
Each object in this array describes one editable setting:
name: the prop name to update on the componentlabel: the label shown in the sidebar UItype: the kind of control to render
In this case, type: types.SideEditPropType.Select means we want to render a select-style control.
Inside selectOptions:
display: types.OptionsDisplay.Radiotells React Bricks to show the options as radio buttonsoptionsdefines the available choices- each option has a
value, which is stored in the prop, and alabel, which is shown to the editor
So when the editor picks Left, the prop becomes imageSide: 'left'.
When the editor picks Right, the prop becomes imageSide: 'right'.
Set the default value
We also added:
imageSide: 'right'inside getDefaultProps.
This means new TextImage bricks will show the image on the right by default.
Final code
Your full TextImage.tsx file should now look like this:
import clsx from 'clsx'
import { Image, Link, RichText, Text, types } from 'react-bricks/rsc'
interface TextImageProps {
title: types.TextValue
description: types.TextValue
image: types.IImageSource
imageSide: 'left' | 'right'
}
const TextImage: types.Brick<TextImageProps> = ({
title,
description,
image,
imageSide,
}) => {
return (
<div className="container">
<div className="grid lg:grid-cols-2 gap-12">
<div>
<Text
propName="title"
value={title}
placeholder="Type a title..."
renderBlock={({ children }) => (
<h2 className="text-3xl font-extrabold">{children}</h2>
)}
/>
<RichText
propName="description"
value={description}
placeholder="Type a description..."
renderBlock={({ children }) => (
<p className="text-lg text-slate-600">{children}</p>
)}
allowedFeatures={[
types.RichTextFeatures.Bold,
types.RichTextFeatures.Link,
]}
renderBold={({ children }) => (
<b className="text-pink-500">{children}</b>
)}
renderLink={({ children, href, target, rel }) => (
<Link
href={href}
target={target}
rel={rel}
className="text-sky-500 hover:text-sky-600 transition-colors"
>
{children}
</Link>
)}
/>
</div>
<div className={clsx({ 'order-first': imageSide === 'left' })}>
<Image
propName="image"
source={image}
alt="Image"
maxWidth={800}
aspectRatio={16 / 9}
/>
</div>
</div>
</div>
)
}
TextImage.schema = {
name: 'text-image',
label: 'Text Image',
getDefaultProps: () => ({
title: 'Thick as a brick',
description: 'Another brick in the wall',
imageSide: 'right',
}),
sideEditProps: [
{
name: 'imageSide',
label: 'Image Side',
type: types.SideEditPropType.Select,
selectOptions: {
display: types.OptionsDisplay.Radio,
options: [
{ value: 'left', label: 'Left' },
{ value: 'right', label: 'Right' },
],
},
},
],
}
export default TextImageTry it in the editor
Go back to the visual editor and select the Text Image brick.
Now, in the sidebar, you'll see an Image Side control with two radio options:
LeftRight
When you switch between them, the image column changes position.
What's next
Your brick now has a sidebar control that changes the layout without editing the code.
From here, you can add more sidebar props for spacing, colors, alignment, or image aspect ratio.