Skip to main content

Create a custom Sidebar component

Superblocks supports adding Custom Components to the frontend of your Applications. In this guide, you will learn how to use a custom React component alongside the out-of-the-box Tabs component in Superblocks to build a multi-page app experience.

Note that the individual pages will not have their own route (i.e. the URL will be static as the user navigates through the app). Multi-page apps with dedicated URL routes per page are currently in beta. Feel free to reach out to our support in case you have any questions.

A preview of a sidebar and a tabs component for multi-page app experiences.

Step-by-step guide

info

You can either follow the step-by-step guide to create the custom Sidebar component from scratch or jump to this section, which provides you with a pre-built version of the Sidebar that you can import into your Superblocks Application.

As you follow the steps below to create the Sidebar component, you can consult the final version of the code in this GitHub repository to compare it with your own work.

Material UI List component

In this guide, we are going to use a customized list component from the Material UI component library.

A List component from the Material UI component library.

Install the Superblocks CLI

If you haven't yet installed the Superblocks CLI, go through Step 1 of the custom component Quickstart to install it.

Create your Sidebar component locally

Next, you need to configure your component. Let's use the Superblocks CLI to create the component locally.

First, we'll navigate into the application directory that we initialized above.

cd apps/[MY_APPLICATION_DIRECTORY]

Then, we'll run the create command to initialize our component locally.

superblocks components create

Follow the wizard in the Superblocks CLI and make the following selections:

  • Would you like to generate an example custom component? N
  • What is the display name of the component you want to create? (e.g. To-Do List) Sidebar
  • What is the machine readable name of the component you want to create? Sidebar

  • Does this component have properties? Y
  • What is the path of the property? This will be used to access the property in your code (e.g. currentTasks) items
  • What is the type of items? any (raw expression)
  • Should this property be shown in the properties panel? Y
  • What is the label of the property? (e.g. Tasks) Navigation items

  • Do you want to add another property? Y
  • What is the path of the property? This will be used to access the property in your code (e.g. currentTasks) selectedItem
  • What is the type of items? string
  • Should this property be shown in the properties panel? N

  • Do you want to add another property? N

  • Does this component have events? Y
  • What is the label of the event? (e.g. On Change) onItemSelect
  • What is the path of the event? This will be used to trigger the event in your code (e.g. onChange) onItemSelect
  • Do you want to add another event? N

The CLI will now create your custom component project files. Open your application folder in your favorite IDE (e.g. VS Code) to inspect them:

The user has generated the component files using the Superblocks CLI.

In the /components directory Superblocks has created a Sidebar folder that contains the following files: component.tsx, config.ts, types.ts.

info

Please have a look at the custom component Quickstart to learn more about the files that have been generated for your Sidebar component.

Add the Material UI code to your custom component directory

Now, navigate to the Material UI list component, select TS (TypeScript) and click on the Show Code button located below the component preview to reveal the React code for the List component:

Reveal the TypeScript code of the Material UI List component.

In VS Code, open the component.tsx, then copy and paste all import statements from the component code on the Material UI website right below the existing import statements of your Superblocks component in your editor.

The import statements for the Material UI have been pasted to VS Code.

In the screenshot, you can see that VS Code is unable to locate the packages for the import statements you've added to your component.tsx, as indicated by the red underlines. Open a Terminal in VS Code and execute the following command to install the necessary JavaScript libraries:

npm install @mui/icons-material @mui/material @emotion/styled @emotion/react

Your editor should now be able to detect the libraries and the error messages should go away.

Next let's copy over the rest of the Component's code from the Matrial UI website. First, start by copying and pasting the data array right below the import statements in your component.tsx:

const data = [
{ icon: <People />, label: 'Authentication' },
{ icon: <Dns />, label: 'Database' },
{ icon: <PermMedia />, label: 'Storage' },
{ icon: <Public />, label: 'Hosting' },
];
The MaterialUI icons are added to a data array.

Next, copy the definition of FireNav and paste it below the data array in your component.tsx:

const FireNav = styled(List)<{ component?: React.ElementType }>({
'& .MuiListItemButton-root': {
paddingLeft: 24,
paddingRight: 24,
},
'& .MuiListItemIcon-root': {
minWidth: 0,
marginRight: 16,
},
'& .MuiSvgIcon-root': {
fontSize: 20,
},
});

