You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TL;DR: I'm proposing a new component in Symfony UX to manipulate HTML attributes.
--
I've been working for some time now on a UX HTML component. The starting point is an HTML attributes helper and builder: safe by default, fast, and easy to use and extend. The goal is simple: one solid foundation we can rely on across all Symfony UX packages, and that other packages or CMSes could also use or build on.
Recently, a nice PR with a different approach that was discussed a year ago has resurfaced in the Twig repository, and I think it's worth discussing the options.
The two approaches are almost opposites. One could even argue they are not solving the same problem. But I strongly believe this problem is not how we merge complex structured arrays or attributes.... The problem is that we use complex arrays for something that should be much simpler and more direct. Something that still allows conditionals, callables, and runtime customization, but can also offer more specific implementations (data-, aria-, Stimulus, etc.).
Best way to explain, I'm pasting my README below. Hopefully that's enough to kick off the discussion. I do not have a lot of time these days, so I'd rather not sink time into implementation details if the component itself is not something we want in UX.
Open to any questions, feedback, ideas, or suggestions :)
Why Symfony UX HTML?
The Problem
Building HTML attributes programmatically in PHP is tedious and error-prone:
{# in a Twig template #}
{% setattrs= attributes()
.class('btn btn-primary')
.ariaLabel('Submit form')
.disabled(notpost.isEnabled)
%}
<button{{ attrs }}>Submit</button>
Key Benefits
Feature
Traditional
UX HTML
Safety
Manual htmlspecialchars()
Auto-escaped ✅
Immutability
Mutable arrays
Immutable objects ✅
Readability
String concatenation
Fluent API ✅
Type Safety
Strings only
Typed methods ✅
Framework Integration
Manual
Twig/Stimulus helpers ✅
Perfect For
✅ Symfony/Twig applications
✅ Component libraries (buttons, forms, modals)
✅ Stimulus.js integration
✅ Building accessible HTML (ARIA helpers)
✅ Teams valuing code quality and DX
When NOT to Use
❌ Simple static HTML (overkill)
❌ Performance-critical hot paths with millions of attributes (never)
❌ Non-PHP projects
HTML Attributes is a fluent, immutable API for building and rendering HTML attribute strings in PHP. It was designed with performance, security, and developer experience in mind. Out of the box, it supports:
Immutable Operations: Every modification returns a new instance.
Fluent Builder API: Chain methods like set(), add(), remove(), and toggle().
Magic Methods: Enable natural method calls (e.g. ->ariaLabel('Close') or ->disabled()).
Namespaced Helpers: Dedicated helpers for ARIA, Stimulus, and generic data attributes.
Secure Rendering: All output is properly escaped.
High Performance: Optimized for the most common attribute operations.
Installation
composer require symfony/ux-html-attributes
Basic Usage
The library provides a single entry point to build an attribute collection and render it as a string:
set(string $name, string|bool|null $value): self
Create or replace an attribute. Use true for boolean attributes and false or null to remove them. Join arrays with spaces before passing.
add(string $name, string|bool|null $value): self
Append to an existing attribute. When both values are strings they are concatenated with a space.
remove(string $name): self
Remove an attribute from the collection.
toggle(string $name, bool $condition): self
Add the attribute when $condition is true, otherwise remove it.
get(string $name): string|bool|null
Fetch the raw value of an attribute.
all(): array
Return all attributes as an associative array.
render(): string
Render the attribute string with proper escaping.
Magic Methods:
Calls such as ->disabled(), ->ariaLabel('Close'), or ->foo('bar') are automatically converted to attribute names
in kebab-case and handled by the core API.
Namespaced Helpers
ARIA Attributes
Use the dedicated helper to set ARIA attributes:
$attributes->aria()->set('label', 'Close');
// Sets "aria-label" to "Close"
Data Attributes
Use the generic data helper to manage custom data-* attributes:
$attributes->data()->set('foo', 'bar');
// Sets "data-foo" to "bar"
Stimulus Attributes
Use the Stimulus helper to manage data-* attributes and controllers:
> [!IMPORTANT]
> The magic methods are NOT enabled by default. Call `enableMagicMethods()` on the factory or an instance to enable them.
### Combining Attributes
```php
$attributes = Attributes::create()
->set('id', 'example')
->aria()->set('expanded', true)
->stimulus()->addController('dropdown');
echo $attributes->render();
// Output might be: id="example" aria-expanded="true" data-controller="dropdown"
Tip
TL;DR: I'm proposing a new component in Symfony UX to manipulate HTML attributes.
--
I've been working for some time now on a UX HTML component. The starting point is an HTML attributes helper and builder: safe by default, fast, and easy to use and extend. The goal is simple: one solid foundation we can rely on across all Symfony UX packages, and that other packages or CMSes could also use or build on.
Recently, a nice PR with a different approach that was discussed a year ago has resurfaced in the Twig repository, and I think it's worth discussing the options.
The two approaches are almost opposites. One could even argue they are not solving the same problem. But I strongly believe this problem is not how we merge complex structured arrays or attributes.... The problem is that we use complex arrays for something that should be much simpler and more direct. Something that still allows conditionals, callables, and runtime customization, but can also offer more specific implementations (data-, aria-, Stimulus, etc.).
Best way to explain, I'm pasting my README below. Hopefully that's enough to kick off the discussion. I do not have a lot of time these days, so I'd rather not sink time into implementation details if the component itself is not something we want in UX.
Open to any questions, feedback, ideas, or suggestions :)
Why Symfony UX HTML?
The Problem
Building HTML attributes programmatically in PHP is tedious and error-prone:
The Solution
Symfony UX HTML provides a fluent, type-safe, and secure API:
Key Benefits
htmlspecialchars()Perfect For
✅ Symfony/Twig applications
✅ Component libraries (buttons, forms, modals)
✅ Stimulus.js integration
✅ Building accessible HTML (ARIA helpers)
✅ Teams valuing code quality and DX
When NOT to Use
❌ Simple static HTML (overkill)
❌ Performance-critical hot paths with millions of attributes (never)
❌ Non-PHP projects
HTML Attributes is a fluent, immutable API for building and rendering HTML attribute strings in PHP. It was designed with performance, security, and developer experience in mind. Out of the box, it supports:
set(),add(),remove(), andtoggle().->ariaLabel('Close')or->disabled()).Installation
Basic Usage
The library provides a single entry point to build an attribute collection and render it as a string:
Core API
DX-oriented API
Twig Extension
Use the Twig helper to fluently compose attributes inside your templates:
Features
Core API
Immutable
Each method returns a new instance.
Basic Methods:
Create or replace an attribute. Use
truefor boolean attributes andfalseornullto remove them. Join arrays with spaces before passing.Append to an existing attribute. When both values are strings they are concatenated with a space.
Remove an attribute from the collection.
Add the attribute when
$conditionistrue, otherwise remove it.Fetch the raw value of an attribute.
Return all attributes as an associative array.
Render the attribute string with proper escaping.
Magic Methods:
Calls such as
->disabled(),->ariaLabel('Close'), or->foo('bar')are automatically converted to attribute namesin kebab-case and handled by the core API.
Namespaced Helpers
ARIA Attributes
Use the dedicated helper to set ARIA attributes:
Data Attributes
Use the generic data helper to manage custom
data-*attributes:Stimulus Attributes
Use the Stimulus helper to manage
data-*attributes and controllers:Advanced Usage
Boolean and Array Values
Boolean attributes are enabled by passing
trueand removed whenfalseornullis used:When working with arrays of values (e.g. classes) join them with spaces before
calling
set()oradd():Magic Methods
$attributes = Attributes::create()->enableMagicMethods();
$attributes->ariaLabel('Accessible Label'); // Sets aria-label="Accessible Label"
$attributes->foo('bar'); // Sets foo="bar"
Stimulus Helpers
Future Features
Additional merging strategies and extensions are already planned for future releases (tailwind merge, CSS scoping, references...)
[...]