Skip to content

Commit 83c125f

Browse files
authored
Use aria-required instead of required on required form elements (#4023)
* sets aria-required attr instead of required * Create khaki-rules-breathe.md
1 parent e8ce7a6 commit 83c125f

File tree

8 files changed

+61
-4
lines changed

8 files changed

+61
-4
lines changed

.changeset/khaki-rules-breathe.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@primer/react": patch
3+
---
4+
5+
Use `aria-required` instead of `required` on required form elements
6+
7+
<!-- Changed components: TextInput, Textarea -->

src/TextInput/TextInput.features.stories.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ export const Large = () => (
8383
</Box>
8484
)
8585

86+
export const Required = () => (
87+
<Box as="form">
88+
<FormControl required>
89+
<FormControl.Label>Default label</FormControl.Label>
90+
<TextInput size="large" />
91+
</FormControl>
92+
</Box>
93+
)
94+
8695
export const WithLeadingVisual = () => (
8796
<Box as="form">
8897
<FormControl>

src/TextInput/TextInput.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
7878
variant: variantProp,
7979
// end deprecated props
8080
type = 'text',
81+
required,
8182
...inputProps
8283
},
8384
ref,
@@ -143,6 +144,7 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
143144
onFocus={handleInputFocus}
144145
onBlur={handleInputBlur}
145146
type={type}
147+
aria-required={required ? 'true' : 'false'}
146148
{...inputProps}
147149
data-component="input"
148150
/>

src/Textarea/Textarea.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
9292
<StyledTextarea
9393
value={value}
9494
resize={resize}
95-
required={required}
9695
aria-required={required ? 'true' : 'false'}
9796
aria-invalid={validationStatus === 'error' ? 'true' : 'false'}
9897
ref={ref}

src/__tests__/FormControl.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('FormControl', () => {
8282

8383
const input = getByRole('textbox')
8484

85-
expect(input.getAttribute('required')).not.toBeNull()
85+
expect(input).toHaveAttribute('aria-required', 'true')
8686
})
8787

8888
it('renders with a caption', () => {

src/__tests__/__snapshots__/Autocomplete.test.tsx.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ exports[`snapshots renders a custom empty state message 1`] = `
118118
aria-expanded={false}
119119
aria-haspopup="listbox"
120120
aria-owns="autocompleteId-listbox"
121+
aria-required="false"
121122
autoComplete="off"
122123
className="c2"
123124
data-component="input"
@@ -285,6 +286,7 @@ exports[`snapshots renders a loading state 1`] = `
285286
aria-expanded={false}
286287
aria-haspopup="listbox"
287288
aria-owns="autocompleteId-listbox"
289+
aria-required="false"
288290
autoComplete="off"
289291
className="c2"
290292
data-component="input"
@@ -503,6 +505,7 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] =
503505
aria-expanded={false}
504506
aria-haspopup="listbox"
505507
aria-owns="autocompleteId-listbox"
508+
aria-required="false"
506509
autoComplete="off"
507510
className="c2"
508511
data-component="input"
@@ -1273,6 +1276,7 @@ exports[`snapshots renders a multiselect input 1`] = `
12731276
aria-expanded={false}
12741277
aria-haspopup="listbox"
12751278
aria-owns="autocompleteId-listbox"
1279+
aria-required="false"
12761280
autoComplete="off"
12771281
className="c2"
12781282
data-component="input"
@@ -1946,6 +1950,7 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = `
19461950
aria-expanded={false}
19471951
aria-haspopup="listbox"
19481952
aria-owns="autocompleteId-listbox"
1953+
aria-required="false"
19491954
autoComplete="off"
19501955
className="c2"
19511956
data-component="input"
@@ -2751,6 +2756,7 @@ exports[`snapshots renders a single select input 1`] = `
27512756
aria-expanded={false}
27522757
aria-haspopup="listbox"
27532758
aria-owns="autocompleteId-listbox"
2759+
aria-required="false"
27542760
autoComplete="off"
27552761
className="c2"
27562762
data-component="input"
@@ -3775,6 +3781,7 @@ exports[`snapshots renders with an input value 1`] = `
37753781
aria-expanded={false}
37763782
aria-haspopup="listbox"
37773783
aria-owns="autocompleteId-listbox"
3784+
aria-required="false"
37783785
autoComplete="off"
37793786
className="c2"
37803787
data-component="input"

src/__tests__/__snapshots__/TextInput.test.tsx.snap

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ exports[`TextInput renders 1`] = `
112112
onClick={[Function]}
113113
>
114114
<input
115+
aria-required="false"
115116
className="c2"
116117
data-component="input"
117118
name="zipcode"
@@ -242,6 +243,7 @@ exports[`TextInput renders block 1`] = `
242243
onClick={[Function]}
243244
>
244245
<input
246+
aria-required="false"
245247
className="c2"
246248
data-component="input"
247249
name="zipcode"
@@ -364,6 +366,7 @@ exports[`TextInput renders consistently 1`] = `
364366
onClick={[Function]}
365367
>
366368
<input
369+
aria-required="false"
367370
className="c2"
368371
data-component="input"
369372
onBlur={[Function]}
@@ -486,6 +489,7 @@ exports[`TextInput renders contrast 1`] = `
486489
onClick={[Function]}
487490
>
488491
<input
492+
aria-required="false"
489493
className="c2"
490494
data-component="input"
491495
name="zipcode"
@@ -615,6 +619,7 @@ exports[`TextInput renders error 1`] = `
615619
onClick={[Function]}
616620
>
617621
<input
622+
aria-required="false"
618623
className="c2"
619624
data-component="input"
620625
name="zipcode"
@@ -744,6 +749,7 @@ exports[`TextInput renders large 1`] = `
744749
size="large"
745750
>
746751
<input
752+
aria-required="false"
747753
className="c2"
748754
data-component="input"
749755
name="zipcode"
@@ -892,6 +898,7 @@ exports[`TextInput renders leadingVisual 1`] = `
892898
</svg>
893899
</span>
894900
<input
901+
aria-required="false"
895902
className="c2"
896903
data-component="input"
897904
name="search"
@@ -1041,6 +1048,7 @@ exports[`TextInput renders leadingVisual 2`] = `
10411048
</svg>
10421049
</span>
10431050
<input
1051+
aria-required="false"
10441052
className="c2"
10451053
data-component="input"
10461054
name="search"
@@ -1171,6 +1179,7 @@ exports[`TextInput renders leadingVisual 3`] = `
11711179
</div>
11721180
</span>
11731181
<input
1182+
aria-required="false"
11741183
className="c2"
11751184
data-component="input"
11761185
name="search"
@@ -1301,6 +1310,7 @@ exports[`TextInput renders leadingVisual 4`] = `
13011310
</div>
13021311
</span>
13031312
<input
1313+
aria-required="false"
13041314
className="c2"
13051315
data-component="input"
13061316
name="search"
@@ -1425,6 +1435,7 @@ exports[`TextInput renders monospace 1`] = `
14251435
onClick={[Function]}
14261436
>
14271437
<input
1438+
aria-required="false"
14281439
className="c2"
14291440
data-component="input"
14301441
name="zipcode"
@@ -1547,6 +1558,7 @@ exports[`TextInput renders placeholder 1`] = `
15471558
onClick={[Function]}
15481559
>
15491560
<input
1561+
aria-required="false"
15501562
className="c2"
15511563
data-component="input"
15521564
name="zipcode"
@@ -1679,6 +1691,7 @@ exports[`TextInput renders small 1`] = `
16791691
size="small"
16801692
>
16811693
<input
1694+
aria-required="false"
16821695
className="c2"
16831696
data-component="input"
16841697
name="zipcode"
@@ -2295,6 +2308,7 @@ exports[`TextInput renders trailingAction icon button 1`] = `
22952308
onClick={[Function]}
22962309
>
22972310
<input
2311+
aria-required="false"
22982312
className="c2"
22992313
data-component="input"
23002314
name="search"
@@ -2734,6 +2748,7 @@ exports[`TextInput renders trailingAction text button 1`] = `
27342748
onClick={[Function]}
27352749
>
27362750
<input
2751+
aria-required="false"
27372752
className="c2"
27382753
data-component="input"
27392754
name="search"
@@ -3379,6 +3394,7 @@ exports[`TextInput renders trailingAction text button with a tooltip 1`] = `
33793394
onClick={[Function]}
33803395
>
33813396
<input
3397+
aria-required="false"
33823398
className="c2"
33833399
data-component="input"
33843400
name="search"
@@ -3531,6 +3547,7 @@ exports[`TextInput renders trailingVisual 1`] = `
35313547
onClick={[Function]}
35323548
>
35333549
<input
3550+
aria-required="false"
35343551
className="c2"
35353552
data-component="input"
35363553
name="search"
@@ -3680,6 +3697,7 @@ exports[`TextInput renders trailingVisual 2`] = `
36803697
onClick={[Function]}
36813698
>
36823699
<input
3700+
aria-required="false"
36833701
className="c2"
36843702
data-component="input"
36853703
name="search"
@@ -3829,6 +3847,7 @@ exports[`TextInput renders trailingVisual 3`] = `
38293847
onClick={[Function]}
38303848
>
38313849
<input
3850+
aria-required="false"
38323851
className="c2"
38333852
data-component="input"
38343853
name="search"
@@ -3959,6 +3978,7 @@ exports[`TextInput renders trailingVisual 4`] = `
39593978
onClick={[Function]}
39603979
>
39613980
<input
3981+
aria-required="false"
39623982
className="c2"
39633983
data-component="input"
39643984
name="search"
@@ -4112,6 +4132,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
41124132
onClick={[Function]}
41134133
>
41144134
<input
4135+
aria-required="false"
41154136
className="c2"
41164137
data-component="input"
41174138
onBlur={[Function]}
@@ -4334,6 +4355,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
43344355
</div>
43354356
</span>
43364357
<input
4358+
aria-required="false"
43374359
className="c4"
43384360
data-component="input"
43394361
onBlur={[Function]}
@@ -4512,6 +4534,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
45124534
onClick={[Function]}
45134535
>
45144536
<input
4537+
aria-required="false"
45154538
className="c2"
45164539
data-component="input"
45174540
onBlur={[Function]}
@@ -4774,6 +4797,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
47744797
</div>
47754798
</span>
47764799
<input
4800+
aria-required="false"
47774801
className="c5"
47784802
data-component="input"
47794803
onBlur={[Function]}
@@ -5036,6 +5060,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
50365060
</div>
50375061
</span>
50385062
<input
5063+
aria-required="false"
50395064
className="c5"
50405065
data-component="input"
50415066
onBlur={[Function]}
@@ -5298,6 +5323,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
52985323
</div>
52995324
</span>
53005325
<input
5326+
aria-required="false"
53015327
className="c5"
53025328
data-component="input"
53035329
onBlur={[Function]}
@@ -5485,6 +5511,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
54855511
onClick={[Function]}
54865512
>
54875513
<input
5514+
aria-required="false"
54885515
className="c2"
54895516
data-component="input"
54905517
onBlur={[Function]}
@@ -5747,6 +5774,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
57475774
</div>
57485775
</span>
57495776
<input
5777+
aria-required="false"
57505778
className="c4"
57515779
data-component="input"
57525780
onBlur={[Function]}
@@ -5965,6 +5993,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
59655993
onClick={[Function]}
59665994
>
59675995
<input
5996+
aria-required="false"
59685997
className="c2"
59695998
data-component="input"
59705999
onBlur={[Function]}
@@ -6276,6 +6305,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
62766305
</div>
62776306
</span>
62786307
<input
6308+
aria-required="false"
62796309
className="c5"
62806310
data-component="input"
62816311
onBlur={[Function]}
@@ -6578,6 +6608,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
65786608
</div>
65796609
</span>
65806610
<input
6611+
aria-required="false"
65816612
className="c5"
65826613
data-component="input"
65836614
onBlur={[Function]}
@@ -6887,6 +6918,7 @@ exports[`TextInput renders with a loading indicator 1`] = `
68876918
</div>
68886919
</span>
68896920
<input
6921+
aria-required="false"
68906922
className="c5"
68916923
data-component="input"
68926924
onBlur={[Function]}
@@ -7078,6 +7110,7 @@ exports[`TextInput should render a password input 1`] = `
70787110
onClick={[Function]}
70797111
>
70807112
<input
7113+
aria-required="false"
70817114
className="c2"
70827115
data-component="input"
70837116
name="password"

src/drafts/MarkdownEditor/MarkdownEditor.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,12 @@ describe('MarkdownEditor', () => {
213213

214214
it('does not require the textarea by default', async () => {
215215
const {getInput} = await render(<UncontrolledEditor />)
216-
expect(getInput()).not.toHaveAttribute('required')
216+
expect(getInput()).toHaveAttribute('aria-required', 'false')
217217
})
218218

219219
it('requires the textarea when required', async () => {
220220
const {getInput} = await render(<UncontrolledEditor required />)
221-
expect(getInput()).toHaveAttribute('required')
221+
expect(getInput()).toHaveAttribute('aria-required', 'true')
222222
})
223223

224224
it('does not render a placeholder by default', async () => {

0 commit comments

Comments
 (0)