The FireNav is defined as a React ElementType in VS Code.

Now you can go on and replace your component's return statement with the return statement from the Material UI component that has the Sidebar's JSX. Replace the following code:

The auto-generated JSX code will be replaced by the JSX from MaterialUI component.

With this code from the Material UI component:

The return statement from the MaterialUI component page is going to be pasted in VS Code.

Next, you can navigate to your Superblocks Application and preview your custom Sidebar component in Local Dev Mode. First, open your Terminal and run the following command:

superblocks components watch

Once the watch command is running successfully:

The user runs the Superblocks CLI watch command in their local Terminal.

You can navigate to your Superblocks Application and turn on the Local Dev Mode:

The user turns on the Local Dev Mode for Custom Components in the Superblocks UI.

The custom Sidebar component should now appear under Custom Components in the Components panel:

The custom Sidebar component shows up in the list of custom components in the Superblocks UI.

Drag and drop your component to the Canvas:

The user has dragged and dropped the custom Sidebar component to a Superblocks Application.

You've successfully added the Material UI List component to your Superblocks Application. You can use the Superblocks CLI to upload your Custom Component to your Superblocks Application for the first time. Open your Terminal and run the following command:

superblocks components upload

In the next sections we will make the Sidebar component functional.

Allow users to pass custom navigation items

The user opens the Sidebars' properties panel to pass Navigation items to the Sidebar.

Paste the following JSON into the Navigation items input field in the properties panel:

[{
key: 'first-section',
label: 'First section',
type: 'group',
children: [{
key: 'authentication',
label: 'Authentication',
icon: 'People'
},{
key: 'database',
label: 'Database',
icon: 'Dns',
disabled: true
}]
}, {
key: 'second-section',
label: 'Second section',
type: 'group',
children: [{
key: 'storage',
label: 'Storage',
icon: 'PermMedia'
},{
key: 'hosting',
label: 'Hosting',
icon: 'Public'
}]
}]

Replace this code in the component.tsx file that we added earlier when we migrated the Material UI component:

const data = [
{ icon: <People />, label: 'Authentication' },
{ icon: <Dns />, label: 'Database' },
{ icon: <PermMedia />, label: 'Storage' },
{ icon: <Public />, label: 'Hosting' },
];

with the following code:

const ICON_MAP: { [key: string]: any } = {
People: <People />,
Dns: <Dns />,
PermMedia: <PermMedia />,
Public: <Public />,
// ... add other icons to the map
};

Then, replace the entire return() statement in the component.tsx file with this code:

return (
<Box sx={{ display: 'flex' }}>
<ThemeProvider
theme={createTheme({
components: {
MuiListItemButton: {
defaultProps: {
disableTouchRipple: true,
},
},
},
palette: {
primary: { main: 'rgb(102, 157, 246)' },
background: { paper: 'rgb(5, 30, 52)' },
},
})}
>
<Paper elevation={0} sx={{ maxWidth: 256 }}>
<FireNav component="nav" disablePadding>
<div>
{items.map((item: any) => {
return (
<div key={item.key} style={{ paddingBottom: "8px" }}>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 400,
lineHeight: "16px",
color: 'white',
padding: "8px 0px",
marginBottom: "2px",
}}
/>
{item.children.map((child: any) => {
const isSelected = child.label === selectedItem;
return (
<ListItemButton
key={child.key}
sx={{
py: 0,
minHeight: 32,
borderRadius: "4px",
backgroundColor: 'white',
color: 'white',
marginBottom: "2px",
"&:hover": {
backgroundColor: 'white',
color: 'white',
},
}}
>
<ListItemIcon sx={{ color: "inherit" }}>
{ICON_MAP[child.icon]}
</ListItemIcon>
<ListItemText
primary={child.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 500,
color: "inherit",
}}
/>
</ListItemButton>
);
})}
</div>
);
})}
</div>
</FireNav>
</Paper>
</ThemeProvider>
</Box>
);
caution

At this point you must provide a JSON to Navigation items in the properties panel otherwise you will see this error message: Error: Cannot read properties of undefined (reading 'map').

The Sidebar component should now dynamically load the JSON and render the new navigation structure:

The custom Sidebar component displays the navigation items passed via the properties panel.

Style the custom component

