Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Html Extra Laravel Package

twig/html-extra

Twig HTML Extension adds handy helpers to Twig: a data_uri filter for RFC 2397 data URLs, an html_classes function to conditionally build CSS class strings, and an html_cva function for managing class variants via a Cva object.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation Require the package in your Laravel project:

    composer require twig/html-extra
    

    Register the extension in your Twig environment (e.g., in AppServiceProvider):

    use Twig\Extra\Html\HtmlExtension;
    
    public function boot()
    {
        $twig = $this->app['twig'];
        $twig->addExtension(new HtmlExtension());
    }
    
  2. First Use Case Use the html_classes function to conditionally merge classes in a Twig template:

    <button class="{{ 'btn'|html_classes({
        'btn-primary': isPrimary,
        'btn-disabled': isDisabled,
        'btn-lg': isLarge
    }) }}">
        {{ buttonText }}
    </button>
    

    Outputs:

    <button class="btn btn-primary btn-lg">Submit</button>
    

Implementation Patterns

Daily Usage Patterns

  1. Conditional Class Merging Replace manual string concatenation with html_classes for cleaner templates:

    {% set classes = 'card'|html_classes({
        'card--featured': isFeatured,
        'card--shadow': hasShadow,
        'card--wide': isWide
    }) %}
    <div class="{{ classes }}">{{ content }}</div>
    
  2. Class Variant Abstraction (CVA) Define reusable class variants for components (e.g., buttons, cards):

    {% set button = 'button'|html_cva({
        'primary': 'bg-blue-600 text-white',
        'secondary': 'bg-gray-200 text-gray-800',
        'size': {
            'sm': 'px-3 py-1 text-sm',
            'md': 'px-4 py-2',
            'lg': 'px-6 py-3'
        }
    }) %}
    
    <button class="{{ button('primary', 'md') }}">
        Save
    </button>
    
  3. Data URIs for Embedded Assets Inline small assets (e.g., icons, SVGs) to reduce HTTP requests:

    <img src="{{ 'assets/icons/logo.svg'|data_uri }}" alt="Logo">
    

    Note: Validate file sizes (aim for <10KB) to avoid bloating HTML.

  4. HTML Attribute Generation Use html_attr (v3.24.0+) for dynamic attributes:

    <input type="text" {{ html_attr({
        'class': 'form-input',
        'disabled': isDisabled,
        'placeholder': 'Enter text...'
    }) }}>
    

Workflow Integration

  • Component Libraries Pair with Laravel’s view components or Inertia.js for reusable UI:

    {% component 'Button', {
        'text': 'Click',
        'classes': 'btn'|html_cva(buttonVariants)('primary', 'md')
    } %}
    
  • Dark Mode Toggle Dynamically switch classes based on user preference:

    {% set themeClasses = 'dark'|html_classes({
        'light': isLightMode
    }) %}
    <body class="{{ themeClasses }}">
    
  • A/B Testing Randomly apply classes to test variants:

    {% set variant = 'variant-a'|html_classes({
        'variant-b': abTestVariant == 'b'
    }) %}
    <div class="{{ variant }}">{{ content }}</div>
    

Laravel-Specific Tips

  • Cache Twig Templates Pre-compile templates for production:

    php artisan twig:cache:compile
    
  • Hybrid Blade/Twig Use Twig for dynamic HTML and Blade for Laravel-specific logic:

    @twig('partials/_header.twig', {
        'user': auth()->user(),
        'activeRoute': request()->route()->getName()
    })
    
  • Validation for Data URIs Sanitize inputs to prevent XSS:

    // In a controller or form request
    $path = Storage::path('uploads/' . $request->file('icon')->store('icons'));
    $uri = e($path); // Escape for Twig
    return view('template', ['iconUri' => $uri]);
    

Gotchas and Tips

Common Pitfalls

  1. Auto-escaping in Twig Twig escapes HTML by default. Use |raw for trusted data_uri outputs:

    <img src="{{ 'icon.svg'|data_uri|raw }}">
    
  2. Immutable Cva Object html_cva returns an immutable object. Reuse it or redefine:

    {% set button = 'btn'|html_cva(buttonVariants) %}
    {# ❌ Avoid: button('primary') = 'new-class' #}
    {% set newButton = 'btn'|html_cva(buttonVariants)('primary') %}
    
  3. Performance with Large Class Lists html_classes iterates over all keys. For >50 classes, optimize:

    {% set baseClasses = 'base-class1 base-class2' %}
    <div class="{{ baseClasses ~ ' ' ~ (baseClasses|html_classes(additionalClasses)) }}">
    
  4. Data URI Size Limits Browsers may reject large base64 strings. Test with:

    wc -c <(base64 -w0 icon.svg)
    

    Target: <10KB (adjust threshold based on use case).

  5. Twig vs. Blade Conflicts Avoid naming collisions (e.g., @class in Blade vs. html_classes in Twig). Use namespaces:

    {% import '_partials/components.twig' as components %}
    {{ components.button({ text: 'Click' }) }}
    

Debugging Tips

  • Check Twig Errors Enable Twig’s debug mode in config/twig.php:

    'debug' => env('APP_DEBUG', false),
    

    Errors show template line numbers.

  • Inspect Cva Output Debug variants with:

    {{ dump(buttonVariants) }}
    
  • Validate Data URIs Test with a known file:

    {{ 'assets/placeholder.png'|data_uri|raw }}
    

    If broken, check file permissions or paths.

Configuration Quirks

  1. Extension Registration Ensure the extension is added after Twig is initialized:

    $twig->addExtension(new HtmlExtension());
    
  2. Custom Filters/Functions Extend the package by creating a custom Twig extension:

    use Twig\TwigFunction;
    
    $twig->addFunction(new TwigFunction('custom_html_class', function ($classes) {
        return (new HtmlClasses())->merge(...$classes);
    }));
    
  3. Laravel Mix Compatibility data_uri bypasses Laravel Mix. For dynamic assets:

    {% if env('APP_ENV') == 'local' %}
        <img src="{{ 'icon.svg'|data_uri|raw }}">
    {% else %}
        <img src="{{ mix('assets/icons/logo.svg') }}">
    {% endif %}
    

Extension Points

  1. Custom HtmlClasses Logic Override the default merging behavior:

    $twig->addFunction(new TwigFunction('custom_classes', function ($classes) {
        $htmlClasses = new HtmlClasses();
        $htmlClasses->setStrategy(new CustomStrategy());
        return $htmlClasses->merge(...$classes);
    }));
    
  2. Data URI Sanitization Add a custom filter to validate paths:

    $twig->addFilter(new TwigFilter('safe_data_uri', function ($path) {
        if (!Storage::exists($path)) {
            throw new \RuntimeException("File not found: {$path}");
        }
        return (new DataUri())->encode($path);
    }));
    
  3. Integrate with Tailwind/Jetstream Use html_cva for Tailwind variants:

    {% set button = 'focus:ring-4'|html_cva({
        'primary': 'bg-blue-600 text-white',
        'secondary': 'bg-gray-200 text-gray-800',
        'size': {
            'sm': 'px-3 py-1 text-sm',
            'md': 'px-4 py-2'
        }
    }) %}
    <button class="{{ button('primary', 'md') }}">
        Login
    </button>
    

Pro Tips

  • Reusable CVA Definitions Store variant maps in a separate file (e.g., resources/twig/variants/button.twig):
    {% macro buttonVariants() %}
    {
        'primary': 'bg-blue-600 text-white',
        'secondary': 'bg-gray-200 text
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope