Controls
Controls are user input fields that dynamically adjust elements in templates. They allow users to customize templates by changing text, images, and other properties.
Overview
Controls connect user input to template elements, enabling dynamic customization:
- Value Controls: Change the content of elements (text, images)
- Visibility Controls: Show or hide elements based on user selection
- Control Types: Various input types for different use cases
Control Object
interface Control {
id: string; // UUID (must match valueControlId exactly!)
label: string; // Display name
type: ControlType; // Control type
displayOrder: number; // Order in UI
// Control-specific
defaultValue?: string; // Default value
maxCharacters?: number; // Max characters (for text)
options?: string[]; // Options (for select)
aspectRatio?: string; // Aspect ratio (for image)
textTransform?: "uppercase" | "lowercase" | "none";
supportsFormatableText?: boolean; // BBCode formatting?
// Exclusive groups
exclusiveGroupIds?: string[]; // IDs of ExclusiveGroups
optionGroups?: Record<string, string>; // Map options to groups
exclusiveOptions?: Record<string, string[]>; // Options that exclude specific groups
// Image controls
backgroundPreference?: 'transparent'; // Auto-remove image background on upload
// Sub-controls
parentControlId?: string; // Makes this a sub-control of another control
// AI assistance
aiHint?: string; // Hint for AI-assisted value generation
aiGenerated?: boolean; // AI should suggest a value for this control
}
Control Types
| Type | Description | Example |
|---|---|---|
text_input | Single-line text input | "Headline" |
textarea | Multi-line text input | "Description" |
checkbox | Boolean toggle | "Show logo" |
select | Dropdown selection | "Button style" |
number | Numeric input | "Price" |
color | Color picker | "Accent color" |
date | Date picker | "Event date" |
image | Image upload | "Main image" |
image_video | Image or video upload | "Background" |
layer_group_select | Selects an active layer group (design variation) | "Style variant" |
Text Input
Single-line text input for short text like headlines or labels:
{
"id": "headline-control",
"label": "Headline",
"type": "text_input",
"defaultValue": "Welcome",
"maxCharacters": 50,
"textTransform": "uppercase"
}
Textarea
Multi-line text input for longer content:
{
"id": "description-control",
"label": "Description",
"type": "textarea",
"defaultValue": "Enter your description here",
"maxCharacters": 500
}
Checkbox
Boolean toggle for showing/hiding elements:
{
"id": "show-logo-control",
"label": "Show logo",
"type": "checkbox",
"defaultValue": "true"
}
Select
Dropdown selection with predefined options:
{
"id": "button-style-control",
"label": "Button Style",
"type": "select",
"options": ["Primary", "Secondary", "Outline"],
"defaultValue": "Primary"
}
Image
Image upload control:
{
"id": "product-image-control",
"label": "Product Image",
"type": "image",
"aspectRatio": "16:9"
}
Image/Video
Control that accepts either image or video:
{
"id": "background-control",
"label": "Background",
"type": "image_video",
"aspectRatio": "1:1"
}
Image and image_video controls support an optional backgroundPreference property. When set to
"transparent", uploaded images are automatically cut out (background removal):
{
"id": "product-control",
"label": "Product",
"type": "image",
"backgroundPreference": "transparent"
}
Layer Group Select
Selects which layer group (design variation) is currently active. Layer groups let templates define mutually exclusive visual variants (e.g. "Dark", "Light", "Seasonal"):
{
"id": "variant-control",
"label": "Design Variant",
"type": "layer_group_select"
}
Element-Control Connection
Value Control
Value controls change the content of elements. The control ID must match the element's valueControlId exactly:
{
"control": {
"id": "headline-control-id",
"label": "Headline",
"type": "textarea"
},
"element": {
"type": "text",
"valueControlId": "headline-control-id" // ← Must match exactly!
}
}
How it works:
- When the user changes the control value, the element's content updates automatically
- For text elements, the
textproperty is updated - For image elements, the
contentproperty is updated
Visibility Control
Visibility controls show or hide elements based on user selection:
{
"control": {
"id": "logo-visibility-id",
"label": "Show logo",
"type": "checkbox",
"defaultValue": "true"
},
"element": {
"type": "image",
"visibilityControlId": "logo-visibility-id",
"visibilityControlValue": true // Visible when control = true
}
}
How it works:
- When
visibilityControlValuematches the control's value, the element is visible - When it doesn't match, the element is hidden
- Useful for optional elements like logos, badges, or decorative items
Control Properties
Display Order
Controls the order in which controls appear in the UI:
{
"displayOrder": 0 // Lower numbers appear first
}
Default Value
Sets the initial value when the template is loaded:
{
"defaultValue": "Welcome to heycreo"
}
Max Characters
Limits the maximum number of characters for text controls:
{
"maxCharacters": 100
}
Text Transform
Automatically transforms text case:
{
"textTransform": "uppercase" // Options: "uppercase", "lowercase", "capitalize", "none"
}
Formatable Text
Enables BBCode formatting for text controls:
{
"supportsFormatableText": true
}
This allows users to use formatting like [b]bold[/b] or [i]italic[/i] in their text.
Exclusive Controls
Exclusive controls prevent conflicting options from being selected simultaneously. This is useful when certain combinations don't make sense together (e.g., two elements can't both be positioned at the top).
How It Works
There are two mechanisms for exclusive controls:
- Group-based exclusivity (bidirectional): Controls in the same group exclude each other
- Option-based exclusivity (unidirectional): Specific options exclude specific groups
Exclusive Groups
First, define exclusive groups in the template:
{
"exclusiveControlGroups": [
{
"id": "position-top",
"name": "Position Top",
"description": "Elements positioned at the top"
},
{
"id": "position-bottom",
"name": "Position Bottom",
"description": "Elements positioned at the bottom"
}
]
}
Group-Based Exclusivity
Controls can belong to exclusive groups. When two controls have options from the same group, they exclude each other.
Example:
- Control A: "Text Position" with options "Top" (group: "position-top") and "Bottom" (group: "position-bottom")
- Control B: "Badge Position" with options "Top" (group: "position-top") and "Bottom" (group: "position-bottom")
If Control A is set to "Top", Control B cannot be "Top" (must be "Bottom" or another compatible option).
{
"id": "text-position-control",
"label": "Text Position",
"type": "select",
"options": ["Top", "Bottom", "Middle"],
"exclusiveGroupIds": ["position-top", "position-bottom"],
"optionGroups": {
"Top": "position-top",
"Bottom": "position-bottom"
// "Middle" has no group - it's neutral
}
}
Option-Based Exclusivity
Specific options can exclude entire groups, even if the control doesn't belong to those groups.
Example:
- Control A has option "Special Mode" that excludes group "position-bottom"
- When "Special Mode" is selected, any control with options in "position-bottom" is automatically changed
{
"id": "mode-control",
"label": "Display Mode",
"type": "select",
"options": ["Normal", "Special Mode"],
"exclusiveOptions": {
"Special Mode": ["position-bottom"] // This option excludes the "position-bottom" group
}
}
Practical Example
Scenario: Prevent text and badge from both being at the top or both at the bottom.
{
"exclusiveControlGroups": [
{ "id": "content-top", "name": "Content Top" },
{ "id": "content-bottom", "name": "Content Bottom" }
],
"controls": [
{
"id": "text-variant-control",
"label": "Text Position",
"type": "select",
"options": ["Text Top", "Text Middle", "Text Bottom"],
"exclusiveGroupIds": ["content-top", "content-bottom"],
"optionGroups": {
"Text Top": "content-top",
"Text Bottom": "content-bottom"
// "Text Middle" is neutral
}
},
{
"id": "badge-variant-control",
"label": "Badge Position",
"type": "select",
"options": ["Badge Top", "Badge Bottom"],
"exclusiveGroupIds": ["content-top", "content-bottom"],
"optionGroups": {
"Badge Top": "content-top",
"Badge Bottom": "content-bottom"
}
}
]
}
Result:
- If "Text Top" is selected, "Badge Top" is automatically changed to "Badge Bottom"
- If "Badge Top" is selected, "Text Top" is automatically changed to "Text Middle" or "Text Bottom"
- "Text Middle" can be combined with any badge position (it's neutral)
Best Practices
- Use descriptive labels: Make it clear what each control does
- Set sensible defaults: Provide good default values for better UX
- Order logically: Use
displayOrderto organize controls in a logical flow - Match IDs exactly: Control IDs must match element control IDs exactly
- Use visibility controls: Hide optional elements by default, show them with checkboxes
- Use exclusive controls: Prevent conflicting combinations (e.g., two elements can't both be at the top)
- Define groups clearly: Use meaningful group names and descriptions
- Map all options: When using
exclusiveGroupIds, map all options inoptionGroups
See also
- Template Structure - Template format overview
- Layout Engine - Container layout system