To make the Sidebar component look better, replace your component's return() function in the component.tsx file with the following code:

return (
<Box sx={{
display: 'flex',
border: '1px solid #E8EAED',
borderRadius: '4px',
height: '100%'
}}>
<ThemeProvider
theme={createTheme({
components: {
MuiListItemButton: {
defaultProps: {
disableTouchRipple: true,
},
},
},
palette: {
mode: 'dark',
primary: { main: 'rgb(102, 157, 246)' },
background: { paper: 'rgb(5, 30, 52)' },
},
})}
>
<Paper
elevation={0}
sx={{
maxWidth: 256,
background: "none !important",
backgroundColor: "none !important",
}}
>
<FireNav component="nav" disablePadding>
<div>
{items.map((item: any) => {
return (
<div key={item.key} style={{ paddingBottom: "8px" }}>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 400,
lineHeight: "16px",
color: 'rgb(69, 77, 95)',
padding: "8px 16px",
marginBottom: "2px",
fontFamily: "Inter"
}}
/>
{item.children.map((child: any) => {
const isSelected = child.label === selectedItem;
return (
<ListItemButton
key={child.key}
sx={{
py: 0,
minHeight: 32,
borderRadius: "4px",
backgroundColor: "",
color: "#404040",
marginBottom: "2px",
fontFamily: "Inter",
"&:hover": {
backgroundColor: "black",
color: "white",
},
}}
>
<ListItemIcon sx={{ color: "inherit" }}>
{ICON_MAP[child.icon]}
</ListItemIcon>
<ListItemText
primary={child.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 500,
color: "inherit",
}}
/>
</ListItemButton>
);
})}
</div>
);
})}
</div>
</FireNav>
</Paper>
</ThemeProvider>
</Box>
);

When you have Local Dev Mode turned on in Superblocks, your Application should hot-reload the Sidebar component and it should now have a light design:

The Sidebar component has a light design after its CSS has been edited.

Optional - Add support for Dark Mode

To apply lighter font and hover colors when Dark mode is activated using Superblocks Themes, add the following to your custom Sidebar component.

In your code editor, open the config.ts file and add the following new theme property to the list of properties:

{
path: "theme",
dataType: "any",
propertiesPanelDisplay: {"label":"Theme","controlType":"js-expr"},
isExternallyReadable: false,
isExternallySettable: true
}
Add the new Theme property to the list of properties in your config.ts.

You should now find the new Theme property in your component's properties panel. Then, set the property to theme to pass the theme object to your component:

The new theme property is available in the component's properties panel.

To utilize the theme object in your custom component, you need to include theme in the React Props passed to the component. Add the following line to your component.tsx:

Theme was added to the props in the custom component's React code.

Among other properties, the theme object contains a mode property that can be either "DARK" or "LIGHT", reflecting the user's selected mode in the Superblocks Application. When the mode is changed in Superblocks, an updated theme object is passed to your custom Sidebar component, triggering a re-render and ensuring it updates accordingly.

Here is an extract from the theme object that will be passed to your custom component:

{
"ENTITY_TYPE": "THEME",
"colors": {
"appBackground": "#F9FAFB",
"contrastText": "#FFFFFF",
"danger": "#F45252",
"dangerLight": "#fdc5c5",
"editor": {
"builtin": "#e5ab64",
...
},
"info": "#29BBFF",
"neutral": "#FFFFFF",
"neutral100": "#E8EAED",
"neutral200": "#C6CAD2",
"neutral25": "#F9FAFB",
"neutral300": "#A4AAB7",
"neutral400": "#818A9C",
"neutral50": "#F3F4F6",
"neutral500": "#6C7689",
"neutral700": "#454D5F",
"neutral900": "#1F2633",
"primary500": "#29BBFF",
"primary600": "#00a7f5",
"primary700": "#0096db",
"primaryHighlight": "#eefaff",
"success": "#0CC26D",
"warning": "#FF9F35"
},
"fontFamily": "Roboto",
"mode": "LIGHT"
}

The colors specified in the object, such as natural100, are primarily controlled by Superblocks and invert when the user changes the Theme from DARK to LIGHT or vice versa.

This allows us to replace the hardcoded colors in your custom React code with the placeholder values from the theme object to add support for Dark Mode to your Sidebar component.

