Skip to content

Commit 27d316b

Browse files
authored
Update Icon.php
1 parent 8b8296d commit 27d316b

File tree

1 file changed

+40
-25
lines changed

1 file changed

+40
-25
lines changed

src/Icons/src/Icon.php

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -141,51 +141,66 @@ public function toHtml(): string
141141
$htmlAttributes = '';
142142
$innerSvg = $this->innerSvg;
143143
$attributes = $this->attributes;
144-
144+
145145
// Extract and remove title/desc attributes if present
146146
$title = $attributes['title'] ?? null;
147147
$desc = $attributes['desc'] ?? null;
148148
unset($attributes['title'], $attributes['desc']);
149-
150-
// Prepare <title> and <desc> elements
149+
151150
$labelledByIds = [];
152151
$a11yContent = '';
153-
152+
153+
// Check if aria-labelledby should be added automatically
154+
$shouldSetLabelledBy = !isset($attributes['aria-labelledby']) && ($title || $desc);
155+
154156
if ($title) {
155-
$titleId = 'title-' . bin2hex(random_bytes(4));
156-
$labelledByIds[] = $titleId;
157-
$a11yContent .= sprintf('<title id="%s">%s</title>', $titleId, htmlspecialchars((string) $title, ENT_QUOTES));
157+
if ($shouldSetLabelledBy) {
158+
$titleId = 'title-' . bin2hex(random_bytes(4));
159+
$labelledByIds[] = $titleId;
160+
$a11yContent .= sprintf('<title id="%s">%s</title>', $titleId, htmlspecialchars((string) $title, ENT_QUOTES));
161+
} else {
162+
$a11yContent .= sprintf('<title>%s</title>', htmlspecialchars((string) $title, ENT_QUOTES));
163+
}
158164
}
159-
165+
160166
if ($desc) {
161-
$descId = 'desc-' . bin2hex(random_bytes(4));
162-
$labelledByIds[] = $descId;
163-
$a11yContent .= sprintf('<desc id="%s">%s</desc>', $descId, htmlspecialchars((string) $desc, ENT_QUOTES));
167+
if ($shouldSetLabelledBy) {
168+
$descId = 'desc-' . bin2hex(random_bytes(4));
169+
$labelledByIds[] = $descId;
170+
$a11yContent .= sprintf('<desc id="%s">%s</desc>', $descId, htmlspecialchars((string) $desc, ENT_QUOTES));
171+
} else {
172+
$a11yContent .= sprintf('<desc>%s</desc>', htmlspecialchars((string) $desc, ENT_QUOTES));
173+
}
164174
}
165-
166-
// Only add aria-labelledby if not already present and we have content
167-
if ($a11yContent !== '' && !isset($attributes['aria-labelledby'])) {
175+
176+
if ($shouldSetLabelledBy) {
168177
$attributes['aria-labelledby'] = implode(' ', $labelledByIds);
169178
}
170-
179+
171180
// Build final attributes string
172181
foreach ($attributes as $name => $value) {
173-
if (false === $value) {
182+
if ($value === false) {
174183
continue;
175184
}
176-
177-
if (true === $value && str_starts_with($name, 'aria-')) {
185+
186+
// Special case for aria-* attributes
187+
// https://www.w3.org/TR/wai-aria-1.1/#state_prop_def
188+
if ($value === true && str_starts_with($name, 'aria-')) {
178189
$value = 'true';
179190
}
180-
181-
$htmlAttributes .= ' '.$name;
182-
183-
if (true === $value) {
191+
192+
$htmlAttributes .= ' ' . $name;
193+
194+
if ($value === true) {
184195
continue;
185196
}
186-
187-
$value = htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
188-
$htmlAttributes .= '="'.$value.'"';
197+
198+
$value = htmlspecialchars($value, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8');
199+
$htmlAttributes .= '="' . $value . '"';
200+
}
201+
202+
// Inject <title> and <desc> before inner content
203+
return '<svg' . $htmlAttributes . '>' . $a11yContent . $innerSvg . '</svg>';
189204
}
190205

191206
public function getInnerSvg(): string

0 commit comments

Comments
 (0)