Tagixo Docs

Developer Documentation for Laravel, SDK integrations, and extensibility

Extending Tagixo

Props System

Define schema-level editable fields with reusable prop building blocks and widget metadata.

Props System

Props are schema-level building blocks used in module definitions.

What a Prop is

A Prop defines a single editable field in the builder schema.

Examples:

  • a text input for a title
  • a toggle for enabling a feature
  • a color picker
  • a size field with units
  • a repeater of nested items

Core base class:

  • Ccast\Tagixo\Core\Props\AbstractProp

Key responsibilities:

  • property key and label
  • widget type and config
  • default values
  • UI metadata serialization for the drawer

Where Props are used

Props are usually declared inside ModuleDefinition:

ModuleDefinition::make()->content(
    TextProp::make('title')->default('Hero title'),
    TextareaProp::make('subtitle'),
)

They can also appear inside PropType schemas.

Common fluent methods

  • setLabel(...)
  • default(...)
  • helpText(...)
  • variablePicker(...)
  • sub(...)
  • showWhen(field, value, operator)
  • withConfig([...])

Common built-in Props

  • TextProp
  • TextareaProp
  • EditorProp
  • NumberProp
  • SelectProp
  • ToggleProp
  • ColorProp
  • MediaProp
  • IconProp
  • SliderProp
  • SizeProp
  • RepeaterProp
  • ModelSelectProp

There are also specialized props for more complex controls such as four-way spacing, tabs, or shadow presets.

Example: simple content schema

use Ccast\Tagixo\Core\Props\TextProp;
use Ccast\Tagixo\Core\Props\TextareaProp;
use Ccast\Tagixo\Core\Props\ToggleProp;

ModuleDefinition::make()->content(
    TextProp::make('title')
        ->setLabel('Title')
        ->default('Welcome'),

    TextareaProp::make('description')
        ->setLabel('Description'),

    ToggleProp::make('show_button')
        ->setLabel('Show button')
        ->default(true)
);

Conditional editor UX

Use showWhen() to make the properties panel easier to use:

TextProp::make('button_text')
    ->showWhen('show_button', true);

This is a UX feature. It is not a substitute for server-side validation in your save pipeline.

Repeater strategy

Use RepeaterProp for item-based structures (for example tabs/slides/plans).

Ensure repeated item keys are stable and version-safe.

Example:

RepeaterProp::make('items')
    ->fields([
        TextProp::make('label'),
        TextProp::make('url'),
    ]);

Repeaters are the right choice when you need structured collections, not free-form JSON blobs.

Pricing table pattern

The built-in pricing table module is a good reference for repeaters with optional commercial fields.

Each plan is stored as a repeater item with stable keys such as:

  • name
  • price
  • period
  • originalPrice optional
  • discountExpiresText optional
  • badge optional
  • features
  • buttonText
  • buttonUrl
  • isFeatured

That pattern is useful when:

  • a plan may or may not be discounted
  • a promo window must be shown without changing the base price
  • the same module should support evergreen pricing and launch offers

Example:

RepeaterProp::make('plans')
    ->fields([
        TextProp::make('name')->default('Annual'),
        TextProp::make('price')->default('199'),
        TextProp::make('period')->default('/year'),
        TextProp::make('originalPrice')->default('349'),
        TextProp::make('discountExpiresText')->default('Launch price until May 31, 2026'),
        TextProp::make('badge')->default('Most popular'),
        TextareaProp::make('features'),
        TextProp::make('buttonText')->default('Buy now'),
        TextProp::make('buttonUrl'),
        ToggleProp::make('isFeatured')->default(false),
    ]);

Keep promo fields optional. Do not overload price with mixed content such as "199 instead of 349" because it makes rendering and styling unstable.

Variable picker integration

variablePicker() allows a field to reference global variables instead of fixed values.

Use it for:

  • theme colors
  • shared spacing tokens
  • reusable links
  • managed text fragments

This keeps design systems consistent across templates and pages.

Custom prop example

class JsonEditorProp extends AbstractProp
{
    public function widget(): string
    {
        return 'json_editor';
    }

    public function widgetConfig(): array
    {
        return [
            ...$this->baseConfig(),
            'mode' => 'tree',
        ];
    }
}

Frontend requirement for custom widgets

If you add a custom widget key, the frontend drawer renderer must know how to render it.

If no renderer exists, the field appears broken or is ignored.

That means a custom Prop can require both:

  • backend schema work
  • frontend field renderer support

Design guidance

  • Keep Props small and composable.
  • Avoid business logic in prop definitions.
  • Use showWhen for UX, not server validation.
  • Prefer a reusable Prop factory over copy-pasting field definitions across modules.
  • Use repeaters for structured data rather than inventing untyped array payloads.