Skip to content

feat(view): add x-slot define attribute to declare slot ownership in nested components#2104

Open
iamdadmin wants to merge 3 commits intotempestphp:3.xfrom
iamdadmin:3.x-slot-define
Open

feat(view): add x-slot define attribute to declare slot ownership in nested components#2104
iamdadmin wants to merge 3 commits intotempestphp:3.xfrom
iamdadmin:3.x-slot-define

Conversation

@iamdadmin
Copy link
Copy Markdown
Contributor

Consider this x-header component, which uses an x-container to position it's content. x-container itself is just a <div> with some classes for formatting, it has only a default slot.

<header>
    <x-slot name="top" />
    <x-container>
        <x-slot name="left"> // this slot is assumed to exist within x-container
            <x-header-left />
        </x-slot>
        <div>
            I am in the center
        </div> 
        <x-slot name="right">  // this slot is assumed to exist within x-container
            <x-header-right />
        </x-slot>
    </x-container>
    <x-slot name="bottom" />
</header>

At the callsite, if you want to override the default content of the "left" or "right" slot, you can't, because tempest/view assumes these are slots of x-container.

This, for example, doesn't match because x-header itself doesn't have a "left" slot.

<x-header>
    <x-slot name="left">Some content I want to insert</x-slot>
</x-header>

This PR adds the ability to define a slot, as owned in the ViewComponent it's defined in. The x-header becomes:

<header>
    <x-slot name="top" />
    <x-container>
        <x-slot define="left"> // define this slot as a slot of x-header, compiled and passed into x-container's default slot
            <x-header-left />
        </x-slot>
        <div>
            I am in the center
        </div> 
        <x-slot define="right">  // define this slot as a slot of x-header, compiled and passed into x-container's default slot
            <x-header-right />
        </x-slot>
    </x-container>
    <x-slot name="bottom" />
</header>

At the callsite, this now works

<x-header>
    <x-slot name="left">Some content I want to insert</x-slot>
</x-header>

You can also push content into a child's named slot this way:

        <div class="outer">
            <x-inner>
                <x-slot name="left">
                    <x-slot define="left"><x-header-left /></x-slot>
                </x-slot>
            </x-inner>
        </div>

At the callsite:

<x-outer>
    <x-slot name="left">My override</x-slot>
</x-outer>

@iamdadmin iamdadmin requested a review from brendt as a code owner April 4, 2026 06:41
@iamdadmin
Copy link
Copy Markdown
Contributor Author

This isn't a breaking change, happily; it doesn't change the behaviour of <x-slot name=""> - and is actually a very simple implementation. It's also optional, meaning no need to change anything at all, unless you specifically need this type of slot.

Writing up some docs now.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 4, 2026

Benchmark Results

Comparison of 3.x-slot-define against 3.x (6c8b9fefdf1a7c7cde6cecdfe9ae902883cc05c7).

Open to see the benchmark results
Benchmark Set Mem. Peak Time Variability
QueryExecutionBench(benchFetchWithBindings) - 4.338mb 0.00% 18.280μs -5.58% ±1.88% -37.75%
ViewRenderBench(benchPlainHtml) - 21.960mb 0.00% 490.103μs -5.86% ±2.41% +6.84%
ViewRenderBench(benchExpressions) - 24.517mb 0.00% 521.314μs -8.21% ±2.92% +104.06%

Generated by phpbench against commit 6e7867c

@iamdadmin iamdadmin requested a review from innocenzi as a code owner April 4, 2026 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant