Skip to content

Commit fa107af

Browse files
authored
Add basic validation docs for hooks (#5375)
1 parent d3a8f6e commit fa107af

File tree

8 files changed

+116
-44
lines changed

8 files changed

+116
-44
lines changed

packages/@react-aria/checkbox/docs/useCheckboxGroup.mdx

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ checkbox groups that can be styled as needed.
5454
* Checkbox groups are exposed to assistive technology via ARIA
5555
* Each checkbox is built with a native HTML `<input>` element, which can be optionally visually
5656
hidden to allow custom styling
57-
* Full support for browser features like form autofill
57+
* Full support for browser features like form autofill and validation
5858
* Keyboard focus management and cross browser normalization
5959
* Group and checkbox labeling support for assistive technology
6060

@@ -105,9 +105,9 @@ import {useCheckboxGroupState} from '@react-stately/checkbox';
105105
let CheckboxGroupContext = React.createContext(null);
106106

107107
function CheckboxGroup(props) {
108-
let {children, label, description, errorMessage} = props;
108+
let {children, label, description} = props;
109109
let state = useCheckboxGroupState(props);
110-
let {groupProps, labelProps, descriptionProps, errorMessageProps} = useCheckboxGroup(props, state);
110+
let {groupProps, labelProps, descriptionProps, errorMessageProps, isInvalid, validationErrors} = useCheckboxGroup(props, state);
111111

112112
return (
113113
<div {...groupProps}>
@@ -116,8 +116,8 @@ function CheckboxGroup(props) {
116116
{children}
117117
</CheckboxGroupContext.Provider>
118118
{description && <div {...descriptionProps} style={{fontSize: 12}}>{description}</div>}
119-
{errorMessage && state.isInvalid &&
120-
<div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{errorMessage}</div>
119+
{isInvalid &&
120+
<div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{validationErrors.join(' ')}</div>
121121
}
122122
</div>
123123
);
@@ -212,17 +212,46 @@ The `description` prop can be used to associate additional help text with a chec
212212
</CheckboxGroup>
213213
```
214214

215-
### Error message
215+
### Group validation
216216

217-
The `errorMessage` prop can be used to help the user fix a validation error. It should be combined with the `isInvalid` prop to
218-
semantically mark the checkbox group as invalid for assistive technologies.
217+
CheckboxGroup supports the `isRequired` prop to ensure the user selects at least one item, as well as custom client and server-side validation. Individual checkboxes also support validation, and errors from all checkboxes are aggregated at the group level. CheckboxGroup can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more.
218+
219+
When a CheckboxGroup has the `validationBehavior="native"` prop, validation errors block form submission. The `isRequired` prop at the `CheckboxGroup` level requires that at least one item is selected. To display validation errors, use the `validationErrors` and `errorMessageProps` returned by `useCheckboxGroup`. This allows you to render error messages from all of the above sources with consistent custom styles.
219220

220221
```tsx example
221-
<CheckboxGroup label="Favorite sports" errorMessage="Invalid selection of sports." isInvalid>
222-
<Checkbox value="soccer">Soccer</Checkbox>
223-
<Checkbox value="baseball">Baseball</Checkbox>
224-
<Checkbox value="basketball">Basketball</Checkbox>
225-
</CheckboxGroup>
222+
<form>
223+
<CheckboxGroup
224+
label="Sandwich condiments"
225+
name="condiments"
226+
/*- begin highlight -*/
227+
isRequired
228+
validationBehavior="native"
229+
/*- end highlight -*/
230+
>
231+
<Checkbox value="lettuce">Lettuce</Checkbox>
232+
<Checkbox value="tomato">Tomato</Checkbox>
233+
<Checkbox value="onion">Onion</Checkbox>
234+
<Checkbox value="sprouts">Sprouts</Checkbox>
235+
</CheckboxGroup>
236+
<input type="submit" style={{marginTop: 8}} />
237+
</form>
238+
```
239+
240+
### Individual Checkbox validation
241+
242+
To require that specific checkboxes are checked, set the `isRequired` prop at the `Checkbox` level instead of the `CheckboxGroup`. The following example shows how to require that all items are selected.
243+
244+
```tsx example
245+
<form>
246+
<CheckboxGroup label="Agree to the following" validationBehavior="native">
247+
{/*- begin highlight -*/}
248+
<Checkbox value="terms" isRequired>Terms and conditions</Checkbox>
249+
<Checkbox value="privacy" isRequired>Privacy policy</Checkbox>
250+
<Checkbox value="cookies" isRequired>Cookie policy</Checkbox>
251+
{/*- end highlight -*/}
252+
</CheckboxGroup>
253+
<input type="submit" style={{marginTop: 8}} />
254+
</form>
226255
```
227256

228257
### Disabled

packages/@react-aria/combobox/docs/useComboBox.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ A combo box can be built using the [&lt;datalist&gt;](https://developer.mozilla.
7474
* Virtual focus management for combo box list box option navigation
7575
* Hides elements outside the input and list box from assistive technology while the list box is open in a portal
7676
* Custom localized announcements for option focusing, filtering, and selection using an ARIA live region to work around VoiceOver bugs
77-
* Support for description and error message help text linked to the input via ARIA
77+
* Support for native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and server-side validation errors
7878

7979
Read our [blog post](../blog/building-a-combobox.html) for more details about the interactions and accessibility features implemented by `useComboBox`.
8080

packages/@react-aria/numberfield/docs/useNumberField.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ formatting options and can be styled as needed.
6161
* Follows the [spinbutton](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/) ARIA pattern
6262
* Works around bugs in VoiceOver with the spinbutton role
6363
* Uses an ARIA live region to ensure that value changes are announced
64-
* Support for description and error message help text linked to the input via ARIA
64+
* Support for native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and server-side validation errors
6565

6666
Read our [blog post](../blog/how-we-internationalized-our-numberfield.html) for more details about the interactions and internationalization support implemented by `useNumberField`.
6767

packages/@react-aria/radio/docs/useRadioGroup.mdx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ radio groups that can be styled as needed.
5555
* Radio groups are exposed to assistive technology via ARIA
5656
* Each radio is built with a native HTML `<input>` element, which can be optionally visually
5757
hidden to allow custom styling
58-
* Full support for browser features like form autofill
58+
* Full support for browser features like form autofill and validation
5959
* Keyboard focus management and cross browser normalization
6060
* Group and radio labeling support for assistive technology
6161

@@ -162,9 +162,9 @@ import {useFocusRing} from '@react-aria/focus';
162162
let RadioContext = React.createContext(null);
163163

164164
function RadioGroup(props) {
165-
let {children, label, description, errorMessage} = props;
165+
let {children, label, description} = props;
166166
let state = useRadioGroupState(props);
167-
let {radioGroupProps, labelProps, descriptionProps, errorMessageProps} = useRadioGroup(props, state);
167+
let {radioGroupProps, labelProps, descriptionProps, errorMessageProps, isInvalid, validationErrors} = useRadioGroup(props, state);
168168

169169
return (
170170
<div {...radioGroupProps}>
@@ -173,8 +173,8 @@ function RadioGroup(props) {
173173
{children}
174174
</RadioContext.Provider>
175175
{description && <div {...descriptionProps} style={{fontSize: 12}}>{description}</div>}
176-
{errorMessage && state.isInvalid &&
177-
<div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{errorMessage}</div>
176+
{isInvalid &&
177+
<div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{validationErrors.join(' ')}</div>
178178
}
179179
</div>
180180
)
@@ -293,16 +293,23 @@ The `description` prop can be used to associate additional help text with a radi
293293
</RadioGroup>
294294
```
295295

296-
### Error message
296+
### Validation
297297

298-
The `errorMessage` prop can be used to help the user fix a validation error. It should be combined with the `isInvalid` prop to
299-
semantically mark the radio group as invalid for assistive technologies.
298+
RadioGroup supports the `isRequired` prop to ensure the user selects an option, as well as custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more.
299+
300+
When a RadioGroup has the `validationBehavior="native"` prop, validation errors block form submission. To display validation errors, use the `validationErrors` and `errorMessageProps` returned by `useRadioGroup`. This allows you to render error messages from all of the above sources with consistent custom styles.
300301

301302
```tsx example
302-
<RadioGroup label="Favorite pet" errorMessage="Invalid pet selection." isInvalid>
303-
<Radio value="dogs">Dogs</Radio>
304-
<Radio value="cats">Cats</Radio>
305-
</RadioGroup>
303+
<form>
304+
{/*- begin highlight -*/}
305+
<RadioGroup label="Favorite pet" name="pet" isRequired validationBehavior="native">
306+
{/*- end highlight -*/}
307+
<Radio value="dogs">Dog</Radio>
308+
<Radio value="cats">Cat</Radio>
309+
<Radio value="dragon">Dragon</Radio>
310+
</RadioGroup>
311+
<input type="submit" style={{marginTop: 8}} />
312+
</form>
306313
```
307314

308315
### Disabled

packages/@react-aria/searchfield/docs/useSearchField.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ search fields that can be styled as needed.
5050
* Keyboard submit handling via the <Keyboard>Enter</Keyboard> key
5151
* Keyboard support for clearing the search field with the <Keyboard>Escape</Keyboard> key
5252
* Custom clear button support with internationalized label for accessibility
53-
* Support for description and error message help text linked to the input via ARIA
53+
* Support for native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and server-side validation errors
5454

5555
## Anatomy
5656

packages/@react-aria/select/docs/useSelect.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ select components that can be styled as needed without compromising on high qual
5858
* Support for disabled options
5959
* Support for sections
6060
* Labeling support for accessibility
61-
* Support for description and error message help text linked to the input via ARIA
61+
* Support for native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and server-side validation errors
6262
* Support for mouse, touch, and keyboard interactions
6363
* Tab stop focus management
6464
* Keyboard support for opening the listbox using the arrow keys, including automatically focusing

packages/@react-aria/textfield/docs/useTextField.mdx

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ allowing for custom styling.
4848
* Built with a native `<input>` or `<textarea>` element
4949
* Visual and ARIA labeling support
5050
* Change, clipboard, composition, selection, and input event support
51-
* Required and invalid states exposed to assistive technology via ARIA
51+
* Support for native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and server-side validation errors
5252
* Support for description and error message help text linked to the input via ARIA
5353

5454
## Anatomy
@@ -78,21 +78,17 @@ to identify the element to screen readers.
7878
import type {AriaTextFieldProps} from '@react-aria/textfield';
7979
import {useTextField} from '@react-aria/textfield';
8080

81-
interface TextFieldProps extends Omit<AriaTextFieldProps, 'errorMessage'> {
82-
errorMessage?: string
83-
}
84-
85-
function TextField(props: TextFieldProps) {
81+
function TextField(props: AriaTextFieldProps) {
8682
let {label} = props;
8783
let ref = React.useRef(null);
88-
let {labelProps, inputProps, descriptionProps, errorMessageProps} = useTextField(props, ref);
84+
let {labelProps, inputProps, descriptionProps, errorMessageProps, isInvalid, validationErrors} = useTextField(props, ref);
8985

9086
return (
9187
<div style={{display: 'flex', flexDirection: 'column', width: 200}}>
9288
<label {...labelProps}>{label}</label>
9389
<input {...inputProps} ref={ref} />
9490
{props.description && <div {...descriptionProps} style={{fontSize: 12}}>{props.description}</div>}
95-
{props.errorMessage && <div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{props.errorMessage}</div>}
91+
{isInvalid && <div {...errorMessageProps} style={{color: 'red', fontSize: 12}}>{validationErrors.join(' ')}</div>}
9692
</div>
9793
);
9894
}
@@ -165,16 +161,25 @@ The `description` prop can be used to associate additional help text with a text
165161
description="Enter an email for us to contact you about your order." />
166162
```
167163

168-
### Error message
164+
### Validation
165+
166+
useTextField supports HTML constraint validation props such as `isRequired`, `type="email"`, `minLength`, and `pattern`, as well as custom validation functions, realtime validation, and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more.
169167

170-
The `errorMessage` prop can be used to help the user fix a validation error. It should be combined with the `isInvalid` prop to
171-
semantically mark the input element as invalid for assistive technologies.
168+
When a TextField has the `validationBehavior="native"` prop, validation errors block form submission. To display validation errors, use the `validationErrors` and `errorMessageProps` returned by `useTextField`. This allows you to render error messages from all of the above sources with consistent custom styles.
172169

173170
```tsx example
174-
<TextField
175-
label="Email"
176-
isInvalid
177-
errorMessage="Please enter a valid email address." />
171+
<form>
172+
<TextField
173+
label="Email"
174+
name="email"
175+
/*- begin highlight -*/
176+
type="email"
177+
isRequired
178+
validationBehavior="native"
179+
/*- end highlight -*/
180+
/>
181+
<input type="submit" style={{marginTop: 8}} />
182+
</form>
178183
```
179184

180185
### Disabled

packages/dev/docs/pages/react-aria/forms.mdx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
77
OF ANY KIND, either express or implied. See the License for the specific language
88
governing permissions and limitations under the License. */}
99

10+
import sharedDocs from 'docs:@react-types/shared';
11+
import {TypeContext, InterfaceType} from '@react-spectrum/docs';
12+
1013
import {Layout} from '@react-spectrum/docs';
1114
export default Layout;
1215

@@ -500,3 +503,31 @@ function App() {
500503
);
501504
}
502505
```
506+
507+
## Hooks
508+
509+
If you're using React Aria hooks rather than components, native form validation can be enabled using the `validationBehavior="native"` prop. Each hook returns validation information which can be used to render error messages with custom styles.
510+
511+
```tsx
512+
let {isInvalid, validationErrors, validationDetails} = useTextField(props, ref);
513+
```
514+
515+
<TypeContext.Provider value={sharedDocs.links}>
516+
<InterfaceType properties={sharedDocs.exports.ValidationResult.properties} />
517+
</TypeContext.Provider>
518+
519+
Server errors can be provided using the `FormValidationContext` directly, or using the `Form` component from `react-aria-components` as described above.
520+
521+
```tsx
522+
import {FormValidationContext} from 'react-aria';
523+
524+
<FormValidationContext.Provider value={{username: 'This username is taken.'}}>
525+
<MyTextField
526+
name="username"
527+
isRequired
528+
validationBehavior="native" />
529+
{/* ... */}
530+
</FormValidationContext.Provider>
531+
```
532+
533+
See the [useTextField](useTextField.html) docs for an example of how to render validation errors.

0 commit comments

Comments
 (0)