Replace your component's return() function in the component.tsx file with the following code:

  return (
<Box sx={{
display: 'flex',
border: '1px solid #E8EAED',
borderRadius: '4px',
height: '100%'
}}>
<ThemeProvider
theme={createTheme({
components: {
MuiListItemButton: {
defaultProps: {
disableTouchRipple: true,
},
},
},
palette: {
mode: theme?.mode === "DARK" ? "dark" : "light",
primary: { main: 'rgb(102, 157, 246)' },
background: { paper: 'rgb(5, 30, 52)' },
},
})}
>
<Paper
elevation={0}
sx={{
maxWidth: 256,
background: "none !important",
backgroundColor: "none !important",
}}
>
<FireNav component="nav" disablePadding>
<div>
{items.map((item: any) => {
return (
<div key={item.key} style={{ paddingBottom: "8px" }}>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 400,
lineHeight: "16px",
color: theme?.colors?.neutral700,
padding: "8px 16px",
marginBottom: "2px",
fontFamily: "Inter"
}}
/>
{item.children.map((child: any) => {
const isSelected = child.label === selectedItem;
return (
<ListItemButton
key={child.key}
sx={{
py: 0,
minHeight: 32,
borderRadius: "4px",
backgroundColor: "",
color: theme?.colors?.neutral700,
marginBottom: "2px",
fontFamily: "Inter",
"&:hover": {
backgroundColor: isSelected
? theme?.colors?.neutral900
: theme?.colors?.neutral100,
color: isSelected
? theme?.colors?.neutral
: theme?.colors?.neutral900,
},
}}
onClick={() => selectItem(child.label)}
>
<ListItemIcon sx={{ color: "inherit" }}>
{ICON_MAP[child.icon]}
</ListItemIcon>
<ListItemText
primary={child.label}
primaryTypographyProps={{
fontSize: 14,
fontWeight: 500,
color: "inherit",
}}
/>
</ListItemButton>
);
})}
</div>
);
})}
</div>
</FireNav>
</Paper>
</ThemeProvider>
</Box>
);

Next, open your Superblocks Application in the browser and set the Mode to "Dark" using the Theme panel in the left-hand side menu. Your custom component should now adopt the inverted colors and look great in Dark Mode.

The custom Sidebar component is nicely

Finally, upload your component by running the superblocks components upload in your Terminal.

Add an event handler to the custom component

When you previously used the Superblocks CLI to generate the files for the the Sidebar component you added a property called selectedItem to your component. In this section you will add logic to your component code that will update the selectedItem property to hold the name of the navigation item the user clicked on when using the Sidebar component.

You can later use this value to update the state of a Tabs component and switch to a Tab with the same name as the navigation item the user has clicked on. This is how your users will be able to navigate to a different "page".

Start by adding an onClick event handler to the <ListItem> component in your React code in the component.tsx file:

onClick={() => selectItem(child.label)}
An onClick event handler was added to the ListItemButton component to handle click events.

Finally, add the function definition to your component.tsx right above the return statement:

// Event handler: onItemSelect()
const selectItem = (item: any) => {
// use the provided updateProperties() method to set the *item* property
updateProperties({ selectedItem: item });
// trigger the onItemSelect event
onItemSelect();
};
The selectItem function is used to update the properties of the Sidebar React component.

Note: You can consult the final version of the code in this GitHub repository to compare it with your own work.

tip

Congratulations, you have built a fully functional Sidebar component from scratch! In the next step, you can connect the Sidebar to a Tabs component to allow your users to navigate to a different page.

The user has successfully added a fully functional custom Sidebar component to a Superblocks Application.

Import the pre-built component

Instead of creating the Sidebar component from scratch step-by-step using the above guide, you can also upload the final component code to your Superblocks Application by following the steps outlined below.

info

This is Technical Guide explains how to add a custom Sidebar component to your Superblocks Applications. To learn more about Custom Components please visit this page.

caution

Custom components need to be uploaded specifically to each Superblocks Application where you want to use them. In Step 1 below, select the URL of the Superblocks Application to which you want to upload the Sidebar component.

