Skip to content

Commit 78cf7f1

Browse files
committed
[Icons] Set aria-hidden="true" when title/label not set
1 parent 71412bc commit 78cf7f1

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

src/Icons/src/DependencyInjection/UXIconsExtension.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ public function getConfigTreeBuilder(): TreeBuilder
4343
->info('Default attributes to add to all icons.')
4444
->defaultValue(['fill' => 'currentColor'])
4545
->end()
46+
->arrayNode('renderer')
47+
->info('Options for the icon renderer.')
48+
->children()
49+
->booleanNode('auto_aria_hidden')
50+
->info('Automatically set aria-hidden="true" when no label or title is provided.')
51+
->defaultTrue()
52+
->end()
53+
->end()
54+
->end()
4655
->arrayNode('iconify')
4756
->info('Configuration for the "on demand" icons powered by Iconify.design.')
4857
->{interface_exists(HttpClientInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
@@ -94,6 +103,7 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
94103

95104
$container->getDefinition('.ux_icons.icon_renderer')
96105
->setArgument(1, $mergedConfig['default_icon_attributes'])
106+
->setArgument(2, $mergedConfig['renderer'] ?? [])
97107
;
98108

99109
if ($mergedConfig['iconify']['enabled']) {

src/Icons/src/IconRenderer.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ final class IconRenderer
2121
public function __construct(
2222
private readonly IconRegistryInterface $registry,
2323
private readonly array $defaultIconAttributes = [],
24+
/**
25+
* @var array{
26+
* auto_aria_hidden: bool
27+
* }
28+
*/
29+
private readonly array $rendererConfiguration = [],
2430
) {
2531
}
2632

@@ -38,8 +44,22 @@ public function __construct(
3844
public function renderIcon(string $name, array $attributes = []): string
3945
{
4046
return $this->registry->get($name)
41-
->withAttributes([...$this->defaultIconAttributes, ...$attributes])
47+
->withAttributes($this->getIconAttributes($name, $attributes))
4248
->toHtml()
4349
;
4450
}
51+
52+
private function getIconAttributes(string $name, array $attributes): array
53+
{
54+
$iconAttributes = $this->defaultIconAttributes;
55+
56+
// Add aria-hidden attribute
57+
if ($this->rendererConfiguration['auto_aria_hidden'] ?? false) {
58+
if ([] === array_intersect(['aria-hidden', 'aria-label', 'aria-labelledby', 'title'], array_keys($attributes))) {
59+
$iconAttributes['aria-hidden'] = 'true';
60+
}
61+
}
62+
63+
return [...$iconAttributes, ...$attributes];
64+
}
4565
}

src/Icons/tests/Unit/IconRendererTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,45 @@ public static function provideAttributesWithDefaultAttributesCases()
159159
];
160160
}
161161

162+
/**
163+
* @dataProvider provideAriaHiddenCases
164+
*
165+
* @param array<string, string> $attributes
166+
*/
167+
public function testRenderIconWithAutoAriaHidden(array $attributes, string $expectedSvg): void
168+
{
169+
$registry = $this->createRegistry([
170+
'foo' => '<path d="M0 0L12 12"/>',
171+
]);
172+
$iconRenderer = new IconRenderer($registry, [], ['auto_aria_hidden' => true]);
173+
174+
$svg = $iconRenderer->renderIcon('foo', $attributes);
175+
$this->assertSame($expectedSvg, $svg);
176+
}
177+
178+
/**
179+
* @return iterable<array{array<string, string>, string}>
180+
*/
181+
public static function provideAriaHiddenCases(): iterable
182+
{
183+
yield "no attributes" => [
184+
[],
185+
'<svg aria-hidden="true"><path d="M0 0L12 12"/></svg>',
186+
];
187+
yield "aria-hidden attribute" => [
188+
['aria-hidden' => 'true'],
189+
'<svg aria-hidden="true"><path d="M0 0L12 12"/></svg>',
190+
];
191+
yield "title attribute" => [
192+
['title' => 'foo'],
193+
'<svg title="foo"><path d="M0 0L12 12"/></svg>',
194+
];
195+
yield "aria-labelledby attribute" => [
196+
['aria-labelledby' => 'foo'],
197+
'<svg aria-labelledby="foo"><path d="M0 0L12 12"/></svg>',
198+
];
199+
}
200+
162201
private function createRegistry(array $icons): IconRegistryInterface
163202
{
164203
$registryIcons = [];

0 commit comments

Comments
 (0)