Properties
Learn how to define and validate properties in your template.
Properties allow you to pass JavaScript values into components. Think of them as custom attributes that are accessible on a component.
To declare props, use the Component.defineProps
function. Store the value in an exported props
constant variable. For simple props, where you don’t want to validate the values, pass in an array of prop names.
<script>
export const props = Component.defineProps(['prop-1', 'prop-2', 'prop-3'])
</script>
Props must start with an alphanumeric character. They should also include a type (see below).
You must set a type
to allow team members to modify the property in the component's properties menu. If your component has no type set, we default it to type text.
A string input used to define a CSS color, image, or gradient for the background of a component. The output is a a single CSS background
string. If opacity is less than 100%, then the a value of rgba
is used instead, like rgba(255, 0, 0, 0.5)
.
background: {
label: 'Background',
section: 'Styles',
schema: Component.props.string().optional(),
type: 'background',
}
Note, there are some CSS properties we do not support for backgrounds:
background-attachment
background-clip
repeating-linear-gradient
andrepeating-radial-gradient
, though you can achieve similar results with Repeat (background-repeat
) in layout properties
A string input used to define pixel values on four sides of a box. The output is between one and four values in pixels as a single string. For instance, it could be any of these: 10px
or 10px 20px
or 10px 20px 5px
or 10px 20px 5px 15px
. Commonly used for padding
, margin
, and border-width
.
The collapsedInput
property defines the starting point of the box:
global
gives one input that applies to all sides of the box.axis
gives two inputs - one for top/bottom value and one for left/right values.
In the visual editor, you'll see the option to select global styles for spacing too.
padding: {
label: 'Padding',
section: 'Layout',
schema: Component.props.string().optional().default('10px'),
type: 'box',
collapsedInput: 'axis',
}
A string input that's the same as a text
input; however, the styling of type code
is monospace.
A string input used to define a CSS color. The output is a six digit hex code. If opacity is less than 100%, then the a value of rgba
is used instead, like rgba(255, 0, 0, 0.5)
.
In the visual editor, you'll see the option to select global styles for colors too.
color: {
label: 'Text color',
section: 'Text styles',
schema: Component.props.string().optional(),
type: 'color',
}
A string input to define a font-family.
In the visual editor, you'll see the option to select global styles for fonts too.
'font-family': {
label: 'Font family',
section: 'Styles',
schema: Component.props.string().optional(),
type: 'font-family',
}'
A property with type hidden
will not appear in the properties menu of the visual editor. However, you can still set the property from the code editor. This can be helpful if you want to limit access to advanced features to more technical users, if you want to keep new features hidden while you're testing them, or if you want to support deprecated features behind-the-scenes.
A string input for a media asset such as an image or video. This is commonly used for the src
input on an image component.
accept
is an optional property that lets you define what file types, like image/png
or image/jpeg
, are allowed. You can also specify image/*
or video/*
to allow any image or video format respectively.
Use placeholder
to inform team members what to enter into the component in the visual editor. The placeholder text is never included in the output email code.
src: {
label: 'Source',
schema: Component.props.string(),
type: 'media',
accept: 'image/*',
placeholder: 'Paste the image url here...',
}
A number input. On the visual editor, you'll see +/- buttons to increase or decrease the value.
Consider whether you want to set these optional properties, too:
min
for a minimum number valuemax
for a maximum number valuestep
to define the increment by which a team member can increase/decrease the value with the +/- buttons
'font-size': {
label: 'Size',
section: 'Text styles',
schema: Component.props.number().optional(),
type: 'number',
min: '1',
max: '100',
}
A string input for setting rounded corners. Similar to the box
input, the output is between one and four values in pixels as a single string. For instance, it could be any of these: 10px
or 10px 20px
or 10px 20px 5px
or 10px 20px 5px 15px
.
In the visual editor, you'll see the option to select global styles for radii too.
'border-radius': {
label: 'Radius',
section: 'Styles',
schema: Component.props.number().optional(),
type: 'radius',
}
An enum or string input that displays a dropdown list of options to select from.
Include options
to define the dropdown list. Each item can include:
label
for the display name in the dropdown listvalue
for what the dropdown item should mean
'font-weight': {
section: 'Text Styles',
label: 'Weight',
schema: Component.props.string().optional(),
type: 'select',
options: [
{ label: 'Light', value: '300' },
{ label: 'Normal', value: '400' },
{ label: 'Bold', value: '700' },
],
}
A string input for a CSS box-shadow. The input allows you to set multiple shadows, but will output a single string.
'box-shadow': {
section: 'Styles',
label: 'Shadow',
schema: Component.props.string().optional(),
type: 'shadow',
}
A string input to define a size. Commonly used as width
and occasionally height
.
units
is an array of the allowed units you can select and include in the output:
auto
will output the keyword ‘auto’. The browser calculates the width.px
will add ‘px’ to the number in the output value.percentage
will add ‘%’ to the number in the output value.
'width': {
section: 'Layout',
label: 'Width',
schema: Component.props.string().optional(),
type: 'size',
units: ['auto', 'px'],
}
A number input, but controlled with a slider.
You can optionally include min
as a minimum number value or max
as an optional maximum number value.
An optional step value to define the increment someone can increase/decrease the value by with the +/- buttons in the visual editor.
'letter-spacing': {
label: 'Letter spacing',
section: 'Text styles',
schema: Component.props.number().optional(),
type: 'slider',
min: 0,
max: 1,
step: 0.1,
}
A boolean input. This is used for a simple true/false statement. You could use this in a footer component to choose if you include social icons, for example.
'social': {
label: 'Include social',
section: 'Options',
schema: Component.props.boolean().optional(),
type: 'switch',
}
A string input for setting text. If your component has no type set, we default it to type text
.
Use placeholder
to inform team members what to enter into the component in the visual editor. The placeholder text is never included in the output email code.
'alt': {
label: 'Alt text',
schema: Component.props.string().optional(),
type: 'text',
placeholder: 'Add image description...'
}
An enum input that will display a toggle in the properties menu of the visual editor.
Use the property options
to set an array of toggles:
label
defines the display name for the toggle.value
defines how the code handles the toggle.icon
if included, replaces thelabel
. You can use Google material symbols and icons.
'text-align': {
section: 'Text Style',
label: 'Text Align',
schema: Component.props.enum(['left', 'center', 'right']).optional(),
type: 'toggle',
options: [
{ label: 'Left', value: 'left', icon: 'format_align_left' },
{ label: 'Center', value: 'center', icon: 'format_align_center' },
{ label: 'Right', value: 'right', icon: 'format_align_right' },
],
}
A string input for setting a url.
Use placeholder
to inform team members what to enter into the component in the visual editor. The placeholder text is never included in the output email code.
'href': {
label: 'Link',
schema: Component.props.string().optional(),
type: 'url',
placeholder: 'Add url of link destination...'
}
After you define your properties, you'll create another object to help build the component and pass styles to your message. Here we'll call it the styleObject
, but you can name this anything you like. Then, when you add a style attribute to your template, we will automatically pass this Javascript object to output your styles.
const styleObject = {
color: props.color,
'font-size': props['font-size'] + 'px',
'text-align': props['text-align'],
'line-height': '150%',
};
The names on the left are the CSS attributes you want to include, and on the right are the values. If a property is not set, it will have a value of undefined
and will not be included in the output code. You can also include hard-coded styles which aren’t included in the props, like line-height
in the example above.
Go to Styling to finish defining your properties.
Consider the data your props should accept. Usually, you’ll want to specify what data type a prop accepts. For example, if you create a prop called name
, it should probably accept a string. If you take in a prop called age
, it should probably take a number. But what happens when there's no value? Do you throw an error? Do you supply a default value?
Instead of simply declaring, “we take a prop called name
and age
," you can explicitly define validation and default values by passing in an object.
We can use the Component.props
variable to define details around what each prop does. View the zod documentation for all the different validations you can apply.
export const props = Component.defineProps({
'prop-1': Component.props.string().default("default value"),
'prop-2': Component.props.boolean(),
'prop-3': Component.props.string().array().optional(),
'variant': {
schema: Component.props.string(),
label: 'Variant',
}
})
Each key is the name of a property like prop-1
. Each value is either a PropType
or ExtendedPropType
.
PropType
is an alias ofZodType
from the zod validation library, which is what powers the validation underneath the hood.ExtendedPropType
is an object that accepts aPropType
in theschema
key, as well as any other, set keys. Examples that may be set arelabel
,description
,inputDisplay
, andhelpText
when generating a UI for editing a component instance.
type ExtendedPropType = {
schema: PropType,
[key:string]?: any
}
To pass in props, simply add attributes. By default, the value is treated as a string.
<my-component prop-1="string value here" />
To pass in a JavaScript value, use the #set:
directive.
<my-component :prop-1="new Date()" />