Create a component from scratch
BetaThis feature is new and we're actively working to improve it. UpdatedIn Design Studio, organize your code into reusable blocks with custom components.
New to custom components?
If you’re new to custom components, check out how to build them using visual blocks or our GPT. This may save you some time!
Understand the structure
There are two required tags when setting up a component: <script> and <template>. The <script> tag is where you define properties for styles, slots for modifiable content, and other JavaScript logic. The <template> tag is where you create your content and reference variables and slots.
When you create a component from scratch, we provide the following code:
<!--
Insert this component in your email with the following code:
<example-component></example-component>
-->
<script>
export const config = {
label: "example component",
presets: [
{
label: "example component",
content: `<example-component></example-component>`
}
]
}
// export const slots = Component.defineSlots({
// default: {
// schema: Component.slots.text(),
// },
// });
// export const props = Component.defineProps({
// });
</script>
<template>
<p>Content goes here</p>
</template>
In the <script> tag, use the config variable to define how the component is referenced in the visual and code editors - there are a number of names and labels to keep in mind.
We also include code that will help you get started defining slots for modifiable, placeholder content and properties for styles.
Learn more about optional top-level elements—<style>, <title>, <link>, <meta>.
Presets
Presets define the name of the component and what gets inserted into the editor.
presets.label is the name you’ll see in the insert menu.
When you drag a custom component into your message, we insert the value of presets.content into the code editor. With this template, we’d insert <example-component></example-component> into the code and render the content of the <template> in the final source code.
Hide from the insert menu
To hide a custom component from the Insert menu, delete the presets array of the <script> tag.
export const config = {
"label": "My paragraph",
presets: [
{
label: "My paragraph",
content: `<my-paragraph></my-paragraph>`
}
]
}You’ll still be able to add the custom component to the code editor and include the component as content in other component files.
Removing this label will not change any existing reference in your messages.
Names and labels
In a component file, you’ll find a number of names and labels:
- Filename - visible in the Design Studio dashboard, what we draw from to label your component when you first create the file.
- Component Name - located at the top of the component file.
- To define parent and child relationships, you’ll reference the component name.
- Defines the name of the component tag visible in the code editor. This must match the component tag name referenced in
presets.content. - The name can’t be an HTML element, like
h1, or start with our standard component naming convention:x-.
config.label- appears in the Layers menu of the visual editor, also appears when you hover over the component on the canvas.presets.label- appears in the Insert menu of the visual editor.
How changes to a component file cascade to emails
If you update a component file, those changes will cascade to your Design Studio messages. Whether you update the <script> or <template> of your component, changes cascade to references.
One caveat is the presets array. If you change presets.content, you must pull in the component again or directly modify the email to see the latest changes. Otherwise, any other change to definitions in your <script> or content in your <template> will immediately be reflected in your referenced messages.
Publish changes to your emails after you update components
Updates first cascade to the message in Design Studio. Then you must click Publish to push those changes to connected campaigns, broadcasts, or transactional messages.
Code your component
When you create a custom component, you can decide how much control your teammates have over the content and styling in the visual editor.
Add content
By default, our out-of-the-box component code helps you build an uneditable block of reusable content—this might make sense for headers and footers to ensure consistency across emails.
You’ll add content—standard components, custom components, and/or HTML elements—to the <template> tag.
To create modifiable, placeholder content, you’ll add slots. You can create slots that are text-based or drop-zones for other components.
Add styles
By default, our out-of-the-box component code helps you build a block where styles are locked—this might make sense for headers and footers to ensure brand consistency across emails.
You can also code components so that after your teammates drag a custom component onto the visual editor, they can choose between specific styles you laid out in the code. To do this, define properties in the <script> of your custom component.
Otherwise, you can hard-code inline styles in the <template> tag.
Create responsive styles
You can use @media queries to define screenbreaks in a custom component or the media attribute.
For Thunderbird and other email clients that don’t support @media queries, use the media attribute within an isolated <style> tag.
Reference global styles
You can use your global styles to define properties so your team stays on brand.
You’ll reference them using globalStyles.<global-style-type>.<global-style-variablename-variableid>. This might look like globalStyles.colors.pink_khyqtq8v5rcs.
Use autocomplete to reference the global style
Note the variable id needed at the end of the global style reference. You can find this by using autocomplete in the component editor.
You can reference global styles in both properties and CSS to customize your components:
- As an inline style—best for quick, one-off styles:
<div :style="`background: ${globalStyles.colors.pink_khyqtq8v5rcs};`"> - As a CSS class (make sure you use the
set()function) while creating a stylesheet - As a property value in a style object
- As a variant for select and toggle properties—these property types let people in the visual editor choose the correct variant
Define relationships between components
You can define parent/child relationships between components such that team members using the visual editor can only drag/drop specific components into each other.
Parents
For instance, maybe you have a component social-icons that team members should only be able to insert into your footer component. In this case, the config code of the social-icons component should include allowedParents:
<script>
export const config = {
"label": "social-icons",
allowedParents: ['footer'],
presets: [
{
label: "social-icons",
content: `<social-icons></social-icons>`
}
]
};
</script>Children
If you want to specify that a component can only have certain child components, take advantage of slots, which let you create modifiable, placeholder content.
The slots code would include this, where you’d replace social-icons with any Component Name.
<script>
export const slots = Component.defineSlots({
default: {
schema: Component.slots.children(['social-icons']),
},
});
</script>
Check out validation of slots for more info on child components.
Troubleshooting issues
If your component throws an error or fails to load after adding it to a Design Studio email, go to your component file and review your code. This often means you’ll need to resolve an issue with the config, props or slots definitions.
- Make sure you define your properties/variables and slots using:
Component.notation in the<script>- Only the schema we support
- Make sure you define any custom properties in the
<script>. - Ensure there’s both a
<script>and<template>tag in your component file. - Make sure all code is within our supported top-level elements.
- Make sure the component name at the top of your component file matches the tag name used in
presets.contentin your<script>. For example, if your component name is “Custom footer”, thenpresets.contentmust include<custom-footer></custom-footer>.
