How to Mix Element Proptypes to Make a “Sale Banner” Block

Element Proptypes allow you to represent a vast variety of data with built-in user selectors, such as color pickers, dropdown menus, and sliders. In this tutorial, you will combine multiple Element Proptypes to make a “Sale Banner” custom Block.

Element Proptypes are How Element Represents Data

The Element platform uses Element Proptypes to represent different types of data, such as boolean values, numbers, colors, or dates. In this tutorial, you will be building a “Sale Banner” custom Block using Element, mixing several Proptypes to achieve the desired result. Element Proptypes give configuration control to the end user, allowing the user to choose data without needing the developer to submit changes to the custom Block. They can be used to allow custom styles in custom Blocks, such as changing fonts, as discussed in the previous articles on custom font size and custom font faces.

The entire list of Element Proptypes is available in the Element Platform Documentation. Using Element Proptypes has been discussed in the article Working With Element Proptypes Tutorial from the Element Platform Documentation, which shows you how to create a block with configurable light and dark modes.

This tutorial uses the principles explained in that article to build a custom “Sale Banner” Block.

What you Will Learn

You will be using the following Element Proptypes:

Combining these Proptypes provide powerful developmental flexibility for the user of your custom Block in the VOLT Store.

Create a Custom Block for Use as a Sale Banner

The rest of this tutorial will assume that you are familiar with creating and publishing a custom Block for your VOLT Store using Element.

To help you learn how to make a custom Block, please refer to the 15-minute article “Building An Element Page Tutorial” located in the Element Platform Documentation. Or, try the 27-minute video playlist “Element Tutorial | VOLT Learning Center” on YouTube.

You will also need authorization from Volusion to develop custom Blocks before beginning this tutorial. Please read the page “How To Get Approved To Develop Blocks” located in the Element Platform Documentation.

This tutorial will show you how to build a custom Block for use as a Sale Banner by incorporating a variety of Element Proptypes.

Create a New Custom Block Using the Element CLI

The first step to making a custom Block is using the element new command in the Element Command Line Interface (CLI). You may already have logged in to the Element CLI; if you have not yet logged in, then please do so by entering the element login command into your terminal:

element login

This command will prompt you to enter the username and password that you usually use with VOLT’s Site Designer.

Once logged in, make a new custom Block in your terminal using the Element CLI:

element new SaleBannerBlock
cd SaleBannerBlock
npm install

Next, create a Git repository in the directory to track your changes by entering the commands:

git init
git add -A
git commit -am "Initial Commit"

