Preserve Field aria-describedby on errors
Cloning the control overwrote any existing description ids. Merge the error id in so hints stay announced. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -30,7 +30,8 @@ export type FieldProps = {
|
|||||||
error?: ReactNode;
|
error?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
// A single form control (TextField, Textarea, …). It receives an injected
|
// A single form control (TextField, Textarea, …). It receives an injected
|
||||||
// `id`, plus `aria-describedby`/`aria-invalid` when an error is present.
|
// `id`, plus `aria-invalid` and a merged `aria-describedby` when an error
|
||||||
|
// is present (existing description IDs are kept).
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,11 +52,22 @@ export function Field(props: FieldProps) {
|
|||||||
const existingId = typeof child?.props.id === "string" ? child.props.id : undefined;
|
const existingId = typeof child?.props.id === "string" ? child.props.id : undefined;
|
||||||
const controlId = existingId ?? generatedId;
|
const controlId = existingId ?? generatedId;
|
||||||
|
|
||||||
|
const existingDescribedBy
|
||||||
|
= typeof child?.props["aria-describedby"] === "string"
|
||||||
|
? child.props["aria-describedby"].trim() || undefined
|
||||||
|
: undefined;
|
||||||
|
// Append the error id without dropping hint / help description ids the
|
||||||
|
// control already exposes. Omit the prop when there is no error so an
|
||||||
|
// existing value is not wiped by cloneElement.
|
||||||
|
const describedBy = error != null
|
||||||
|
? [existingDescribedBy, errorId].filter(Boolean).join(" ")
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const control = child
|
const control = child
|
||||||
? cloneElement(child, {
|
? cloneElement(child, {
|
||||||
"id": controlId,
|
id: controlId,
|
||||||
"aria-describedby": error != null ? errorId : undefined,
|
...(describedBy != null ? { "aria-describedby": describedBy } : {}),
|
||||||
"aria-invalid": error != null ? true : undefined,
|
...(error != null ? { "aria-invalid": true as const } : {}),
|
||||||
})
|
})
|
||||||
: children;
|
: children;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user