Skip to content

Commit ccbd7ec

Browse files
committed
(fix): accessibility on Select, aria-described-by of <select> should be defined when state is different of default
1 parent ad213e1 commit ccbd7ec

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/Select.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,16 @@ export const Select = memo(
6363
return `select-${id}`;
6464
})();
6565

66-
const stateDescriptionId = `select-${useId()}-desc`;
6766
const messagesGroupId = `${selectId}-messages-group`;
6867

68+
const selectStateDescriptionId = useId();
69+
const stateIsDefault = state === "default";
70+
71+
const stateDescriptionId = getStateDescriptionId(stateIsDefault, selectStateDescriptionId);
72+
const nativeDescription = getSelectNativeDescription(nativeSelectProps["aria-describedby"]);
73+
74+
const selectAriaDescribedBy = `${stateDescriptionId} ${nativeDescription}`.trim();
75+
6976
return (
7077
<div
7178
id={id}
@@ -104,17 +111,13 @@ export const Select = memo(
104111
{...nativeSelectProps}
105112
className={cx(fr.cx("fr-select"), nativeSelectProps.className)}
106113
id={selectId}
107-
aria-describedby={
108-
nativeSelectProps["aria-describedby"] !== undefined
109-
? `${stateDescriptionId} ${nativeSelectProps["aria-describedby"]}`
110-
: stateDescriptionId
111-
}
114+
aria-describedby={selectAriaDescribedBy}
112115
disabled={disabled}
113116
>
114117
{children}
115118
</select>
116119
<div id={messagesGroupId} className={fr.cx("fr-messages-group")} aria-live="polite">
117-
{state !== "default" && (
120+
{!stateIsDefault && (
118121
<p
119122
id={stateDescriptionId}
120123
className={fr.cx(
@@ -140,6 +143,16 @@ export const Select = memo(
140143
})
141144
);
142145

146+
function getStateDescriptionId(stateIsDefault: boolean, selectStateDescriptionId: string) {
147+
return stateIsDefault ? "" : `select-${selectStateDescriptionId}-desc`;
148+
}
149+
150+
function getSelectNativeDescription(
151+
nativeSelectPropsAriaDescribedBy: React.SelectHTMLAttributes<HTMLSelectElement>["aria-describedby"]
152+
) {
153+
return nativeSelectPropsAriaDescribedBy !== undefined ? nativeSelectPropsAriaDescribedBy : "";
154+
}
155+
143156
Select.displayName = symToStr({ Select });
144157

145158
export default Select;

0 commit comments

Comments
 (0)