This is a good time to backup the repository online, such as to GitHub. (Please refer to the article Adding a repository from your local computer to GitHub for instructions using GitHub Desktop.

Edit the /src/configs.js file for your Sale Banner

The first step is to establish the Element Proptypes you will be using for your Sale Banner.

In your text editor or IDE (such as VS Code ), open up your /src/configs.js file from the SaleBannerBlock directory.

Replace the entire text of the /src/configs.js file with the following:

import { ElementPropTypes } from "@volusion/element-proptypes"
export const configSchema = {
section1: {
type: ElementPropTypes.sectionHeader,
},
backgroundColor: {
label: "Background Color",
type: ElementPropTypes.color,
},
section2: {
type: ElementPropTypes.sectionHeader,
},
text: {
label: "Heading Text",
type: ElementPropTypes.editorFull,
},
section3: {
type: ElementPropTypes.sectionHeader,
},
color: {
label: "Font Color",
type: ElementPropTypes.color,
},
fontSizeSlider: {
label: "Font Size (rem)",
type: ElementPropTypes.slider,
},
textAlign: {
label: "Text Alignment",
type: ElementPropTypes.oneOf(["left", "center", "right"]),
},
section4: {
type: ElementPropTypes.sectionHeader,
},
readOnlyInstructions: {
label: "",
type: ElementPropTypes.readOnly,
},
link: {
label: "Link URL",
type: ElementPropTypes.string,
},
}

export const defaultConfig = {
section1: "Background Color",
backgroundColor: "rgba(0,0,0,1)",
section2: "Sale Banner Text",
text: "<h1>50% Off Sale Items</h1>",
section3: "Font Options",
fontColor: "rgba(255,255,255,1)",
fontSizeSlider: {
labelPrefix: "rem",
labelStepSize: 0.5,
labelSuffix: "",
min: 0.25,
max: 4,
stepSize: 0.25,
selectedValue: 3,
vertical: true,
},
textAlign: "center",
section4: "Optional Link",
readOnlyInstructions: "Leave URL blank for no link",
link: "",
}

This code establishes multiple configurable props for use in your custom Sale Banner Block, as well as some headings and read-only content.

The props that are not headings or read-only can be changed by the user of the custom Block inside VOLT’s Site Designer.

Explaining the Proptypes Used in the Sale Banner

The first thing you will notice is the use of multiple “sectionHeader” Proptypes, which are simply headings that will appear in VOLT’s Site Designer. These section headers help keep your custom Block fields readable by grouping them together.

The “color” Proptype provides the user with a color picker tool that will save the color in rgba format. The default colors given in the example are a black background with white font.

The “editorFull” Proptype provides the user with a rich text editor (also called a WYSIWYG editor), which gives the user the ability to add multiple headings and select bold or italic styles. This rich text is saved as HTML markup inside Element. The default text for the Sale Banner in the example is a <h1> heading element that reads “50% Off Sale Items.”

The “slider” Proptype creates a drag-and-drop slider that lets the user assign a numeric value, in this case for font size. The included example provides a vertical slider (top-to-bottom) with steps from 0.25rem to 4rem. In the example, the steps values are every 0.25rem, but the labels only appear every 0.5rem, starting from the bottom (0.25rem, 0.75em, etc.). The slider’s selected value is saved as a number (in the fontSizeSlider.selectedValue prop, as you will see later).

The “oneOf” Proptype creates a dropdown menu from an arbitrary JavaScript array of items. In this example, the menu gives the user the option to select the alignment of the text in the banner. As you can see in the code, this is achieved using an array of strings ["left", "center", "right"].

The “readOnly” Proptype is purely informational, offering an option to provide instructional text in the custom Block’s configuration in VOLT’s Site Designer. Unlike the “sectionHeader” Proptype, an empty label property is recommended for use with the “readOnly” Proptype. Without specifying an empty label, the “readOnly” Proptype will include the name of the prop as a label by default. In comparison, the “sectionHeader” Proptype does not include any label by default.

The “string” Proptype holds arbitrary text in the form of a JavaScript string. In this example, the “string” Proptype holds a URL for the Sale Banner to link to. If there is no link provided, then the Sale Banner will not be a link. Note that an equivalent behavior could be also achieved with the “bool” Proptype, which would represent a simple true-and-false boolean value. 

Edit Your /src/getStyles.js file for Your Sale Banner

Open up the file /src/getStyles.js from the custom Block in your IDE or text editor.

Replace the contents of that file with the following code:

export const getStyles = (blockConfig) => {
const { backgroundColor, fontColor, fontSizeSlider, textAlign } = blockConfig
const fontSize = fontSizeSlider.selectedValue

return {
banner: {
backgroundColor: backgroundColor,
color: fontColor,
fontSize: `${fontSize}rem`,
textAlign: textAlign,
},
}
}

In this file, you are creating a CSS class called “banner” to style the Sale Banner custom Block.

In Element, CSS styles are handled by the “CSS-in-JS” (also c alled “JSS”) package Aphrodite. For more information on using Aphrodite in Element, please see the article How To Style a Block With Aphrodite located in the Element Platform Documentation.

Note that because you are writing Javascript-based CSS, the CSS rule names are camelCase and not hyphenated.

That means you reference backgroundColor, fontSize, and textAlign instead of the CSS rules background-color, font-size, and text-align. 

As previously mentioned, the numeric value fontSize is available as the selectedValue property of the fontSizeSlider object prop.

Edit Your /src/Block.js file For Your Sale Banner

Next, open the /src/Block.js file of the custom Block in your text editor or IDE.

Replace the entire code of that file with the following:

import React from "react"
import { css, StyleSheet } from "aphrodite/no-important"
import { getStyles } from "./getStyles"
import { defaultConfig } from "./configs"

const Block = (props) => {
// Get the custom styles to be used in this Block:
const classes = StyleSheet.create(getStyles(props))
// Element helper function to combine Atomic CSS with the custom styles:
const joinClasses = props.joinClasses

// Destructure the banner text and optional link from the props:
const { text, link } = props

// The editorFull Element Proptype returns html as text, not HTML markup.
// React requires an object with the __html property to mark it as HTML:
const outputAsMarkup = { __html: text }
// Make a <div> element based on the banner text using the custom styles:
const outputDiv = (
<div
// Combine Atomic CSS classes with custom styles using joinClasses:
className={joinClasses("ma0 pa3", css(classes.banner))}
// The class ma0 sets all margins to 0, and pa3 sets padding to 1rem.
// dangerouslySetInnerHTML will render HTML markup, such as headings:
dangerouslySetInnerHTML={outputAsMarkup}
// The rich text editor used by the editorFull Element Proptype does
// not allow <script> tags to prevent XSS (cross-site scripting).
></div>
)

// Only include the link <a> element if the banner's link is not empty:
const outputWithLink = link ? <a href={link}>{outputDiv}</a> : outputDiv

return outputWithLink
}

Block.defaultProps = defaultConfig
export default Block

This code uses the joinClasses() function (props.joinClasses) to combine custom styles (from Aphrodite) with Element’s built-in Atomic CSS classes. 

As noted in the code sample, your Sale Banner block uses the “ma0” and “pa3” CSS classes from the Atomic CSS spacing.css file. This improves the spacing of the Block by setting the margin and padding CSS attributes, to 0 (none) and 1rem, respectively.

In React, the method to set the HTML markup contained inside an element (Element.innerHTML) is called dangerouslySetInnerHTML (for reasons explained here). This method allows you to render the HTML saved from the rich text editor created by the editorFull Proptype.

Finally, the sale banner will include a link to the designated URL only if the “link” prop is truthy, meaning not the empty string ("").

Start the Local Server to View the Sale Banner

Now it is time to try out your custom Block. You can launch your local development environment by opening a terminal window and entering the npm run start command:

npm run start

This should open a new window in your local browser. If it does not, then please open a web browser to http://localhost:4000/ in order to examine your new custom Block.

Having previewed the Block, it is time to try adding some local props to make sure that everything is working correctly.

Testing Local Prop Data in /local/index.js

The defaultConfig from /src/configs.js has a lot of configuration already built-in to it. To make sure that props set by the user successfully change the behavior of the Block, you can set up local environment props in the /local/index.js file.

This will let you test the Block locally and observe the effect on the Block when you edit props.

In your IDE or text editor, open the file /local/index.js, and try replacing the lines const localEnvPropOverrides = { … } with the following code:

const localEnvPropOverrides = {
backgroundColor: "slategray",
text: "<h1>Custom prop value for local testing</h1><h2>Second heading</h2>",
fontColor: "orange",
fontSizeSlider: { selectedValue: 1.25 },
textAlign: "left",
link: "/sale",
}

Save the file, then view your Block in the local browser (npm run start).

Reload the page if it did not automatically update, and you should see many changes.

Notably, the custom Block should have become a link to the “/sale” page.

Now you need to update the test files of the custom Block.

Having automated tests makes sure that the functionality of the Block is working correctly.

Unit Testing Your Sale Banner Block

The next step in making your Sale Banner Block is publishing your custom Block.

Publishing your Block will make it available to use in a theme in your VOLT Store.

But first, you need all tests to pass in order to publish a custom Block with Element.

Open up the file /__tests__/Block.spec.js and replace the entire code with the following:

import React from "react"
import { mount } from "enzyme"
import {
mockUtils as utils,
joinClasses,
} from "@volusion/element-block-utils/test-utils"
import { block as Block, defaultConfig } from "../src"
const stripHTMLFromString = (string) => string.replace(/(<([^>]+)>)/gi, "")
let props
describe("The Block", () => {
beforeEach(() => {
props = {
data: {},
utils,
joinClasses,
queryParams: {},
}
})
it("renders without errors", () => {
mount(<Block {...props} />)
})
describe("when there is no custom data", () => {
it("should render the block with the default content", () => {
const wrapper = mount(<Block {...props} />)
expect(wrapper.text()).toBe(stripHTMLFromString(defaultConfig.text))
})
})
describe("when given custom data", () => {
it("should render the block using the custom data", () => {
const customText = "<h1>Custom Block Text</h1><h2>Subheading</h2>"
const wrapper = mount(<Block {...props} text={customText} />)
expect(wrapper.text()).toBe(stripHTMLFromString(customText))
})
})
})

To run the tests, enter the npm run test command in a terminal window:

npm run test

This code only tests the behavior of the dangerouslySetInnerHTML method by making sure that the HTML is being correctly stripped out (or removed) from the displayed text.

To test the CSS is being rendered (displayed) correctly, please refer to the previous article on Unit Testing CSS in Custom Blocks.

To test the Google AMP(Accelerated Mobile Pages) version of your site, copy the same code into the file /__tests__/AMP.spec.js, and then change line 16 from “utils: {},” to:

utils: { ...utils, isAmpRequest: true },

This will cause the test to render the AMP version of the page instead of the regular version of your custom Block.

Once finished with both test files, you are ready to build and publish the Sale Banner Block.

Build and Publish the Sale Banner

In order to publish your custom Block for use in VOLT’s Site Designer, then you need to build and publish the block. In a terminal window, enter the npm run build command:

npm run build

You already updated the tests so that they will pass. Next, publish your custom Block with the Element CLI using the element publish command, including the required -n (“name”) flag:

element publish -n "Sale Banner Block"

Please note that the name of your custom Block needs to be surrounded by quotes.

The Element CLI will then prompt you to select a category for this Block using the arrow keys. Choose Promos & Announcements by scrolling down using the down key; then hit Enter.

You will notice a warning that no image exists for the “thumbnail.png” file. This warning occurs because there is no thumbnail image for your custom Block to display in VOLT’s Site Designer.

Your Sale Banner Block will now be available for use in VOLT’s Site Designer.

For additional information on publishing Blocks, please read about the Element CLI’s publish command over in the Element Platform Documentation.

For help with adding a thumbnail, please refer to the 4-minute YouTube video How to Create a Thumbnail for Your Block | Element Tutorial | VOLT Resource Center or take a look at the documentation for Element CLI’s publish command. 

Releasing the Sale Banner Block to Production

Up to this point, your custom Block has been in development, which is called “Staging” in Element and VOLT’s Site Designer. Staging means that your custom Block is only visible on the preview version of a VOLT Store (when working in VOLT’s Site Designer), but it will not show on public (or live) VOLT Stores.

To make your custom Block available to the public, you can release it with the element release command including the -n “Notes” flag:

element release -n "Release Notes for this Version"

Note that your release notes should be surrounded by quotes. Including release notes is optional when releasing a Block, but release notes are highly recommended.

The element release command will then ask you to confirm (by entering “Y” for yes or “n” for no).

When you confirm, you will release the first public version of the Block, which will immediately cause the Block to appear in all public VOLT stores that installed the Block.

You should mark the release of the public version using Git:

git commit -am "Public Version 1.0"
git tag 1.0

The first release command will release Version 1 of your custom Block. For more information, see the Element CLI’s release command.

For more details on Block versioning, please refer to the article How To Track Block Versions located in the Element Platform Documentation.

Conclusion

Element is a powerful framework for building custom Blocks for the VOLT Store. Being able to use multiple Element Proptypes is one of the key features that provides VOLT with superb developmental flexibility. Built-in color pickers, rich text editors, sliders, dropdown menus, and section headings are just some of the Element Proptypes available for use in your custom Block. 

This tutorial provides a fully-functional sale banner that mixes several Proptypes. The goal of using multiple Proptypes is allowing the user of your custom Block the ability to customize the Block to best fit their VOLT Store. In this case, your end user has the ability to choose font and background colors, change font size with a slider, and alter text alignment with a dropdown menu.

Element allows you to create custom Blocks that change CSS style properties dynamically based on user input, as seen in this Sale Banner tutorial. When used appropriately, mixing Element Proptypes in custom Blocks empowers the end user of the VOLT Store, without ever needing to contact the developer.