Skip to content

Commit 7f2ddce

Browse files
authored
Pass through FormControl.Label props (#3262)
* add test * changeset * pass through InputLabel props too
1 parent 3d89d51 commit 7f2ddce

File tree

4 files changed

+54
-15
lines changed

4 files changed

+54
-15
lines changed

.changeset/polite-chicken-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/react': patch
3+
---
4+
5+
passthrough form control label props

src/FormControl/_FormControlLabel.tsx

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import InputLabel, {LabelProps, LegendOrSpanProps} from '../_InputLabel'
2+
import InputLabel from '../_InputLabel'
33
import {SxProp} from '../sx'
44
import {FormControlContext} from './FormControl'
55

@@ -12,21 +12,35 @@ export type Props = {
1212
} & SxProp
1313

1414
const FormControlLabel: React.FC<
15-
React.PropsWithChildren<{htmlFor?: string} & (LegendOrSpanProps | LabelProps) & Props>
16-
> = ({children, htmlFor, id, visuallyHidden, sx}) => {
15+
React.PropsWithChildren<{htmlFor?: string} & React.ComponentProps<typeof InputLabel> & Props>
16+
> = ({as, children, htmlFor, id, visuallyHidden, sx, ...props}) => {
1717
const {disabled, id: formControlId, required} = React.useContext(FormControlContext)
18-
return (
19-
<InputLabel
20-
htmlFor={htmlFor || formControlId}
21-
id={id}
22-
visuallyHidden={visuallyHidden}
23-
required={required}
24-
disabled={disabled}
25-
sx={sx}
26-
>
27-
{children}
28-
</InputLabel>
29-
)
18+
19+
/**
20+
* Ensure we can pass through props correctly, since legend/span accept no defined 'htmlFor'
21+
*/
22+
const labelProps: React.ComponentProps<typeof InputLabel> =
23+
as === 'legend' || as === 'span'
24+
? {
25+
as,
26+
id,
27+
visuallyHidden,
28+
required,
29+
disabled,
30+
sx,
31+
...props,
32+
}
33+
: {
34+
as,
35+
id,
36+
visuallyHidden,
37+
htmlFor: htmlFor || formControlId,
38+
required,
39+
disabled,
40+
sx,
41+
...props,
42+
}
43+
return <InputLabel {...labelProps}>{children}</InputLabel>
3044
}
3145

3246
export default FormControlLabel

src/_InputLabel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const InputLabel: React.FC<React.PropsWithChildren<Props>> = ({
3131
visuallyHidden,
3232
sx,
3333
as = 'label',
34+
...props
3435
}) => {
3536
return (
3637
<VisuallyHidden
@@ -49,6 +50,7 @@ const InputLabel: React.FC<React.PropsWithChildren<Props>> = ({
4950
alignSelf: 'flex-start',
5051
...sx,
5152
}}
53+
{...props}
5254
>
5355
{required ? (
5456
<Box display="flex" as="span">

src/__tests__/FormControl.test.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ describe('FormControl', () => {
199199
expect(input).toBeDefined()
200200
expect(label).toBeDefined()
201201
})
202+
203+
it('passes through props on the label element', () => {
204+
const {getByLabelText, getByText} = render(
205+
<SSRProvider>
206+
<FormControl>
207+
<FormControl.Label data-testid="some-test-id">{LABEL_TEXT}</FormControl.Label>
208+
<Textarea />
209+
</FormControl>
210+
</SSRProvider>,
211+
)
212+
213+
const input = getByLabelText(LABEL_TEXT)
214+
const label = getByText(LABEL_TEXT)
215+
216+
expect(input).toBeDefined()
217+
expect(label).toBeDefined()
218+
expect(label).toHaveAttribute('data-testid', 'some-test-id')
219+
})
202220
})
203221

204222
describe('ARIA attributes', () => {

0 commit comments

Comments
 (0)