skills/hyva-cms-custom-field/SKILL.md
Create custom field types and field handlers for Hyvä CMS components. Use when the user mentions Hyvä, Hyva, or CMS together with custom field, custom input, or modal selector (e.g. hyva custom field, custom cms field, hyva modal selector, custom hyva input, custom cms input). Do not use for generic form or UI work outside Hyvä CMS.
npx skillsauth add hyva-themes/hyva-ai-tools hyva-cms-custom-fieldInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill guides the creation of custom field types and field handlers for Hyvä CMS components. Custom field types extend the built-in field types (text, textarea, select, etc.) with specialized input controls for the CMS editor interface.
Two types of custom fields:
Command execution: For commands that need to run inside the development environment (e.g., bin/magento), use the hyva-exec-shell-cmd skill to detect the environment and determine the appropriate command wrapper.
If not already specified in the prompt, determine where to create the custom field type:
Option A: New Module
Use the hyva-create-module skill with:
dependencies: ["Hyva_CmsBase", "Hyva_CmsLiveviewEditor"]composer_require: {"hyva-themes/commerce-module-cms": "^1.0"}Option B: Existing Module
Verify the module has required dependencies:
Hyva_CmsBase and Hyva_CmsLiveviewEditor in etc/module.xmlhyva-themes/commerce-module-cms in composer.jsonAdd missing dependencies if needed.
Gather information about the custom field type:
date_range, product_selector, color_picker)Based on the UI pattern identified in Step 2:
Pattern A: Basic Custom Field Type
For simple inputs with custom HTML5 validation or specialized input controls:
Pattern B: Inline Field Handler
For enhanced controls that remain in the field area:
Pattern C: Modal-Based Field Handler
For complex selection interfaces requiring more space:
See references/handler-patterns.md for detailed implementation patterns and code examples for each type.
Create the field template at view/adminhtml/templates/field-types/[field-type-name].phtml.
Required template elements:
field-container-{uid}_{fieldName}{uid}_{fieldName}validation-messages-{uid}_{fieldName}updateWireField() or updateField() call on value change$magewire->errors$block->getData('value') ?? '' (NOT type casting)Use the appropriate template from assets/templates/:
basic-field.phtml.tpl - Basic custom field typeinline-handler.phtml.tpl - Inline enhanced controlmodal-field.phtml.tpl - Modal handler field templateSee references/template-requirements.md for detailed template requirements and patterns.
For modal-based handlers only, create the handler template at view/adminhtml/templates/handlers/[handler-name]-handler.phtml.
Handler modal structure:
<dialog> element with Alpine.js component and open:flex class (NOT static flex)editor-change event on saveUse assets/templates/modal-handler.phtml.tpl as the starting point.
See references/handler-communication.md for event protocols and data exchange patterns.
Add registration to etc/adminhtml/di.xml:
<type name="Hyva\CmsLiveviewEditor\Model\CustomField">
<arguments>
<argument name="customTypes" xsi:type="array">
<item name="[field_type_name]" xsi:type="string">
[Vendor]_[Module]::field-types/[field-type-name].phtml
</item>
</argument>
</arguments>
</type>
For modal-based handlers only, create or update view/adminhtml/layout/liveview_editor.xml:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="before.body.end">
<block name="[handler_name]_handler"
template="[Vendor]_[Module]::handlers/[handler-name]-handler.phtml"/>
</referenceContainer>
</body>
</page>
Note: Inline handlers do NOT require layout XML registration.
Provide an example of using the custom field type in components.json:
{
"my_component": {
"label": "My Component",
"content": {
"[field_name]": {
"type": "custom_type",
"custom_type": "[field_type_name]",
"label": "Field Label",
"attributes": {
"required": true,
"pattern": ".*"
}
}
}
}
}
Complete reference for custom field type template requirements:
updateWireField vs updateField)Read this file when implementing the field template to ensure proper integration with the CMS editor.
Implementation patterns for all three custom field types:
Each pattern includes:
Read this file when selecting the implementation pattern and writing the template code.
Event protocols and data exchange for field handlers:
Read this file when implementing handler modals to understand the communication protocol.
Reference for Hyvä CMS built-in field handlers:
Each includes:
Read this file when looking for implementation examples or patterns to copy.
Template for basic custom field types with custom validation or input controls.
Placeholders:
{{FIELD_TYPE_NAME}} - Custom field type identifier{{FIELD_INPUTS}} - Input element(s) HTML{{VALIDATION_LOGIC}} - Custom validation JavaScript (optional)Template for inline enhanced controls (searchable dropdown, color picker, etc.).
Placeholders:
{{HANDLER_NAME}} - Alpine.js component name{{HANDLER_LOGIC}} - Alpine.js component implementation{{HANDLER_UI}} - Enhanced control HTMLField template for modal-based handlers (trigger button + hidden input).
Placeholders:
{{EVENT_NAME}} - Custom event name to dispatch{{BUTTON_LABEL}} - Button text{{DISPLAY_VALUE}} - Current selection displayHandler modal template for modal-based selection interfaces.
Placeholders:
{{HANDLER_NAME}} - Alpine.js component name{{MODAL_TITLE}} - Dialog header text{{SELECTION_UI}} - Selection interface HTML{{SAVE_LOGIC}} - Save button logic$filteredAttributes for automatic validationHyva_CmsLiveviewEditor::page/js/ for proven patternsBased on built-in Hyvä CMS handler implementations:
Event Naming Convention: Use toggle-{type}-select pattern
toggle-product-select, toggle-link-select, toggle-category-selecttoggle-product-handler, toggle-link-handlerHandler Function Naming: Use init{Type}Select() pattern
initProductSelect(), initLinkSelect(), initCategorySelect()Field Value Update Methods:
updateWireField (default): Products, Link, Category handlers
updateField (specialized): Image handler, debounced inputs (color, range)
JSON Encoding Pattern: All complex data (arrays, objects) must be JSON-encoded
// Field template
value="<?= $escaper->escapeHtmlAttr(json_encode($fieldValue)) ?>"
// Handler initialization
const data = JSON.parse(fieldValue);
// @change handler
@change="updateWireField(..., JSON.parse($event.target.value))"
wire:ignore for Livewire Compatibility: Searchable select uses wire:ignore wrapper
<div wire:ignore>
<div x-data="initSearchableSelect(...)">
<!-- Alpine component -->
</div>
</div>
Separate Handler Files: Even inline handlers may have separate function files
liveview/field-types/searchable_select.phtmlpage/js/searchable-select-handler.phtmlIcons View Model: Use for UI elements
/** @var Icons $icons */
$icons = $viewModels->require(Icons::class);
<?= /** @noEscape */ $icons->trashHtml('', 22, 22) ?>
FieldTypes View Model: Use for attribute filtering
/** @var FieldTypes $fieldTypes */
$fieldTypes = $viewModels->require(FieldTypes::class);
$filteredAttributes = $fieldTypes->getDefinedFieldAttributes($attributes);
// Or for specific attributes:
$filteredAttributes = $fieldTypes->getAttributesByKeys($attributes, ['required', 'data-required']);
CRITICAL: Layout XML referenceContainer: Handler modals MUST use before.body.end container
<referenceContainer name="before.body.end"><referenceContainer name="content">before.body.end container ensures the handler modal is loaded at the end of the page body, which is required for proper Alpine.js initialization and modal functionalityCRITICAL: Field Value Type Handling: NEVER use type casting for field values, always use null coalescing operator
$fieldValue = $block->getData('value') ?? '';$fieldValue = (string) $block->getData('value');(string) will fail when value is null, causing PHP errors?? '' for string values, ?? [] for array values, or appropriate default for your data typecategory.phtml which use ?? [] patternopen:flex not static flex class<dialog class="... open:flex flex-col"><dialog class="... flex flex-col"> (modal always visible)open: prefix applies styles only when dialog is open (native HTML dialog state)category-handler.phtml which use open:flex flex-col$data = ['default' => 'structure'];
if ($fieldValue) {
if (is_array($fieldValue)) {
$data = $fieldValue; // Already decoded
} elseif (is_string($fieldValue)) {
$decoded = json_decode($fieldValue, true);
if (is_array($decoded)) {
$data = $decoded;
}
}
}
// When outputting to hidden input, ALWAYS ensure it's a JSON string
$fieldValueJson = is_array($fieldValue) ? json_encode($fieldValue) : $fieldValue;
json_decode($fieldValue) without type checking (fails if value is already an array)value attribute without JSON-encoding firstdocumentation
Apply Hyva UI template-based components to a Hyvä theme. This skill should be used when the user wants to add, install, or apply a Hyva UI component (such as header, footer, gallery, menu, minicart, etc.) to their Hyvä theme. It lists available non-CMS components and their variants, displays component README instructions, and copies component files to the theme directory.
data-ai
List all Hyvä theme paths in a Magento 2 project. This skill should be used when the user wants to find Hyvä themes, list available themes, discover theme paths, or when other skills need to locate Hyvä themes. Trigger phrases include "list hyva themes", "find themes", "show themes", "available themes", "theme paths".
development
Generate responsive image code for Hyvä Theme templates using the Media view model. This skill should be used when the user wants to render images in a Hyvä template, create responsive picture elements, add hero images, product images, or any image that needs responsive breakpoints. Trigger phrases include "render image", "add image to template", "responsive image", "picture element", "hero image", "responsive banner", "image for mobile and desktop", or "banner image".
development
Write Playwright tests for Hyvä themes with Alpine.js components. This skill should be used when writing e2e tests, creating page objects, or debugging selector issues in Playwright tests for Hyvä Magento storefronts. Trigger phrases include "write playwright test", "playwright alpine", "test hyva page", "e2e test", "playwright selector".