diff --git a/packages/@react-aria/datepicker/src/useDatePicker.ts b/packages/@react-aria/datepicker/src/useDatePicker.ts index ae7776c1187..7cdd4744a96 100644 --- a/packages/@react-aria/datepicker/src/useDatePicker.ts +++ b/packages/@react-aria/datepicker/src/useDatePicker.ts @@ -164,7 +164,7 @@ export function useDatePicker(props: AriaDatePickerProps isDateUnavailable: props.isDateUnavailable, defaultFocusedValue: state.dateValue ? undefined : props.placeholderValue, isInvalid: state.isInvalid, - errorMessage: typeof props.errorMessage === 'function' ? props.errorMessage(state.displayValidation) : props.errorMessage + errorMessage: typeof props.errorMessage === 'function' ? props.errorMessage(state.displayValidation) : (props.errorMessage || state.displayValidation.validationErrors.join(' ')) }, isInvalid, validationErrors, diff --git a/packages/@react-aria/datepicker/src/useDateRangePicker.ts b/packages/@react-aria/datepicker/src/useDateRangePicker.ts index ead9c7254d0..ce41f051fa0 100644 --- a/packages/@react-aria/datepicker/src/useDateRangePicker.ts +++ b/packages/@react-aria/datepicker/src/useDateRangePicker.ts @@ -213,7 +213,7 @@ export function useDateRangePicker(props: AriaDateRangePick allowsNonContiguousRanges: props.allowsNonContiguousRanges, defaultFocusedValue: state.dateRange ? undefined : props.placeholderValue, isInvalid: state.isInvalid, - errorMessage: typeof props.errorMessage === 'function' ? props.errorMessage(state.displayValidation) : props.errorMessage + errorMessage: typeof props.errorMessage === 'function' ? props.errorMessage(state.displayValidation) : (props.errorMessage || state.displayValidation.validationErrors.join(' ')) }, isInvalid, validationErrors, diff --git a/packages/@react-aria/textfield/src/useTextField.ts b/packages/@react-aria/textfield/src/useTextField.ts index d3b9cc91c61..5aa016b8c6f 100644 --- a/packages/@react-aria/textfield/src/useTextField.ts +++ b/packages/@react-aria/textfield/src/useTextField.ts @@ -17,10 +17,11 @@ import { HTMLAttributes, LabelHTMLAttributes, ReactDOM, - RefObject + RefObject, + useEffect } from 'react'; import {DOMAttributes, ValidationResult} from '@react-types/shared'; -import {filterDOMProps, mergeProps, useFormReset} from '@react-aria/utils'; +import {filterDOMProps, getOwnerWindow, mergeProps, useFormReset} from '@react-aria/utils'; import {useControlledState} from '@react-stately/utils'; import {useField} from '@react-aria/label'; import {useFocusable} from '@react-aria/focus'; @@ -138,6 +139,24 @@ export function useTextField { + // This works around a React/Chrome bug that prevents textarea elements from validating when controlled. + // We prevent React from updating defaultValue (i.e. children) of textarea when `value` changes, + // which causes Chrome to skip validation. Only updating `value` is ok in our case since our + // textareas are always controlled. React is planning on removing this synchronization in a + // future major version. + // https://github.com/facebook/react/issues/19474 + // https://github.com/facebook/react/issues/11896 + if (ref.current instanceof getOwnerWindow(ref.current).HTMLTextAreaElement) { + let input = ref.current; + Object.defineProperty(input, 'defaultValue', { + get: () => input.value, + set: () => {}, + configurable: true + }); + } + }, [ref]); + return { labelProps, inputProps: mergeProps( diff --git a/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx b/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx index 91b47024278..e23d4c329f9 100644 --- a/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx +++ b/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx @@ -266,41 +266,34 @@ function AsyncLoadingExample() { ``` ## Validation -SearchAutocomplete can display a validation state to communicate to the user whether the current value is valid or invalid. -Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the SearchAutocomplete via the `validationState` prop. -The example below illustrates how one would validate if the user has entered a valid email into the SearchAutocomplete. -```tsx example -function Example() { - let [value, setValue] = React.useState('me@email.com'); - let isValid = React.useMemo(() => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value), [value]); +SearchAutocomplete supports the `isRequired` prop to ensure the user enters a value, 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. - let options = [ - {id: 1, email: 'fake@email.com'}, - {id: 2, email: 'anotherfake@email.com'}, - {id: 3, email: 'bob@email.com'}, - {id: 4, email: 'joe@email.com'}, - {id: 5, email: 'yourEmail@email.com'}, - {id: 6, email: 'valid@email.com'}, - {id: 7, email: 'spam@email.com'}, - {id: 8, email: 'newsletter@email.com'}, - {id: 9, email: 'subscribe@email.com'} - ]; +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the search field or submits the form. - return ( - - {item => {item.email}} - - ); -} +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + Aardvark + Cat + Dog + Kangaroo + Panda + Snake + + + + + +
``` +By default, `SearchAutocomplete` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Custom Filtering By default, SearchAutocomplete uses a string "contains" filtering strategy when deciding what items to display in the dropdown menu. This filtering strategy can be overwritten by filtering the list of items yourself and passing the filtered list to the SearchAutocomplete via the `items` prop. diff --git a/packages/@react-spectrum/checkbox/docs/CheckboxGroup.mdx b/packages/@react-spectrum/checkbox/docs/CheckboxGroup.mdx index 4afca923dbb..67dd8eba6b7 100644 --- a/packages/@react-spectrum/checkbox/docs/CheckboxGroup.mdx +++ b/packages/@react-spectrum/checkbox/docs/CheckboxGroup.mdx @@ -156,54 +156,51 @@ function Example() { ## Validation -CheckboxGroups can display a validation state to communicate to the user if the current value is invalid. -Implement your own validation logic in your app and set the `isInvalid` prop to either -the `CheckboxGroup` or an individual `Checkbox` to mark it as invalid. +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. ### Group validation -If the group as a whole is invalid, for example if the user must choose at least one option but failed -to do so, then pass `isInvalid` to the `CheckboxGroup`. - -The following example shows how to require that at least one option is selected. It sets the `isInvalid` -prop when no options are selected and removes it otherwise. +The `isRequired` prop at the `CheckboxGroup` level requires that at least one item is selected. When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. ```tsx example -function Example() { - let [selected, setSelected] = React.useState([]); - - return ( - - Lettuce - Tomato - Onion - Sprouts - - ); -} +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + Lettuce + Tomato + Onion + Sprouts + + + + + +
``` -### Individual Checkbox validation +By default, `CheckboxGroup` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. -If an individual checkbox is invalid, for example if the user must select a particular option but failed -to do so, then pass `isInvalid` to the `Checkbox` element instead. +### Individual Checkbox validation -The following example shows how to require that all items are selected. It uses the `isRequired` prop on each individual `Checkbox` -element to indicate to assistive technology that every checkbox is required. By default, the `isRequired` prop on the `CheckboxGroup` only -indicates that the group is required, not any individual option. In addition, `isInvalid` is set on each checkbox that is not yet checked. +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. ```tsx example -function Example() { - let [selected, setSelected] = React.useState([]); - - return ( - - Terms and conditions - Privacy policy - Cookie policy - - ); -} +
+ + {/*- begin highlight -*/} + Terms and conditions + Privacy policy + Cookie policy + {/*- end highlight -*/} + + + + + +
``` ## Props diff --git a/packages/@react-spectrum/color/docs/ColorField.mdx b/packages/@react-spectrum/color/docs/ColorField.mdx index 0fec7fb73c4..1c0574524f9 100644 --- a/packages/@react-spectrum/color/docs/ColorField.mdx +++ b/packages/@react-spectrum/color/docs/ColorField.mdx @@ -103,31 +103,26 @@ When the `necessityIndicator` prop is set to `"label"`, a localized string will ## Validation -ColorField can display a validation state to communicate to the user whether the current value is valid or invalid. -Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the ColorField via the `validationState` prop. +ColorField supports the `isRequired` prop to ensure the user enters a value, 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. -The example below illustrates how one would validate if the user has entered a red color. In it, -the function is used to parse the -initial color from a hexadecimal string so that `value`'s type remains consistent. +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the color field or submits the form. ```tsx example -function Example() { - let [value, setValue] = React.useState(parseColor('#e73623')); - let isValid = React.useMemo(() => { - return value && value.getChannelValue('red') > value.getChannelValue('green') && value.getChannelValue('red') > value.getChannelValue('blue'); - }, [value]); - - return ( - - ); -} +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + ``` +By default, `ColorField` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Props @@ -172,23 +167,10 @@ left most edge of the ColorField and "end" refers to the right most edge. For ri Both a description and an error message can be supplied to a ColorField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. ```tsx example -function Example() { - let [value, setValue] = React.useState(parseColor('#e73623')); - let isValid = React.useMemo(() => { - return value && value.getChannelValue('red') > value.getChannelValue('green') && value.getChannelValue('red') > value.getChannelValue('blue'); - }, [value]); - - return ( - - ); -} + + + + ``` ### Contextual help diff --git a/packages/@react-spectrum/combobox/docs/ComboBox.mdx b/packages/@react-spectrum/combobox/docs/ComboBox.mdx index abf03bcc809..819beb0fe73 100644 --- a/packages/@react-spectrum/combobox/docs/ComboBox.mdx +++ b/packages/@react-spectrum/combobox/docs/ComboBox.mdx @@ -659,42 +659,34 @@ function AsyncLoadingExample() { ``` ## Validation -ComboBox can display a validation state to communicate to the user whether the current value is valid or invalid. -Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the ComboBox via the `validationState` prop. -The example below illustrates how one would validate if the user has entered a valid email into the ComboBox. -```tsx example -function Example() { - let [value, setValue] = React.useState('me@email.com'); - let isValid = React.useMemo(() => /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value), [value]); +ComboBox supports the `isRequired` prop to ensure the user enters a value, 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. - let options = [ - {id: 1, email: 'fake@email.com'}, - {id: 2, email: 'anotherfake@email.com'}, - {id: 3, email: 'bob@email.com'}, - {id: 4, email: 'joe@email.com'}, - {id: 5, email: 'yourEmail@email.com'}, - {id: 6, email: 'valid@email.com'}, - {id: 7, email: 'spam@email.com'}, - {id: 8, email: 'newsletter@email.com'}, - {id: 9, email: 'subscribe@email.com'} - ]; +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the combo box or submits the form. - return ( - - {item => {item.email}} - - ); -} +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + Aardvark + Cat + Dog + Kangaroo + Panda + Snake + + + + + +
``` +By default, `ComboBox` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Custom Filtering By default, ComboBox uses a string "contains" filtering strategy when deciding what items to display in the dropdown menu. This filtering strategy can be overwritten by filtering the list of items yourself and passing the filtered list to the ComboBox via the `items` prop. diff --git a/packages/@react-spectrum/datepicker/docs/DateField.mdx b/packages/@react-spectrum/datepicker/docs/DateField.mdx index eff54da9d35..2fd0361b3e4 100644 --- a/packages/@react-spectrum/datepicker/docs/DateField.mdx +++ b/packages/@react-spectrum/datepicker/docs/DateField.mdx @@ -221,43 +221,77 @@ function Example() { ## Validation -`DateField` can display a validation state to communicate to the user whether the current value is valid or invalid. Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` via the `validationState` prop. The `errorMessage` prop can be used to communicate errors to the user. +DateField supports the `isRequired` prop to ensure the user enters a value, as well as minimum and maximum values, and custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more. + +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the date field or submits the form. + +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + +``` + +By default, `DateField` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + +### Minimum and maximum values + +The `minValue` and `maxValue` props can also be used to ensure the value is within a specific range. This example only accepts dates after today. + +```tsx example +import {today} from '@internationalized/date'; + +
+ + + + + + +``` + +### Custom validation + +The `validate` function can be used to perform custom validation logic. It receives the current field value, and should return a string or array of strings representing one or more error messages if the value is invalid. This example validates that the selected date is a weekday and not a weekend according to the current locale. ```tsx example -import {today, isWeekend} from '@internationalized/date'; +import {isWeekend} from '@internationalized/date'; import {useLocale} from '@adobe/react-spectrum'; function Example() { - let [date, setDate] = React.useState(today(getLocalTimeZone())); let {locale} = useLocale(); return ( - +
+ date && isWeekend(date, locale) ? 'We are closed on weekends.' : null} + /*- end highlight -*/ + defaultValue={parseDate('2023-10-28')} /> + + + + + ); } ``` -### Minimum and maximum values - -The `minValue` and `maxValue` props can also be used to perform builtin validation. This displays an invalid state if the user enters an invalid date. - -This example only accepts dates after today. - -```tsx example - -``` - ## Props @@ -296,7 +330,14 @@ By default, the label is positioned above the `DateField`. The `labelPosition` p ### Help text [View guidelines](https://spectrum.adobe.com/page/help-text/#Usage-guidelines) -Both a description and an error message can be supplied to a DateField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. See the [Validation](#validation) section above for an example. +Both a description and an error message can be supplied to a DateField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. + +```tsx example + + + + +``` `DateField` also supports displaying the expected date format for the user's locale automatically using the `showFormatHelpText` prop. diff --git a/packages/@react-spectrum/datepicker/docs/DatePicker.mdx b/packages/@react-spectrum/datepicker/docs/DatePicker.mdx index 0507fd79335..31a470af4a6 100644 --- a/packages/@react-spectrum/datepicker/docs/DatePicker.mdx +++ b/packages/@react-spectrum/datepicker/docs/DatePicker.mdx @@ -220,46 +220,51 @@ function Example() { ## Validation -`DatePicker` can display a validation state to communicate to the user whether the current value is valid or invalid. Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` via the `validationState` prop. The `errorMessage` prop can be used to communicate errors to the user. +DatePicker supports the `isRequired` prop to ensure the user enters a value, as well as minimum and maximum values, and custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more. -This example validates that the selected date is a weekday and not a weekend according to the current locale. +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the date picker or submits the form. ```tsx example -import {today, isWeekend} from '@internationalized/date'; -import {useLocale} from '@adobe/react-spectrum'; - -function Example() { - let [date, setDate] = React.useState(today(getLocalTimeZone())); - let {locale} = useLocale(); - - return ( - - ); -} +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + ``` -### Minimum and maximum values +By default, `DatePicker` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. -The `minValue` and `maxValue` props can also be used to perform builtin validation. This prevents the user from selecting dates outside the valid range in the calendar, and displays an invalid state if the user enters an invalid date into the date field. +### Minimum and maximum values -This example only accepts dates after today. +The `minValue` and `maxValue` props can also be used to ensure the value is within a specific range. This example only accepts dates after today. ```tsx example - +import {today} from '@internationalized/date'; + +
+ + + + + + ``` + ### Unavailable dates -`DatePicker` supports marking certain dates as _unavailable_. These dates cannot be selected by the user and are displayed with a crossed out appearance in the calendar. In the date field, an invalid state is displayed if a user enters an unavailable date. The `isDateUnavailable` prop accepts a callback that is called to evaluate whether a date is unavailable. +`DatePicker` supports marking certain dates as _unavailable_. These dates cannot be selected by the user and are displayed with a crossed out appearance in the calendar. In the date field, an invalid state is displayed if a user enters an unavailable date. The `isDateUnavailable` prop accepts a callback that is called to evaluate whether each visible date is unavailable. This example includes multiple unavailable date ranges, e.g. dates when no appointments are available. In addition, all weekends are unavailable. The `minValue` prop is also used to prevent selecting dates before today. @@ -276,9 +281,45 @@ function Example() { ]; let {locale} = useLocale(); - let isDateUnavailable = (date) => isWeekend(date, locale) || disabledRanges.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0); + return ( + isWeekend(date, locale) || disabledRanges.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0)} + /*- end highlight -*/ + validationBehavior="native" /> + ); +} +``` + +### Custom validation + +The `validate` function can be used to perform custom validation logic. It receives the current date value, and should return a string or array of strings representing one or more error messages if the value is invalid. + +This example validates that the selected date is a weekday and not a weekend according to the current locale. + +```tsx example +import {isWeekend} from '@internationalized/date'; +import {useLocale} from '@adobe/react-spectrum'; + +function Example() { + let {locale} = useLocale(); - return + return ( +
+ date && isWeekend(date, locale) ? 'We are closed on weekends.' : null} + /*- end highlight -*/ + defaultValue={parseDate('2023-10-28')} /> + + + + + + ); } ``` @@ -320,7 +361,14 @@ By default, the label is positioned above the `DatePicker`. The `labelPosition` ### Help text [View guidelines](https://spectrum.adobe.com/page/help-text/#Usage-guidelines) -Both a description and an error message can be supplied to a DatePicker. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. See the [Validation](#validation) section above for an example. +Both a description and an error message can be supplied to a DatePicker. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. + +```tsx example + + + + +``` `DatePicker` also supports displaying the expected date format for the user's locale automatically using the `showFormatHelpText` prop. diff --git a/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx b/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx index 329735441c8..9d584d5aee5 100644 --- a/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx +++ b/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx @@ -240,50 +240,77 @@ function Example() { ## Validation -`DateRangePicker` can display a validation state to communicate to the user whether the current value is valid or invalid. Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` via the `validationState` prop. The `errorMessage` prop can be used to communicate errors to the user. +DateRangePicker supports the `isRequired` prop to ensure the user enters a value, as well as minimum and maximum values, and custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more. -This example validates that the start and end dates of the selected range are within the same month. +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the date range picker or submits the form. ```tsx example -import {today, isSameMonth} from '@internationalized/date'; +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + +``` -function Example() { - let [range, setRange] = React.useState({ - start: today(getLocalTimeZone()), - end: today(getLocalTimeZone()).add({weeks: 1}) - }); +By default, `DateRangePicker` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. - return ( - - ); -} +### Minimum and maximum values + +The `minValue` and `maxValue` props can also be used to ensure the value is within a specific range. `DateRangePicker` also validates that the end date is after the start date. This example only accepts dates after today. + +```tsx example +import {today} from '@internationalized/date'; + +
+ + + + + + ``` -### Minimum and maximum values +### Custom validation -The `minValue` and `maxValue` props can also be used to perform builtin validation. This prevents the user from selecting dates outside the valid range in the calendar, and displays an invalid state if the user enters an invalid date into the date field. +The `validate` function can be used to perform custom validation logic. It receives the current date range, and should return a string or array of strings representing one or more error messages if the value is invalid. -This example only accepts dates after today. +This example validates that the selected date range is a maximum of 1 week in duration. ```tsx example - +
+ range?.end.compare(range.start) > 7 ? 'Maximum stay duration is 1 week.' : null} + /*- end highlight -*/ + defaultValue={{ + start: today(getLocalTimeZone()), + end: today(getLocalTimeZone()).add({ weeks: 1, days: 3 }) + }} /> + + + + + ``` ### Unavailable dates -`DateRangePicker` supports marking certain dates as _unavailable_. These dates cannot be selected by the user and are displayed with a crossed out appearance in the calendar. The `isDateUnavailable` prop accepts a callback that is called to evaluate whether a date is unavailable. +`DateRangePicker` supports marking certain dates as _unavailable_. These dates cannot be selected by the user and are displayed with a crossed out appearance in the calendar. The `isDateUnavailable` prop accepts a callback that is called to evaluate whether each visible date is unavailable. Note that by default, users may not select non-contiguous ranges, i.e. ranges that contain unavailable dates within them. Once a start date is selected in the calendar, enabled dates will be restricted to subsequent dates until an unavailable date is hit. While this is handled automatically in the calendar, additional validation logic must be provided to ensure an invalid state is displayed in the date field. This can be achieved using the `validationState` prop. See [below](#non-contiguous-ranges) for an example of how to allow non-contiguous ranges. @@ -300,18 +327,15 @@ function Example() { [now.add({days: 23}), now.add({days: 24})], ]; - let isDateUnavailable = (date) => disabledRanges.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0); - let [value, setValue] = React.useState(null); - let isInvalid = value && disabledRanges.some(interval => value.end.compare(interval[0]) >= 0 && value.start.compare(interval[1]) <= 0); - return ( + /*- begin highlight -*/ + isDateUnavailable={date => disabledRanges.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0)} + validate={value => disabledRanges.some(interval => value && value.end.compare(interval[0]) >= 0 && value.start.compare(interval[1]) <= 0) ? 'Selected date range may not include unavailable dates.' : null} + /*- end highlight -*/ + validationBehavior="native" /> ); } ``` @@ -371,7 +395,14 @@ By default, the label is positioned above the `DateRangePicker`. The `labelPosit ### Help text [View guidelines](https://spectrum.adobe.com/page/help-text/#Usage-guidelines) -Both a description and an error message can be supplied to a `DateRangePicker`. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. See the [Validation](#validation) section above for an example. +Both a description and an error message can be supplied to a `DateRangePicker`. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. + +```tsx example + + + + +``` `DateRangePicker` also supports displaying the expected date format for the user's locale automatically using the `showFormatHelpText` prop. diff --git a/packages/@react-spectrum/datepicker/docs/TimeField.mdx b/packages/@react-spectrum/datepicker/docs/TimeField.mdx index 6111cbed16d..4b8eeb26d54 100644 --- a/packages/@react-spectrum/datepicker/docs/TimeField.mdx +++ b/packages/@react-spectrum/datepicker/docs/TimeField.mdx @@ -165,38 +165,65 @@ function Example() { ## Validation -`TimeField` can display a validation state to communicate to the user whether the current value is valid or invalid. Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` via the `validationState` prop. The `errorMessage` prop can be used to communicate errors to the user. +TimeField supports the `isRequired` prop to ensure the user enters a value, as well as minimum and maximum values, and custom client and server-side validation. It can also be integrated with other form libraries. See the [Forms](forms.html) guide to learn more. -This example validates that the selected time is on a 15 minute increment. +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the time field or submits the form. ```tsx example -function Example() { - let [time, setTime] = React.useState(new Time(9, 15)); - - return ( - - ); -} +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + ``` +By default, `TimeField` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ### Minimum and maximum values -The `minValue` and `maxValue` props can also be used to perform builtin validation. This displays an invalid state if the user enters an invalid time into the time field. +The `minValue` and `maxValue` props can also be used to ensure the value is within a specific range. This example only accepts times between 9 AM and 5 PM. + +```tsx example +
+ + + + + + +``` + +### Custom validation -This example only accepts times between 9 AM and 5 PM. +The `validate` function can be used to perform custom validation logic. It receives the current field value, and should return a string or array of strings representing one or more error messages if the value is invalid. + +This example validates that the selected time is on a 15 minute increment. ```tsx example - +
+ time?.minute % 15 !== 0 ? 'Meetings start every 15 minutes.' : null} + /*- end highlight -*/ + defaultValue={new Time(9, 25)} /> + + + + + ``` ## Props @@ -237,7 +264,14 @@ By default, the label is positioned above the `TimeField`. The `labelPosition` p ### Help text [View guidelines](https://spectrum.adobe.com/page/help-text/#Usage-guidelines) -Both a description and an error message can be supplied to a TimeField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. See the [Validation](#validation) section above for an example. +Both a description and an error message can be supplied to a TimeField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. + +```tsx example + + + + +``` ### Contextual help diff --git a/packages/@react-spectrum/form/docs/Form.mdx b/packages/@react-spectrum/form/docs/Form.mdx index 1b9e6408ff3..7d6fd3e5fae 100644 --- a/packages/@react-spectrum/form/docs/Form.mdx +++ b/packages/@react-spectrum/form/docs/Form.mdx @@ -78,6 +78,35 @@ technology as a form landmark region to which assistive technology can navigate. ``` +## Validation + +React Spectrum supports native HTML constraint validation with customizable UI, custom validation functions, realtime validation, and integration with server-side validation errors. The `Form` component facilitates server-side validation by providing error messages to the fields within it. + +To provide validation errors, the `validationErrors` prop should be set to an object that maps each field's `name` prop to a string or array of strings representing one or more errors. These are displayed to the user as soon as the `validationErrors` prop is set, and cleared after the user modifies each field's value. + +```tsx example +
+ + +``` + +See the [Forms](forms.html) guide to learn more about form validation in React Spectrum, including client-side validation, and integration with other frameworks and libraries. + +### Validation behavior + +By default, validation errors are displayed to the user in realtime as the value is edited, and do not block form submission. To enable native HTML form validation and prevent form submission when fields are invalid, set the `validationBehavior` prop to `"native"`. + +```tsx example +import {ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ + + + + + +``` ## Props diff --git a/packages/@react-spectrum/numberfield/docs/NumberField.mdx b/packages/@react-spectrum/numberfield/docs/NumberField.mdx index bde6edaedfd..ad8e04346d7 100644 --- a/packages/@react-spectrum/numberfield/docs/NumberField.mdx +++ b/packages/@react-spectrum/numberfield/docs/NumberField.mdx @@ -267,26 +267,26 @@ function Example() { ## Validation -NumberFields can display a validation state to communicate to the user whether the current value is valid or invalid. -Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the NumberField via the `validationState` prop. +NumberField supports the `isRequired` prop to ensure the user enters a value, 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. -The example below illustrates how one would validate if the user has entered a [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz) number into the NumberField. -```tsx example -function Example() { - let [value, setValue] = React.useState(15); - let isValid = React.useMemo(() => value % 3 === 0 && value % 5 === 0, [value]); +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the number field or submits the form. - return ( - - ); -} +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + ``` +By default, `NumberField` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Props diff --git a/packages/@react-spectrum/picker/docs/Picker.mdx b/packages/@react-spectrum/picker/docs/Picker.mdx index c31bc325582..d0e72330c4d 100644 --- a/packages/@react-spectrum/picker/docs/Picker.mdx +++ b/packages/@react-spectrum/picker/docs/Picker.mdx @@ -351,6 +351,35 @@ function AsyncLoadingExample() { } ``` +## Validation + +Picker 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. + +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. + +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + Aardvark + Cat + Dog + Kangaroo + Panda + Snake + + + + + +
+``` + +By default, `Picker` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Props diff --git a/packages/@react-spectrum/radio/docs/RadioGroup.mdx b/packages/@react-spectrum/radio/docs/RadioGroup.mdx index 1e52fbe21f0..2cf61a1d937 100644 --- a/packages/@react-spectrum/radio/docs/RadioGroup.mdx +++ b/packages/@react-spectrum/radio/docs/RadioGroup.mdx @@ -149,16 +149,30 @@ function Example() { ## Validation -RadioGroups can display a validation state to communicate to the user if the current value is invalid. -Implement your own validation logic in your app and set the `isInvalid` prop accordingly. +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. + +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. ```tsx example - - Wizard - Dragon - +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + Dog + Cat + Dragon + + + + + +
``` +By default, `RadioGroup` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## RadioGroup props diff --git a/packages/@react-spectrum/searchfield/docs/SearchField.mdx b/packages/@react-spectrum/searchfield/docs/SearchField.mdx index 248eb40a24f..4da71beeaac 100644 --- a/packages/@react-spectrum/searchfield/docs/SearchField.mdx +++ b/packages/@react-spectrum/searchfield/docs/SearchField.mdx @@ -139,6 +139,28 @@ function Example() { } ``` +## Validation + +SearchField supports native HTML [constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation) props such as `isRequired`, `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. + +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the search field or submits the form. + +```tsx example +import {Form, ButtonGroup, Button} from '@adobe/react-spectrum'; + +
+ {/*- begin highlight -*/} + + {/*- end highlight -*/} + + + + + +``` + +By default, `SearchField` displays default validation messages provided by the browser. See [Customizing error messages](forms.html#customizing-error-messages) in the Forms guide to learn how to provide your own custom errors. + ## Props @@ -177,25 +199,13 @@ By default, the label is positioned above the SearchField. The `labelPosition` p ### Help text [View guidelines](https://spectrum.adobe.com/page/help-text/#Usage-guidelines) -Both a description and an error message can be supplied to a ComboBox. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. +Both a description and an error message can be supplied to a SearchField. The description is always visible unless the `validationState` is “invalid” and an error message is provided. The error message can be used to help the user fix their input quickly and should be specific to the detected error. All strings should be localized. ```tsx example -function Example() { - let [value, setValue] = React.useState('0'); - let isValid = React.useMemo(() => /^\d$/.test(value), [value]); - - return ( - - ); -} + + + + ``` ### Contextual help diff --git a/packages/@react-spectrum/textfield/docs/TextArea.mdx b/packages/@react-spectrum/textfield/docs/TextArea.mdx index 200bb953318..db7c8191295 100644 --- a/packages/@react-spectrum/textfield/docs/TextArea.mdx +++ b/packages/@react-spectrum/textfield/docs/TextArea.mdx @@ -122,25 +122,26 @@ function Example() { ## Validation -TextAreas can display a validation state to communicate to the user whether the current value is valid or invalid. -Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the TextArea via the `validationState` prop. +TextArea supports native HTML [constraint validation](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation) props such as `isRequired` and `minLength`, 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. -The example below illustrates how one would validate if the user entered more than 20 characters into the TextArea. -```tsx example -function Example() { - let [value, setValue] = React.useState('Lorem ipsum dolor sit'); - let isValid = React.useMemo(() => value.length <= 20, [value]); +When the [Form](Form.html) component has the `validationBehavior="native"` prop, validation errors block form submission and are displayed as help text automatically. Errors are displayed when the user blurs the text area or submits the form. - return ( -