PropTypes System
PropTypes are reusable groups that power:
- properties panel sections
- defaults
- CSS generation
Registry
Core registry: PropTypeRegistry
Responsibilities:
- register/resolve PropTypes
- generate CSS from stored props
- serialize metadata to frontend
This registry is one of the main reasons Tagixo integrations stay consistent across SDKs.
Contract and base class
- Contract:
PropTypeContract - Recommended base:
Core\PropTypes\AbstractPropType
Key methods
key()label()tab()schema()hasCss()toCss()/toCssWithSelectors()defaults()features()vueComponent()
Schema-driven PropTypes
Prefer schema-driven definitions whenever possible.
Benefits:
- less frontend custom code
- predictable defaults
- easier maintenance
Example
use Ccast\Tagixo\Core\PropTypes\AbstractPropType;
use Ccast\Tagixo\Core\Props\NumberProp;
use Ccast\Tagixo\Core\Props\ToggleProp;
class BlurPropType extends AbstractPropType
{
public function key(): string { return 'blur'; }
public function label(): string { return __('Blur'); }
public function tab(): string { return 'design'; }
public function hasCss(): bool { return true; }
public function schema(): array
{
return [
ToggleProp::make('enabled')->default(false),
NumberProp::make('amount')->min(0)->max(30)->default(0),
];
}
public function toCss(array $values): string
{
if (!($values['enabled'] ?? false)) {
return '';
}
return 'filter: blur(' . (int) ($values['amount'] ?? 0) . 'px);';
}
}
How PropType values are stored
PropType values are stored under their own key inside a node's props.
Example:
{
"props": {
"blur": {
"enabled": true,
"amount": 8
}
}
}
That namespacing is what keeps design groups isolated and predictable.
toCss() vs toCssWithSelectors()
Use toCss() when the PropType styles the main node itself.
Use toCssWithSelectors() when the PropType needs nested rules, such as:
- heading rules for
h1,h2,h3 - button label rules
- repeated child selectors
- structural sub-elements
If nested styling is part of the feature, document the selector strategy early so it stays stable.
Registration
app(\Ccast\Tagixo\Core\PropTypeRegistry::class)
->register(new BlurPropType());
Then reference in module definitions through design groups.
Config-based registration is also valid:
'prop_types' => [
App\Tagixo\PropTypes\BlurPropType::class,
]
Built-in catalog
The package ships 18 PropTypes out of the box, grouped by the tab they target in the drawer. You compose them per module via ModuleDefinition::design(...).
Content tab
| PropType | Key | Generates CSS | What it provides |
|---|---|---|---|
LinkPropType |
link |
no | URL, new-tab toggle, title |
AdminPropType |
admin |
no | Editorial label shown in the canvas tree |
LayoutPropType |
layout |
no | Structural layout options (section/row/column) |
Design tab
| PropType | Key | What it provides |
|---|---|---|
TypographyPropType |
typography |
5 nested tabs — text, link, ul, ol, quote — each with font family/size/weight/line-height/letter-spacing/transform/align/color. Generates base typography + nested rules for a, ul, ol, blockquote. |
HeadingTypographyPropType |
heading_typography |
Per-heading-level cascade (H1–H6) with override semantics — H1 inherits from base, H2 inherits from H1 if unset, etc. |
SpacingPropType |
spacing |
4-way padding + margin via FourWaysProp (linked or per-side) |
BackgroundPropType |
background |
6 layers — color, gradient, image, video, pattern, shape-mask — all composable per element |
BorderPropType |
border |
Width, style, color, radius (linked or per-corner) |
SizingPropType |
sizing |
Width/height with min/max, aspect-ratio, object-fit |
BoxShadowPropType |
box_shadow |
Multiple shadow layers with x/y/blur/spread/color/inset/opacity |
FilterPropType |
filter |
Brightness, contrast, saturate, blur, hue-rotate, sepia, grayscale, invert |
TransformPropType |
transform |
Translate/rotate/scale/skew on X and Y |
AnimationPropType |
animation |
Entry animations with stagger + scroll-triggered playback |
SectionDividerPropType |
section_divider |
SVG divider (top and bottom) with shape preset, color, height, flip |
Advanced tab
| PropType | Key | What it provides |
|---|---|---|
CssSelectorsPropType |
css_selectors |
Custom CSS id and class on the wrapper |
CustomCssPropType |
custom_css |
Raw CSS with .this-element placeholder for the current node |
VisibilityPropType |
visibility |
Hide per breakpoint + overflow control per axis |
DisplayPropType |
display |
Position (static/relative/absolute), top/right/bottom/left, z-index |
A module enables whichever set fits its semantics:
->design('typography', 'spacing', 'border', 'box_shadow', 'animation')
Unspecified PropTypes simply don't appear in the drawer for that module.
When to create a PropType instead of a Prop
Create a custom Prop when you need a single field.
Create a custom PropType when you need:
- a reusable group of fields
- generated CSS
- a panel section that appears across many modules
- stable defaults and reset behavior
Common pitfalls
- duplicate keys
- invalid CSS units
- missing defaults
- schema/data shape mismatch
- mixing business data with design-layer configuration
- creating a custom Vue-only PropType for a case that a schema-driven PropType could handle