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.

Define props

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).

Options for type

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.

background

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 and repeating-radial-gradient, though you can achieve similar results with Repeat (background-repeat) in layout properties

box

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',
}

code

A string input that's the same as a text input; however, the styling of type code is monospace.

color

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',
}

font-family

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',
}'

hidden

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.

media

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...',
}

number

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 value
  • max for a maximum number value
  • step 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',
}

radius

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',
}

select

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 list
  • value 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' },
  ],
}

shadow

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',
}

size

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'],
}

slider

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.

step

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,
}

switch

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',
}

text

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...'
}

toggle

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 the label. 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' },
  ],
}

url

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...'
}

Create a style object

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.

Validate props

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 of ZodType from the zod validation library, which is what powers the validation underneath the hood.
  • ExtendedPropType is an object that accepts a PropType in the schema key, as well as any other, set keys. Examples that may be set are label, description, inputDisplay, and helpText when generating a UI for editing a component instance.
type ExtendedPropType = {
	schema: PropType,
	[key:string]?: any
}

Insert props

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()" />