Skip to content

Conversation

@AlexandreBulete
Copy link

Description

This PR adds a new badge field component for Sylius Grid that supports:

  • ✅ PHP 8.1+ enums with getLabel(), getColor(), and getIcon() methods
  • ✅ Customization via options.vars.colors, labels, and icons
  • ✅ Badge styling with rounded-pill
  • ✅ Optional icon
  • ✅ Sylius test attributes

Usage Example

use Sylius\Bundle\GridBundle\Builder\Field\TwigField;

TwigField::create('status', '@SyliusBootstrapAdminUi/shared/grid/field/badge.html.twig')
    ->setLabel('Status')
    ->setOptions([
        'vars' => [
            'colors' => [
                'active' => 'success',
                'inactive' => 'danger',
            ],
            'icons' => [
                'active' => 'bi:check-circle',
            ],
        ],
    ]),

With PHP Enum

enum Status: string
{
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';

    public function getLabel(): string
    {
        return match($this) {
            self::ACTIVE => 'Active',
            self::INACTIVE => 'Inactive',
        };
    }

    public function getColor(): string
    {
        return match($this) {
            self::ACTIVE => 'success',
            self::INACTIVE => 'danger',
        };
    }

    public function getIcon(): string
    {
        return match($this) {
            self::ACTIVE => 'bi:check-circle',
            self::INACTIVE => 'bi:x-circle',
        };
    }
}

Files added

  • templates/shared/grid/field/badge.html.twig
  • templates/shared/helper/field/badge.html.twig

@AlexandreBulete AlexandreBulete changed the title feat: Add badge field component with enum support [AdminUi] Add badge field component with enum support Nov 14, 2025
Copy link
Member

@loic425 loic425 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for your proposal. It's an interesting idea.

1/ You Twig template has too much complexity
2/ test_html_attribute placed on color is strange
3/ magic with getLabel, getColor without any interface is not cool.

@AlexandreBulete
Copy link
Author

Thanks for the feedback!

I've refactored the badge implementation to address all concerns:

  • Template complexity reduced (53 → 26 lines, logic moved to PHP)
  • Test attribute now value-based instead of color-based
  • Added BadgeableInterface for type safety (no more magic checks)

Created proper architecture with value objects and Twig extension. Documentation included.

Let me know if you need any changes!

* This class normalizes badge data from various sources (BadgeableInterface, arrays, strings)
* into a consistent format for rendering.
*/
final readonly class BadgeData
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a nit-pick but shoudln't it simply be called Badge?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, for me, this class is more akin to DTO behaviour, which involves instantiating and formatting data (hydrated from the enum) to be used properly by the twig template. That's why it seemed more logical to me to add something like the suffix “Data.”

{% set badgeData = sylius_badge_data(data, options|default({})) %}

{% if badgeData %}
<span class="badge rounded-pill text-{{ badgeData.color }}" {{ sylius_test_html_attribute('badge', badgeData.value ?? badgeData.label) }}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the color should be on the badge itself (background instead of text), so for instance a colour like bg-purple-lt would be rendered via

Suggested change
<span class="badge rounded-pill text-{{ badgeData.color }}" {{ sylius_test_html_attribute('badge', badgeData.value ?? badgeData.label) }}>
<span class="badge rounded-pill bg-{{ badgeData.color }}" {{ sylius_test_html_attribute('badge', badgeData.value ?? badgeData.label) }}>

and which would render as something like Image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! After testing it, you've convinced me! :)
I'll remove the rounded-pill and add this CSS class bg-{color}-lt instead of a simple text-color to match your screenshot. I also fixed the icon-text flex alignment too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible globally for all those kind of templates to get a way to expose all HTML attributes the same way Symfony form block "attributes" is working?
It's just an idea, it's not required a required change for this PR.

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.

4 participants