forked from CredenceOrg/Credence-Frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFormField.tsx
More file actions
45 lines (39 loc) · 1.2 KB
/
Copy pathFormField.tsx
File metadata and controls
45 lines (39 loc) · 1.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from 'react'
import './FormField.css'
interface FormFieldProps {
id: string
label: string
hint?: string
error?: string
/** When true, the label is visually hidden but remains linked to the control via htmlFor/id. */
srOnlyLabel?: boolean
children: React.ReactElement
}
export function FormField({ id, label, hint, error, srOnlyLabel = false, children }: FormFieldProps) {
const hintId = hint ? `${id}-hint` : undefined
const errorId = error ? `${id}-error` : undefined
const existingDescribedBy = children.props['aria-describedby'] as string | undefined
return (
<div className="form-field">
<label htmlFor={id} className={srOnlyLabel ? 'sr-only' : undefined}>
{label}
</label>
{hint && (
<span id={hintId} className="form-hint">
{hint}
</span>
)}
{React.cloneElement(children, {
id,
'aria-describedby':
[existingDescribedBy, hintId, errorId].filter(Boolean).join(' ') || undefined,
'aria-invalid': error ? 'true' : undefined,
})}
{error && (
<span id={errorId} className="form-error" role="alert">
⚠ {error}
</span>
)}
</div>
)
}