Skip to content
This plugin is new and currently in beta. For the stable version, please use the previous version of the plugin.

UI Element

Overview

UI Elements are the foundational building blocks for creating custom user interface components in the Stripo Email Editor. They enable you to extend the editor's interface with custom inputs, pickers, dropdowns, and specialized interactive components that go beyond standard HTML form elements. UI Elements can be embedded within controls and settings panels to provide rich, interactive functionality tailored to your specific needs.

Purpose and Core Concepts

What is a UI Element?

A UI Element in the Stripo Extensions SDK is a reusable UI component that:

  • Defines custom interactive interface elements (color pickers, dropdowns, custom inputs, etc.)
  • Can be embedded within controls
  • Maintains state and responds to external attribute changes
  • Integrates seamlessly with the editor's control system
  • Provides lifecycle hooks for initialization and cleanup
  • Communicates value changes to parent controls

Built-in vs Custom UI Elements

The SDK provides a rich set of built-in UI elements for common use cases, but you can also create custom UI elements when you need specialized functionality:

Built-in UI Elements - Ready to use without additional configuration:

  • Buttons, checkboxes, radio buttons
  • Text inputs, textareas, date pickers
  • Color pickers, font family selectors
  • Dropdown selects, switchers, counters
  • Labels, messages, icons
  • And more (see the Built-in UI Elements table)

Custom UI Elements - When built-in elements don't meet your needs:

  • Brand-specific color palette pickers
  • Advanced file uploaders with preview
  • Custom merge tag selectors
  • Specialized input validators
  • Integration with external services
  • Complex multi-field components

Creating Custom UI Elements

To create a custom UI element, follow these steps:

  1. Create a class that extends the UIElement class
  2. Register your UI element with the ExtensionBuilder

UI element configuration requires:

  • Unique element identifier (getId())
    • This identifier is used as a tag name in control templates
    • It must be unique across all UI elements in the extension
  • HTML template structure (getTemplate())
  • Render logic (onRender())
    • Register all event listeners and other UI element-specific logic here
  • Cleanup logic (onDestroy())
    • Remove all event listeners and other UI element-specific logic here
  • Getter and setter methods to maintain UI element state from parent control
  • (Optional) Attribute update handler (onAttributeUpdated())
    • This method is called when an attribute of the UI element is updated from the parent control

Once registered, you can use your custom UI element in control templates by referencing its ID:

javascript
import {UIElement, ExtensionBuilder} from '@stripoinc/ui-editor-extensions';

class BrandColorPickerUIElement extends UIElement {
    getId() {
        return 'brand-color-picker';
    }

    getTemplate() {
        return `
            <div class="brand-color-picker-palette" style="display: flex; gap: 16px;">
                <button
                    data-value="#ff6f61" 
                    style="width: 30px; height: 30px; border-radius: 50%; border: none; background-color: #ff6f61; cursor: pointer;"
                    title="Coral"></button>
                <button
                    data-value="#43e97b" 
                    style="width: 30px; height: 30px; border-radius: 50%; border: none; background-color: #43e97b; cursor: pointer;"
                    title="Mint"></button>
                <button 
                    data-value="#5f72bd"
                    style="width: 30px; height: 30px; border-radius: 50%; border: none; background-color: #5f72bd; cursor: pointer;"
                    title="Violet"></button>
            </div>
        `;
    }

    onRender(container) {
        this.palette = container.querySelector('.brand-color-picker-palette');
        this.palette.addEventListener('click', this.paletteClickHandler.bind(this));
    }

    onDestroy() {
        this.palette.removeEventListener('click', this.paletteClickHandler.bind(this));
    }

    paletteClickHandler(e) {
        const selectedColor = e.target.getAttribute('data-value');
        
        // Trigger value change to parent control.
        // The 'setValue' method will be called automatically.
        this.api.triggerValueChange(selectedColor);
    }

    getValue() {
        return this.palette.querySelector('button.selected')?.getAttribute('data-value');
    }

    setValue(_value) {
        this.palette.querySelector('button.selected')?.classList.remove('selected');
        this.palette.querySelector(`button[data-value="${_value}"]`)?.classList.add('selected');
    }

    onAttributeUpdated(_name, _value) {
        // Handle attribute updates from parent control
        console.log(`Attribute updated: ${_name} = `, _value);
    }
}

class BrandControl extends Control {
    getId() {
        return 'brand-control';
    }

    getTemplate() {
        return `<brand-color-picker name="brandColorPicker"></brand-color-picker>`;
    }

    onRender() {
        this.api.onValueChanged('brandColorPicker', (newValue, oldValue) => {
            // Handle value changes from 'brandColorPicker' UI element
            console.log('brandColorPicker value changed:', newValue);
        });
    }

    onTemplateNodeUpdated(node) {
        // Update UI to reflect template state
        this.api.updateValues({
            'brandColorPicker': '#43e97b' // Get actual value from node
        });

        // Optionally, set UI element state with attribute values
        this.api.setUIEAttribute('brandColorPicker', 'preferred-color', '#53f97a');
    }
}

export default new ExtensionBuilder()
    .addUiElement(BrandColorPickerUIElement)
    .addControl(BrandControl)
    .build();

Built-in UI Elements

Supported Built-in UI Elements

The following image and table list all built-in UI elements available in the Stripo Extensions SDK:

