Wyatt Castaneda

Introducing Tailor for Laravel

Last updated January, 2025


I'm excited to introduce Tailor, a Laravel package I've been working on to simplify class management in Blade components. Inspired by Caleb Porzio's Flux component library, Tailor brings a clean and elegant approach to handling dynamic classes and component variants.

The Inspiration

When Caleb first introduced Flux, he casually showcased a powerful API for managing classes within Blade components.

Seeing Flux::classes() in action—so clean, so elegant—I knew I needed something similar. Another standout feature was the ability to define component variants effortlessly:

<flux:button>Default</flux:button>
<flux:button variant="primary">Primary</flux:button>
<flux:button variant="filled">Filled</flux:button>
<flux:button variant="danger">Danger</flux:button>
<flux:button variant="ghost">Ghost</flux:button>
<flux:button variant="subtle">Subtle</flux:button>

Absolutely beautiful! 🧽

Meet Tailor

Tailor builds on these concepts, providing a powerful yet intuitive API for managing classes, attributes, and variants in Blade components. Here’s a quick guide to how it works:

Getting Started with Tailor

// components/button.blade.php
@props([
    'type' => 'button',
    'size' => 'base',
    'disabled' => false,
    'tag' => 'button',
    'variant' => 'ghost',
])

@php
    $c = Tailor::make('button');

    // Configure attributes
    $c->attributes()
        ->merge($attributes->except('class'))
        ->if($tag === 'button', function ($set) use ($type) {
            $set('type', $type);
        });

    // Define data attributes
    $c->data()->set([
        'variant' => $variant,
        'size' => $size
    ]);

    // Define base classes
    $c->classes()
        ->base(['rounded-lg', 'border', 'ease-in-out', 'text-gray-800', 'font-medium'])
        ->focus(['focus:outline-none', 'focus:ring-2', 'focus:ring-offset-2'])
        ->match($size, [
            'xs' => 'px-2.5 py-1.5 text-xs',
            'sm' => 'px-3 py-2 text-sm',
            'base' => 'px-4 py-2 text-sm',
            'lg' => 'px-4 py-2 text-base',
            'xl' => 'px-6 py-3 text-base',
            'default' => $size,
        ]);

    // Create the `primary` variant
    $primary = $c->variant('primary');

    // Define styles for `primary` variant
    $primary->classes()
        ->light(['!text-inherit', 'bg-inherit', 'border-transparent'])
        ->hoverLight(['hover:text-gray-800', 'hover:bg-gray-300/60'])
        ->focusLight(['focus:border-gray-400', 'focus:ring-gray-400', 'focus:ring-offset-white'])
        ->dark(['dark:bg-gray-700/0'])
        ->hoverDark(['dark:hover:bg-gray-600/80'])
        ->focusDark(['dark:focus:border-gray-500', 'dark:focus:ring-gray-500', 'dark:focus:ring-offset-gray-900']);
    
    // Create the `secondary` variant
    $secondary = $c->variant('secondary');

    // Apply the selected variant
    $c->setVariant($variant);

    // Merge any additional classes
    $c->classes()->merge($attributes->get('class', ''));
@endphp

// Render the button with all defined attributes
<{{ $as }} {{ $c }}>{{ $slot }}</{{ $as }}>

Why Use Tailor?

Tailor helps streamline Blade components by making class management intuitive and maintainable. Whether you're building buttons, cards, or form elements, it provides a structured way to handle attributes, data, and styles dynamically.

I’d love for you to check it out and share your feedback. You can find Tailor on GitHub: Tailor. Let me know what you think!