tempestphp / tempest-framework

The PHP framework that gets out of your way 🌊
https://tempest.stitcher.io/framework/01-getting-started
MIT License
506 stars 36 forks source link

Anonymous view components #258

Open brendt opened 1 month ago

brendt commented 1 month ago

View components will replace include and replace functionality. We need a way to access view components without them having a dedicated class file though, since oftentimes people will simply want to reference a view file. Let's brainstorm syntax options.

brendt commented 1 month ago

Option 1:

<?php

use Tempest\View\ViewComponent;

return new class implements ViewComponent
{
    public static function getName(): string
    {
        return 'x-my';
    }

    public function render(string $slot): string
    {
?>

        <div class=""><?= $slot ?></div>

<?php
    }
};

I dislike it, but figured I'd mention it anyway

brendt commented 1 month ago

Option 2:

<?php
/** @var \Tempest\View\GenericView $this */
$this->component('x-my');
?>

<div class=""><?= $this->slot() ?></div>
brendt commented 1 month ago

Option 3:

<?php
component('x-my');
?>

<div class=""><?= $this->slot() ?></div>
brendt commented 1 month ago

The tricky part is registering and discovering components. Simultaneously, it's the easy part since we have discovery and it can be cached.

brendt commented 1 month ago

Option 4, and this is the winner:

<x-component name="x-my">
    <?= $this->slot() ?>
</x-component>
brendt commented 1 month ago

Allowing anonymous view components will open up a world of possibilities. I need to write down some thoughts about them so that I know which direction to take. The most important thing is that there's no more need for $this->extends and $this->include, since everything can be modeled with view components.

Here's an example of how extension works:

<x-component name="base-layout">
    <h1><?= $this->title ?? 'Hello' ?></h1>

    <x-slot />
</x-component>

<x-base-layout :title="$this->title">
    <p>Hello world</p>
</x-base-layout>

And here's an example of how inclusion works:

<x-component name="field">
    <label for="<?= $this->name ?>"><?= $this->label ?></label>
    <input type="button" name="<?= $this->name ?>">
</x-component>

<p>
    <x-field name="first_name" label="First Name" />
</p>

I suggest we totally remove extends, include and slot functionality from the view, and only rely on component-based syntax.