Tag NameAliasDescriptionCommon Attributes
<ue-button>UIElementType.BUTTONButton element for triggering actionsname, disabled, caption, icon
<ue-check-buttons>UIElementType.CHECK_BUTTONSGroup of checkboxes as buttonsname, disabled, buttons
<ue-checkbox>UIElementType.CHECKBOXCheckbox input for boolean valuesname, disabled, caption
<ue-color>UIElementType.COLORColor picker for selecting colorsname, disabled
<ue-counter>UIElementType.COUNTERNumeric input with increment/decrement buttonsname, disabled, min-value, max-value, step
<ue-datepicker>UIElementType.DATEPICKERDate picker for selecting datesname, disabled, placeholder, min-date
<ue-expandable>UIElementType.EXPANDABLEExpandable/collapsible containername, expanded
<ue-icon>UIElementType.ICONIcon display elementname, img, src, title, width, height, image-class, hint, is-active, visibility, transform
<ue-label>UIElementType.LABELText label with optional hintname, text, hint
<ue-message>UIElementType.MESSAGEMessage box for displaying informationname, type
<ue-radio-buttons>UIElementType.RADIO_BUTTONSRadio button groupname, disabled, buttons
<ue-select>UIElementType.SELECTPICKERDropdown select pickername, disabled, searchable, multi-select, placeholder, items
<ue-switcher>UIElementType.SWITCHERToggle switcher for boolean valuesname, disabled
<ue-text>UIElementType.TEXTSingle-line text inputname, disabled, placeholder
<ue-textarea>UIElementType.TEXTAREAMulti-line text inputname, disabled, resizable, placeholder

Using Built-in UI Elements

All built-in UI elements can be used directly in your control templates without additional registration by referencing their tag names or aliases:

Simple Usage

javascript
class ComprehensiveControl extends Control {
    getId() {
        return 'comprehensive-control';
    }

    getTemplate() {
        return `
            <div class="container two-columns">
                <${UIElementType.LABEL} ${UEAttr.LABEL.text}="<ue-button>"></${UIElementType.LABEL}>
                <${UIElementType.COLOR} ${UEAttr.COLOR.name}="colorPicker"></${UIElementType.COLOR}>
            </div>`;
    }

    onRender() {
        // Listen for 'colorPicker' UI element value changes
        this.api.onValueChanged('colorPicker', (newValue, oldValue) => {
            this.api.getDocumentModifier()
                .modifyHtml(this.node.querySelector(`.custom-message-area`))
                .setStyle('background-color', newValue)
                .apply(new ModificationDescription(`Updated background color to ${newValue}`));
        })
    }

    onTemplateNodeUpdated(node) {
        this.node = node;

        // Set the value for 'colorPicker' UI element
        const element = node.querySelector('.custom-message-area');
        this.api.updateValues({
            'colorPicker': node.querySelector(`.custom-message-area`).getStyle('background-color')
        });
    }
}

Complex Usage

Expandable container

Expandable containers allow you to group multiple UI elements inside a collapsible section, making complex forms more organized and user-friendly. An expandable UI element is composed of three main parts:

  • <ue-expandable> — The main wrapper for the entire collapsible section
  • <ue-expandable-header> — The header area, typically containing the title, placed next to the expand/collapse toggle
  • <ue-expandable-content> — The container for the content that is shown or hidden when expanded or collapsed
javascript
class ExpandableControl extends Control {
    getTemplate() {
        return `
            <div class="container">
                <${UIElementType.EXPANDABLE}>
                    <${UIElementType.EXPANDABLE_HEADER}>
                        <${UIElementType.LABEL} ${UEAttr.LABEL.text}="Click to expand"></${UIElementType.LABEL}>
                    </${UIElementType.EXPANDABLE_HEADER}>
                    <${UIElementType.EXPANDABLE_CONTENT}>
                        <${UIElementType.LABEL} ${UEAttr.LABEL.text}="First content row"></${UIElementType.LABEL}>
                        <${UIElementType.LABEL} ${UEAttr.LABEL.text}="Another row"></${UIElementType.LABEL}>
                    </${UIElementType.EXPANDABLE_CONTENT}>
                </${UIElementType.EXPANDABLE}>
            </div>`;
    }

    // Additional configuration should be here
}

Overriding Built-in UI Elements

The UIElementTagRegistry allows you to replace built-in UI elements with custom implementations throughout your extension. This is particularly useful when you want to:

  • Apply consistent branding to all UI elements
  • Add custom functionality to standard elements
  • Integrate with external services
  • Enforce specific validation or formatting rules

Creating a Tag Registry

To override built-in UI elements:

  1. Create a class that extends UIElementTagRegistry
  2. Implement the registerUiElements() method
  3. Map tags to your custom UI element IDs
  4. Register the registry with ExtensionBuilder
javascript
import {UIElementTagRegistry, UIElementType, ExtensionBuilder} from '@stripoinc/ui-editor-extensions';

class CustomTagRegistry extends UIElementTagRegistry {
    registerUiElements(uiElementsTagsMap) {
        // Override the built-in color picker with custom implementation
        uiElementsTagsMap[UIElementType.COLOR] = 'brand-color-picker';
    }
}

export default new ExtensionBuilder()
    .addUiElement(BrandColorPickerUIElement)
    .withUiElementTagRegistry(CustomTagRegistry)
    .build();

UI Element API

The UI Element API, accessible through this.api, provides method to notify the parent control when the UI element's value changes, ensuring proper synchronization and state management.

For complete API reference, see UIElementApi.