Steps to take:

  1. [Optional] If you haven't done it yet, follow Step 1 in this guide to install the Superblocks CLI and initialize your Superblocks repository locally

  2. [Optional] If you don't yet have a Components folder in apps/[MY_APPLICATION_DIRECTORY], follow Step 2 in this guide to create the example To-Do List component

    info

    You don't actually need the example To-Do list component; running the above command simply helps scaffold out our local environment.

  3. Clone the custom Sidebar component Github repository

  4. Copy and paste the /Sidebar folder from the Github repository into the /components folder of the Superblocks repository you have created in Step 1. (Place the directory on the same level as the /ToDoList directory)

  5. Open package.json file in your editor and add the following dependencies to "dependencies":

    "@emotion/react": "^11.11.3",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.15.6",
    "@mui/material": "^5.15.6",
    The JavaScript libraries used by the MaterialUI component are added to the package.json file.
  6. Open a Terminal and navigate into apps/[MY_APPLICATION_DIRECTORY]

  7. In your Terminal run npm install to install any missing libraries for the Sidebar component

  8. In your Terminal run superblocks components upload to upload the component to your Superblocks Application

  9. The custom Sidebar component should now appear under Custom Components in the Components panel:

    The custom Sidebar component is part of the list of custom component in the Superblocks App builder.

    Drag and drop your component to the Canvas (Note that the Component appears empty at this point because it does not yet have navigation; we will add these in the next step):

    The user has added the custom Sidebar component to the Application frontend canvas.
  10. Click on the Sidebar component to open the Properties Panel on the right side of the screen

    The user clicks on the Sidebar component to open the properties panel for it.
  11. Set Navigation items to the following code:

        [{
    key: 'first-section',
    label: 'First section',
    type: 'group',
    children: [{
    key: 'authentication',
    label: 'Authentication',
    icon: 'People'
    },{
    key: 'database',
    label: 'Database',
    icon: 'Dns',
    disabled: true
    }]
    }, {
    key: 'second-section',
    label: 'Second section',
    type: 'group',
    children: [{
    key: 'storage',
    label: 'Storage',
    icon: 'PermMedia'
    },{
    key: 'hosting',
    label: 'Hosting',
    icon: 'Public'
    }]
    }]
    A fully functional custom sidebar component has been uploaded to a Superblocks Application.

Connect the Sidebar to a Tabs component

Whether you followed the Step-by-step guide or Imported the pre-built component, the next steps involve adding a Tabs component to your Superblocks application to act as the container for your "pages".

The currently visible tab in a Tabs component is a settable property, meaning it can be externally set by other components, such as the Sidebar component you just added to your Application.

  1. Drag and drop a Tabs component to the Canvas and place it to the right of the Sidebar component

    The user adds a Tabs component right next to the custom sidebar component.
  2. Rename the Tabs to:

    • Authentication
    • Database
    • Storage
    • Hosting
  3. Set the Default tab to Authentication

    The names of the individual tabs have been edited in the properties panel.
  4. Click on the Sidebar component to open the Properties Panel

    The user opens the Sidebar's properties panel to edit the onItemSelect event handeler.
  5. Add an Action to the onItemSelect event handler

    • Set the Action Type to Set Component Property
    • Set Component to Tabs1 (assuming that this is the name of your Tabs component)
    • Set Value to {{Sidebar1.selectedItem}} (assuming that Sidebar1 is the name of your Sidebar component)
    The onItemSelect event handler has been set to set the Tabs' component properties.

The custom Sidebar component should now allow you to navigate through the different tabs. Each tab acts as its own "page" within the app.

The Sidebar component can now be used to update the state of a Tabs component.

You can make a few final changes to improve the multi-page experience further:

  1. Resize the Tabs component to cover the entire page.

  2. Turn off the visibility of the Tabs header:

    The header of the Tabs component can be set to invisible via the properties panel.

Frequently Asked Questions

How to add additional navigation items to the Sidebar component

To edit the navigation items displayed by the Sidebar component, you can modify the JSON passed to the Sidebar's Navigation Items property. Remember to update the names of the tabs in the Tabs component to exactly match the label of each item in the JSON.

How can I change the design of the Sidebar component

You can edit the CSS in your component.tsx file to change the design of the Sidebar component. Serve your component from your local dev server using the superblocks components watch so that you can see live updates of the changes you make.

You can also take a look at the guide on Styling Custom Components for more general information on how to design custom components in Superblocks.

Additional resources

Learn more about how to leverage custom components for your internal tools here: