Docs / Inlay / Single-file Components

Single-file components

For a simple component, defining a class and a separate view is more ceremony than it needs. A single-file component declares everything - handle, metadata, settings - in one Blade file, compiling into the exact same internal representation a class + view component resolves to. The registry, the picker, settings resolution, validation, persistence, preview, rendering, publishing, and revisions all treat the two identically; nothing downstream branches on which one produced a given component.

This is not Livewire Volt. It borrows the one-file ergonomic, but a single-file component is an ordinary Blade file rendered through Laravel's real view engine. It may contain nested Livewire tags exactly like a class-based component, but it is not itself a Livewire component and doesn't depend on the Volt package.

{{-- resources/views/inlay/components/hero.blade.php --}} <?php use App\Enums\ImageSize; use WearePixel\Inlay\Schema\Settings; use WearePixel\Inlay\SingleFile\Component; component( Component::make('hero') ->name('Hero') ->category('Headers') ->icon('layout-header') ->settings( Settings::make() ->text('heading')->label('Heading')->default('Welcome') ->select('imageSize')->label('Image size')->options(ImageSize::class)->default(ImageSize::Large) ) ); ?> <section> <h1>{{ $heading }}</h1> <img class="{{ $imageSize === ImageSize::Small ? 'max-w-md' : 'w-full' }}" src="..."> </section>

The PHP block at the top declares the component; everything after the closing ?> is ordinary Blade markup, rendered with every setting already available as a variable - exactly as $data is available in any Blade view.

Every top-level setting needs a default

A single-file component has no constructor, so there's nothing for the settings declaration to be cross-checked against - it must be authoritative on its own for field type, nullability, default, and enum/value-object type. Concretely, ->default(...) is required on every top-level setting (unlike a class-based component, where the constructor parameter's own default is authoritative and a schema-level .default() is reserved for nested repeater/group fields only). Omitting it fails registration immediately:

Single-file component [hero] setting [heading] has no default(). A single-file component has no constructor to infer one from - every top-level setting must declare its own default via ->default(...).

Everything else about authoring settings - field types, visibleWhen(), enums, links, repeaters, groups - works identically to the fluent Settings API documented in Fluent settings.

Registering a single file

Register a file explicitly, e.g. from AppServiceProvider::boot():

use WearePixel\Inlay\Facades\Inlay; Inlay::singleFileComponent(resource_path('views/inlay/components/hero.blade.php'));

Or register every *.blade.php file directly inside a directory at once:

Inlay::singleFileComponents(resource_path('views/inlay/components'));

Directory discovery uses each file's own declared handle (from Component::make('hero') inside it), not its filename - the filename is purely an organisational convenience, not a second source of truth for the handle. A handle already claimed by a class-based component, or by another single-file component, is a registration error rather than a silent override:

Cannot register single-file component [hero] - a class-based component is already registered for that handle.

Referencing a handle-only component

A future Page Definition's component allow-list will need to name components, but a single-file component has no PHP class to put in a list of ::class references. WearePixel\Inlay\Support\ComponentHandle is a small typed value object for exactly this case, added now so that whenever Page Definitions ship, there's already a safe, IDE-discoverable way to reference a handle-only component rather than a raw string:

// Illustrative - Page Definitions are not implemented yet. public function allowedComponents(): array { return [ Hero::class, ComponentHandle::make('promo-banner'), ]; }

Single-file-specific registration errors

| Situation | Exception message | | --- | --- | | A top-level setting has no ->default() | Single-file component [...] setting [...] has no default(). ... | | The Blade file never calls component(...) | [...] does not declare a single-file component - it must call component(Component::make(...)) in a PHP block at the top of the file. | | Inlay::singleFileComponent() is given a path with no file | No single-file component found at [...]. | | A handle collides with an already-registered component | Cannot register single-file component [...] - a class-based component is already registered for that handle. (or the equivalent for another single-file component) |

See Registering components for the errors shared with class-based components.

Discovery Call

One call.
We'll both know.

An hour to walk through your project, ask the hard questions, and work out honestly if we're the right team for it.

  • One call per day - it gets our full attention
  • Australia's only Laravel Premier Partner
  • Senior engineers only - no juniors on your project
  • Brisbane-based, onshore team

Press Esc to close  ·  B to reopen