Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow scoping of attributes to specific elements inside Blade components. #54968

Open
wants to merge 2 commits into
base: 12.x
Choose a base branch
from

Conversation

abdelhamiderrahmouni
Copy link

Added Scoped Attributes to ComponentAttributeBag for Blade Components

Problem

While working with Blade components, I encountered a major limitation when trying to apply styles or attributes to specific elements within a component:

  • Attributes could only be passed if a slot was present, requiring an explicit closing tag. This reduced the simplicity and flexibility of Blade components.

For example, I wanted to build the following input component:

@props(['label', 'input', 'helperText'])

<div {{ $attributes->merge(['class' => 'w-full max-w-sm']) }}>
    @if ($label)
        <label {{ $label->attributes->merge(['class' => 'text-gray-950']) }}>
            {{ $label }}
        </label>
    @endif

    <input {{ $input->attributes->merge(['class' => 'py-4 px-0']) }} />

    @if (isset($helperText) && !blank($helperText))
        <span {{ $helperText->attributes->merge(['class' => 'text-gray-500']) }}>
            {{ $helperText }}
        </span>
    @endif
</div>

Current Usage and Limitation

Currently, applying styles to child elements requires defining multiple slots:

<x-forms.input name="first_name" id="name-input-container">
    <x-slot name="label" class="text-blue-700">
        {{ __('Hello') }}
    </x-slot>
    <x-slot name="input" id="input" class="text-slate-700 text-sm"></x-slot>
</x-forms.input>

The problem is that an extra slot must be added just to style the input element, making it cumbersome for every slot in the component.


Solution

Introducing the scope function to the ComponentAttributeBag class, allows attributes to be scoped to specific elements using a prefix convention.

Example Usage

With the scope function, the component can now be used like this:

<x-forms.input name="first_name"
               :label="__('Hello')"
               label:class="flex flex-col"
               label:for="#name-input"
               input:id="name-input"
               container:id="name-input-container" />

This approach eliminates the need for extra slots, allowing attributes to be directly assigned to the corresponding element using the prefix:attribute format.


Updated Component Implementation

Attributes can be automatically scoped to the correct elements within the component:

<!-- forms.input.blade.php -->
<div {{ $attributes->scope('container')->merge(['class' => 'flex gap-y-2']) }}>
    
    @if ($label)
        <label {{ $attributes->scope('label')->merge(['class' => 'text-gray-500']) }}>
            {{ $label }}
        </label>
    @endif

    <input {{ $attributes->scope('input')->merge(['class' => 'border-b']) }} />
</div>

Each element has a named scope, and attributes with the corresponding prefix are automatically applied to the correct element.

This enhancement improves Blade component flexibility, simplifies attribute management, and eliminates the need for redundant slots.

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