Watch our biggest AI launch event

Announcing Visual Copilot - Figma to production in half the time

Builder.io logo
Contact Sales
Platform
Developers
Contact Sales

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

When you want your custom component to accept other blocks, configure your component with children. The following video demonstrates a custom tabs component that accepts Builder blocks as content. Each tab receives a unique block that the user drags and drops in.

To get the most out of this tutorial, you should have the following:

For more details on child-related options when working with child components, visit the canHaveChildren, childRequirements, and defaultChildren sections of the registerComponent() documentation.

When adding children, Builder's Gen 1 SDKs use withChildren(), while the Gen 2 SDKs require <Blocks>. For more information on the SDKs, visit SDK Comparision.

For Gen 1 or Gen 2, now your component should show up in the Visual Editor with no further configuration in the code.

The following video shows the Hero block in the Custom Components section of the Insert tab. When the Hero block is on the page in the Visual Editor, you can drag and drop more blocks and drop them into the Hero block, along with the other children defined in code.

To use a registered component with children, do the following:

  1. If you're still developing your component, change the Preview URL to localhost with the port you're using for your local app and the page name. In this example, the URL is http://localhost:3000/cc-children.
  2. Drag and drop your custom component into the work area.
  3. Drag other blocks onto your custom component.

In the following video, after the user drops a Columns block into the custom component, they open the Layers tab to show the Columns block nested within the Hero block.

For React, use this technique if you want to manually specify details about your custom component's children. This section shows you how to to create a a Tabs component that renders multiple sets of children. Refer to the corresponding comments in the code for each step.

  1. Import React, useState, BuilderBlocks, and Builder along with your other JavaScript imports.
  2. Create your component. This example creates a Tabs component where each tab has a label as well as content that displays when that tab is active.
  3. Configure BuilderBlocks so that Builder knows what makes up your component.
  4. Register your component using registerComponent(). Specify the required values of name and type as well as subFields. The subFields are label and content and they get their values from defaultValue. When you create a new tab in the Visual Editor, the default label is New Tab 1 while the content is empty, because of the empty array.
import {
  Blocks,
  BuilderBlock,
  RegisteredComponent,
} from '@builder.io/sdk-react';
import { useState } from 'react';

type Tab = {
  tabName: string;
  children: BuilderBlock[];
};
interface TabProps {
  tabList: Tab[];
  builderBlock: BuilderBlock;
}

const CustomTabs = (props: TabProps) => {
  const [activeTab, setActiveTab] = useState(0);

  return (
    <div>
      <h2>Custom Component with editable regions</h2>

      <div>
        <div>
          {/* 
            The tabList[] prop is an array that represents the tabs.
            Each tab has a tabName, which is displayed as the button label,
            and children, which are the content blocks rendered inside the tab.
            This comes from the inputs declared inside your custom component.
            For more details: https://www.builder.io/c/docs/custom-components-input-types
          */}
          {props.tabList?.map((tab, index) => (
            <button
              key={index}
              className={activeTab === index ? 'active' : ''}
              onClick={() => setActiveTab(index)}
            >
              {tab.tabName}
            </button>
          ))}
        </div>
      </div>

      {props.tabList && props.tabList.length !== 0 && (
        <div>
          {props.tabList.map((tab, index) => (
            <div
              key={index}
              style={{ display: activeTab === index ? 'block' : 'none' }}
            >
              {/** 
                The Blocks component from Builder.io dynamically renders the content inside the tab.
                - `parent` is the ID of the Builder's parent div, ensuring correct content rendering.
                - `path` defines where to find the content for this Tab
                - `blocks` contains the actual content to be displayed inside the tab.
              */}
              <Blocks
                parent={props.builderBlock?.id}
                path={`component.options.tabList.${index}.children`}
                blocks={tab.children}
              />
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export const customTabsInfo: RegisteredComponent = {
  component: CustomTabs,
  name: 'TabFields',
  shouldReceiveBuilderProps: {
    /** enabling this causes the SDK to pass the `builderBlock` prop down to the component */
    builderBlock: true,
  },
  inputs: [
    {
      name: 'tabList',
      type: 'list',

      subFields: [
        {
          name: 'tabName',
          type: 'string',
        },
        {
          name: 'children',
          type: 'uiBlocks',
          hideFromUI: true,
          defaultValue: [
            {
              '@type': '@builder.io/sdk:Element',
              component: {
                name: 'Text',

                options: {
                  text: 'This is editable block within the builder editor',
                },
              },
              responsiveStyles: {
                large: {
                  ...,
                },
                small: {
                  ...,
                },
              },
            },
          ],
        },
      ],
    },
  ],
};

This section explains how to configure custom components to accept children with the Gen 1 and Gen 2 SDKs. By implementing editable regions within custom components, users can dynamically add and customize content within their Builder projects.

To use a custom component with multiple sets of children in the Visual Editor, take the following steps:

  1. In the Insert tab, expand the Custom Components section.
  2. Drag and drop your component onto the work area.
  3. With your component selected, click the Edit button and add sets of children if needed.
  4. Drag other blocks, for example Text or Image blocks, into the Add Block region of your component.

To customize your components even further, leverage Builder's Input Types.

For more examples of custom components with multiple sets of children, visit:

Was this article helpful?

Product

Visual CMS

Theme Studio for Shopify

Sign up

Login

Featured Integrations

React

Angular

Next.js

Gatsby

Get In Touch

Chat With Us

Twitter

Linkedin

Careers

© 2020 Builder.io, Inc.

Security

Privacy Policy

Terms of Service

Newsletter

Get the latest from Builder.io

By submitting, you agree to our Privacy Policy

Product

Platform Overview

Integrations

What's New

Open Source

Builder

Builder

Mitosis

Mitosis

Qwik

Qwik

Partytown

Partytown

Popular Guides

From Design to Code Guide

Composable Commerce Guide

Headless CMS Guide

Headless Commerce Guide

Composable DXP Guide

Design to Code

Resources

Blog

Knowledge Base

Community Forum

Partners

Templates

Success Stories

Showcase

Resource Center

Frameworks

React

React

Next

Next.js

Qwik

Qwik

Gatsby

Gatsby

Angular

Angular

Vue

Vue

Svelte

Svelte

Remix logo

Remix

Nuxt

Nuxt

Hydrogen

Hydrogen

See All

© 2024 Builder.io, Inc.

Security

Privacy Policy

SaaS Terms

Security & Compliance

Cookie Preferences