Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions packages/@react-spectrum/form/docs/Form.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
<!-- Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. -->

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-spectrum/form';
import {HeaderInfo, PropTable} from '@react-spectrum/docs';
import packageData from '../package.json';

```jsx import
import {Checkbox} from '@react-spectrum/checkbox';
import {Form} from '@react-spectrum/form';
import {Radio, RadioGroup} from '@react-spectrum/radio';
import {TextField} from '@react-spectrum/textfield';
```

# Form

<p>{docs.exports.Form.description}</p>

<HeaderInfo
packageData={packageData}
componentNames={['Form']} />

## Example

```tsx example
<h3 id="label-1">Login</h3>
<Form width={400} aria-labelledby="label-1">
<TextField label="Email" placeholder="abc@adobe.com" />
<TextField label="Password" placeholder="1234" />
<Checkbox>Remember me</Checkbox>
</Form>
```

## Content

Form accepts one or more children to render as its form elements. Label alignment, positioning, and other [properties](#visual-options)
are set on the Form itself and propagated to its children to generate a cohesive design. To override these top level Form props on individual children,
set them directly on the child instead.

```tsx example
<h3 id="label-2">Sign Up</h3>
<Form width={400} aria-labelledby="label-2" isRequired necessityIndicator="label">
<TextField label="Name" placeholder="Bob Doe" />
<TextField label="Email" placeholder="abc@adobe.com" />
<TextField label="Address" placeholder="123 Any Street" isRequired={false} />
</Form>
```

### Accessibility

As per [W3 Form guidelines](https://www.w3.org/TR/wai-aria-practices/examples/landmarks/form.html), the controls provided to the form should
use native host semantics (`button`, `input`, `select`, `textarea`) whenever possible. React Spectrum components such as Button, TextField, and TextArea
all satisfy this criteria.

## Labeling

### Accessibility

A label should be provided to the Form by adding either the `aria-label` or `aria-labelledby` prop, so that the element will be identified to assistive
technology as a form landmark region to which assistive technology can navigate to.

```tsx example
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this example provide that isn't covered in a previous example? Maybe the prior examples shouldn't have a label so this shows something new?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeahhhhh, I was torn between having all of my examples follow aria guidelines by having the external label or just having this one. Maybe I should get rid of this one? Other opinions welcome

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this example can be removed since it is so similar to the first one you have. Curious to hear others opinions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaning towards keeping this example to keep things contextual and to keep everything accessible.

<h3 id="label-3">Personal Information</h3>
<Form width={400} aria-labelledby="label-3">
<TextField label="First Name" placeholder="Bob" />
<TextField label="Last Name" placeholder="Dole" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
<Radio value="dragons">Dragons</Radio>
</RadioGroup>
</Form>
```


## Props

<PropTable component={docs.exports.Form} links={docs.links} />

## Visual Options

### Label Position and Label Alignment

```tsx example
<Form labelPosition="top" labelAlign="start" aria-label="Form example: label position=top, label alignment=start " width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form labelPosition="top" labelAlign="end" aria-label="Form example: label position=top, label alignment=end" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form labelPosition="side" labelAlign="start" aria-label="Form example: label position=side, label alignment=start" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form labelPosition="side" labelAlign="end" aria-label="Form example: label position=side, label alignment=end" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```

### Quiet

```tsx example
<Form isQuiet aria-label="Form example: isQuiet" width={400}>
<TextField label="Name" placeholder="John Smith" />
<TextField label="Address" placeholder="123 Any Street" />
</Form>
```

### Emphasized

```tsx example
<Form isEmphasized aria-label="Form example: isEmphasized" width={400}>
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```

### Disabled

```tsx example
<Form isDisabled aria-label="Form example: isDisabled" width={400}>
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```

### Required and Necessity Indicator

```tsx example
<Form necessityIndicator="label" aria-label="Form example: optional with necessityIndicator=label" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form isRequired necessityIndicator="label" aria-label="Form example: isRequired with necessityIndicator=label" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form isRequired necessityIndicator="icon" aria-label="Form example: isRequired with necessityIndicator=icon" width={400} >
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```

### Read Only

```tsx example
<Form isReadOnly aria-label="Form example: isReadOnly" width={400}>
<TextField label="Name" value="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```

### Validation State

```tsx example
<Form validationState="invalid" aria-label="Form example: validationState=invalid" width={400} marginBottom="20px">
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>

<Form validationState="valid" aria-label="Form example: validationState=valid" width={400}>
<TextField label="Name" placeholder="John Smith" />
<RadioGroup label="Favorite pet" name="favorite-pet-group">
<Radio value="dogs">Dogs</Radio>
<Radio value="cats">Cats</Radio>
</RadioGroup>
</Form>
```
3 changes: 3 additions & 0 deletions packages/@react-spectrum/form/src/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@ function Form(props: SpectrumFormProps, ref: DOMRef<HTMLFormElement>) {
);
}

/**
* Form provides unified structure, alignment, and styling for a user's form fields.
*/
const _Form = React.forwardRef(Form);
export {_Form as Form};
3 changes: 1 addition & 2 deletions packages/@react-types/checkbox/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export interface CheckboxProps extends CheckboxBase {

export interface SpectrumCheckboxProps extends CheckboxProps, DOMProps, StyleProps {
/**
* By default, checkboxes are not emphasized (gray).
* This prop sets the emphasized style (blue) which provides visual prominence.
* This prop sets the emphasized style which provides visual prominence.
*/
isEmphasized?: boolean
}
10 changes: 10 additions & 0 deletions packages/@react-types/form/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,21 @@ import {DOMProps, SpectrumLabelableProps, StyleProps, ValidationState} from '@re
import {ReactElement} from 'react';

export interface SpectrumFormProps extends DOMProps, StyleProps, SpectrumLabelableProps {
/** The contents of the Form. */
children: ReactElement<SpectrumLabelableProps> | ReactElement<SpectrumLabelableProps>[],
/** Whether the Form elements are displayed with their quiet style. */
isQuiet?: boolean,
/** Whether the Form elements are rendered with their emphasized style. */
isEmphasized?: boolean,
/** Whether the Form elements are disabled. */
isDisabled?: boolean,
/** Whether user input is required on each of the Form elements before Form submission. */
isRequired?: boolean,
/** Whether the Form elements can be selected but not changed by the user. */
isReadOnly?: boolean,
/**
* Whether the Form elements should display their "valid" or "invalid" visual styling.
* @default "valid"
*/
validationState?: ValidationState
}
3 changes: 1 addition & 2 deletions packages/@react-types/switch/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import {DOMProps, StyleProps} from '@react-types/shared';
export type SwitchProps = CheckboxBase;
export interface SpectrumSwitchProps extends SwitchProps, DOMProps, StyleProps {
/**
* By default, switches are not emphasized (gray).
* This prop sets the emphasized style (blue) which provides visual prominence.
* This prop sets the emphasized style which provides visual prominence.
* @default "false"
*/
isEmphasized?: boolean
Expand Down