> ## Documentation Index
> Fetch the complete documentation index at: https://flex-fields.bjanczak.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Examples target Filament 5. Verify optional dependencies before configuring integrations.
> Upload transfer completion, permanent storage and record acceptance are separate milestones. Native and Spatie image conversions retain the original.

# Build your own FLEX components

> Compose existing FLEX fields, create matching table and infolist views, or render reusable component families from saved schemas.

**Build the control your application needs from the controls FLEX already provides.**
Combine a Select, Text Input, color picker or other field in your own layout. Keep
its configuration, validation and interactions, without copying its HTML or JavaScript.

Start with a composition in one form. When you need a reusable package, add a
named field, matching display views and the configuration your application uses.

## Watch: build a custom component step by step

Follow a narrated workshop from Filament's field generator to a reusable Composer
package. Build a campaign brief with live channel previews and tracking links,
then add typed configuration, your own CSS and JavaScript, table and infolist
views, translations and AI-readable guidance.

[Build custom Laravel Filament form components with FLEX Fields — step-by-step workshop](https://www.youtube-nocookie.com/embed/m4V_R7YxTP4)

[Watch on YouTube](https://www.youtube.com/watch?v=m4V_R7YxTP4)

**1 hour 4 minutes · English narration · Full HD · 27 YouTube chapters.** The workshop starts in an
existing Laravel application with Filament 5 and FLEX Fields v4 installed.

> **Jump to a workshop chapter**
>
> * [00:00 — Generate a custom Filament field with Artisan](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=0s)
> * [02:04 — Reuse the real FLEX Text Input](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=124s)
> * [02:49 — Configure a single Select field](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=169s)
> * [03:35 — Configure the same Select as a searchable multi-select](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=215s)
> * [04:34 — Position child fields in a Blade layout](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=274s)
> * [05:16 — Add your component's own JavaScript behavior](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=316s)
> * [06:34 — Show missing data and publication readiness](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=394s)
> * [07:08 — Build a copyable campaign brief](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=428s)
> * [08:40 — Clean up listeners and handle async feedback](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=520s)
> * [09:53 — Style your custom component with CSS](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=593s)
> * [13:45 — Build the extension's JavaScript and CSS assets](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=825s)
> * [15:11 — Register dependencies and asset ownership](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=911s)
> * [17:32 — Connect live previews to the shared form state](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1052s)
> * [21:35 — Try the campaign brief builder](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1295s)
> * [22:31 — Add an optional Color Picker per instance](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1351s)
> * [24:14 — Validate the completed form in PHP](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1454s)
> * [25:06 — Generate UTM campaign tracking links](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1506s)
> * [29:56 — Scaffold a reusable component package](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1796s)
> * [31:44 — Define typed configuration and child field options](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=1904s)
> * [36:12 — Form field, native Filament table column and infolist entry](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=2172s)
> * [42:52 — Add review guards and successful-copy notifications](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=2572s)
> * [46:57 — Build a custom settings dialog with asset readiness](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=2817s)
> * [52:13 — Add translations and right-to-left support](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3133s)
> * [55:45 — Protect routes and expose AI-readable component guidance](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3345s)
> * [59:42 — Validate schemas and explicitly migrate stored values](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3582s)
> * [1:02:07 — Verify the complete component example](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3727s)
> * [1:03:07 — Install through Composer and register with Filament](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3787s)

> **[Compose existing fields](https://flex-fields.bjanczak.com/docs/extensions/composition-patterns.md)**
>
> Build a call-to-action control with text, a URL and a Select.

> **[Create a reusable package](https://flex-fields.bjanczak.com/docs/extensions/quickstart.md)**
>
> Generate a field, table column and infolist entry in one package.

> **[Use saved schemas](https://flex-fields.bjanczak.com/docs/extensions/schema-adapter.md)**
>
> Select and configure registered component families from stored definitions.

> **[Add AI guidance](https://flex-fields.bjanczak.com/docs/extensions/ai-guidance.md)**
>
> Let assistants discover your component's usage, examples and storage contract.

## 1. Compose a control from real fields

Watch the example: [02:04 — compose real child fields](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=124s) · [04:34 — place them in Blade](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=274s).

A composed control has a parent layout and real child fields. Each child keeps
its own behavior; the parent decides how they are arranged and named.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TB
    parent["Call-to-action control"] --> label["Flex Text Input<br/>Button text and emoji"]
    parent --> url["Flex Text Input<br/>Validated destination URL"]
    parent --> target["Select<br/>Same tab or new tab"]
    label --> value["call_to_action<br/>label · url · target"]
    url --> value
    target --> value
    value --> model["Your application's save flow"]
```

Add this to the schema of an existing Resource or form:

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
use Bjanczak\FilamentFlexFields\Filament\Forms\Components\CompositeField;
use Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexTextInput;
use Bjanczak\FilamentFlexFields\Filament\Forms\Components\SelectField;

CompositeField::make('call_to_action')
    ->label('Call to action')
    ->schema([
        FlexTextInput::make('label')
            ->label('Button text')
            ->required()
            ->maxLength(80)
            ->emojiPicker(),
        FlexTextInput::make('url')
            ->label('Destination URL')
            ->url()
            ->required(),
        SelectField::make('target')
            ->label('Open link in')
            ->options(['_self' => 'Same tab', '_blank' => 'New tab'])
            ->default('_self')
            ->required(),
    ]);
```

This composition produces one nested value with `label`, `url` and `target`.
For ordinary Eloquent storage, provide a matching JSON column and array cast;
FLEX does not create the database column. If your application needs separate
columns or related rows, define that mapping in its save flow.

Every child still accepts its supported PHP options. Enabling emoji on the text
field does not enable it on other text fields, and choosing a parent layout does
not replace the child's validation or asset ownership.

[See the complete composition patterns](https://flex-fields.bjanczak.com/docs/extensions/composition-patterns.md).

## 2. Give one value several presentations

Watch the example: [36:12 — share a validated value across a field, table column and infolist entry](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=2172s).

A component family can expose a field for editing, a column for tables and an
entry for infolists. You can provide just the surfaces your application needs.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart LR
    value["One saved value"] --> family["Your component family"]
    family --> field["Field<br/>Edit the value"]
    family --> column["Table column<br/>Compact presentation"]
    family --> entry["Infolist entry<br/>Read-only detail"]
    styles["Shared display styles"] -.-> field
    styles -.-> column
    styles -.-> entry
    interaction["Editing behavior"] -.-> field
```

For example, a Summary field can edit text while its column and entry display
that same text. Shared appearance can be reused without loading the editor's
interactive JavaScript in the read-only views.

The [quickstart](https://flex-fields.bjanczak.com/docs/extensions/quickstart.md) generates a working Summary package.
Follow [columns and entries](https://flex-fields.bjanczak.com/docs/extensions/columns-and-entries.md) when adding
another presentation to your own family.

## 3. Render components selected by a saved schema

Watch the example: [59:42 — validate configured family values](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3582s) · [1:01:26 — prepare an explicit value migration](https://www.youtube.com/watch?v=m4V_R7YxTP4\&t=3686s).

Use a saved schema when the set of fields is configurable, such as product
attributes or tenant settings. Your application registers which families are
available and defines their supported configuration.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TB
    definition["Saved field definition<br/>Family · label · allowed configuration"] --> resolve["Resolve an installed family"]
    context["Your application<br/>Record · tenant · permissions"] --> resolve
    resolve --> form["Form builder<br/>Editable field"]
    resolve --> display["Table or infolist builder<br/>Display the saved value"]
    form --> validate["Validate submitted values<br/>and application write permissions"]
    validate --> save["Your application's persistence"]
```

A saved definition chooses from trusted, installed families. It does not contain
executable PHP callbacks or invent a new renderer. Keep relationship queries,
authorization and custom save logic in your application.

This is optional. A normal field or a simple composition does not require a
managed JSON field group. Learn about [schema adapters](https://flex-fields.bjanczak.com/docs/extensions/schema-adapter.md),
[builders](https://flex-fields.bjanczak.com/docs/extensions/schema-builders.md) and [saving values](https://flex-fields.bjanczak.com/docs/extensions/submission.md).

## How composition shares resources

| What you need | What you declare |
| - | - |
| Reuse another component's appearance | `stylesFrom` — share its styles without importing its interactive JavaScript |
| Require another component's styles and JavaScript | `uses` — declare a full dependency; render its actual control separately |
| Render independently configured children | `children` and child schemas — keep each rendered child's state and lifecycle |
| Enable an optional editor or other tool for one instance | `capabilities` — request that feature only for the instances that enable it |

A dependency declaration does not draw the child. Render its real PHP component
or use a child slot. Each rendered instance retains its own resource boundary,
including when the composition appears in a repeater, tab or modal.

See [resource ownership](https://flex-fields.bjanczak.com/docs/extensions/asset-ownership.md),
[typed Select children](https://flex-fields.bjanczak.com/docs/extensions/child-select.md) and
[the child's full PHP API](https://flex-fields.bjanczak.com/docs/extensions/child-php-api.md).

## Choose your next step

| You want to… | Continue with |
| - | - |
| Reuse a small group of fields in your application | [Composition patterns](https://flex-fields.bjanczak.com/docs/extensions/composition-patterns.md) |
| Build and install a named package | [Your first extension](https://flex-fields.bjanczak.com/docs/extensions/quickstart.md) |
| Configure children with callbacks or relationships | [Child PHP API](https://flex-fields.bjanczak.com/docs/extensions/child-php-api.md) |
| Define supported options and defaults | [Configuration](https://flex-fields.bjanczak.com/docs/extensions/configuration.md) |
| Add an editor, dialog or browser interaction | [Runtime SDK](https://flex-fields.bjanczak.com/docs/extensions/sdk.md) and [custom surfaces](https://flex-fields.bjanczak.com/docs/extensions/surfaces.md) |
| Use your own CSS, translations or RTL layout | [Appearance](https://flex-fields.bjanczak.com/docs/extensions/appearance.md) and [locales](https://flex-fields.bjanczak.com/docs/extensions/locales.md) |
| Upgrade saved values and settings | [Migrations](https://flex-fields.bjanczak.com/docs/extensions/migrations.md) |

## Using an extension privately or publishing it

You own your independently written application code. Creating an extension does
not change FLEX's license or grant rights to redistribute FLEX. Private use must
fit your existing free or commercial grant. Before distributing a package or
reusable kit, check the [licensing conditions](https://flex-fields.bjanczak.com/docs/licensing.md) and agree any
required [Custom rights](https://flex-fields.bjanczak.com/docs/plans.md). A license for your hosted application does
not automatically cover software delivery to other customers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.