4.1.0 • Published 2 years ago

@devseed-ui/form v4.1.0

Weekly downloads
45
License
MIT
Repository
github
Last release
2 years ago

@devseed-ui/form

A package to build custom forms. List of available components:

  • Form
  • FormGroup
  • FormGroupBody
  • FormGroupHeader
  • FormLabel
  • FormInput
  • FormCheckable
  • FormCheckableGroup
  • FormSwitch
  • FormSelect
  • FormTextarea
  • FormHelper
  • FormHelperCounter
  • FormHelperMessage
  • FormFieldset
  • FormFieldsetBody
  • FormFieldsetHeader
  • FormLegend
This component requires [collecticons](/collecticons) to be included.
You'll see strange characters (example �) in place of icons if collecticons is missing.

Example

<DevseedUiThemeProvider>
  <CollecticonsGlobalStyle />
  <Form>
    <FormFieldset>
      <FormFieldsetHeader>
        <FormLegend>Form legend</FormLegend>
        <Toolbar>
          <ToolbarIconButton useIcon="xmark--small">
            Close
          </ToolbarIconButton>
        </Toolbar>
      </FormFieldsetHeader>
      <FormFieldsetBody>
        <FormGroup>
          <FormGroupHeader>
            <FormLabel htmlFor="input-text-a">Form label</FormLabel>
            <Toolbar size="small">
              <ToolbarIconButton useIcon="circle-information">
                More information
              </ToolbarIconButton>
            </Toolbar>
          </FormGroupHeader>
          <FormGroupBody>
            <FormInput
              type="text"
              size="large"
              id="input-text-a"
              placeholder="This is a text input"
              invalid
            />
            <FormHelper>
              <div>
                <FormHelperMessage>
                  This is some help text.
                </FormHelperMessage>
                <FormHelperMessage invalid>
                  This is an error message.
                </FormHelperMessage>
              </div>
              <FormHelperCounter>0 / 80</FormHelperCounter>
            </FormHelper>
          </FormGroupBody>
        </FormGroup>

        <FormGroup>
          <FormGroupHeader>
            <FormLabel>Form label</FormLabel>
            <Toolbar size="small">
              <ToolbarLabel>Select</ToolbarLabel>
              <ToolbarButton>All</ToolbarButton>
              <ToolbarButton>None</ToolbarButton>
            </Toolbar>
          </FormGroupHeader>
          <FormGroupBody>
            <FormCheckableGroup>
              <FormCheckable
                checked={undefined}
                type="checkbox"
                name="checkbox-a"
                id="checkbox-a"
              >
                Checkbox A
              </FormCheckable>
              <FormCheckable
                checked={undefined}
                type="checkbox"
                name="checkbox-b"
                id="checkbox-b"
              >
                Checkbox B
              </FormCheckable>
            </FormCheckableGroup>
          </FormGroupBody>
        </FormGroup>

        <FormGroup>
          <FormGroupHeader>
            <FormLabel>Form label</FormLabel>
          </FormGroupHeader>
          <FormGroupBody>
            <FormCheckableGroup>
              <FormCheckable
                textPlacement="right"
                checked={undefined}
                type="radio"
                name="radio-a"
                id="radio-a1"
              >
                Radio A
              </FormCheckable>
              <FormCheckable
                textPlacement="right"
                checked={undefined}
                type="radio"
                name="radio-a"
                id="radio-a2"
              >
                Radio B
              </FormCheckable>
              <FormCheckable
                textPlacement="right"
                checked={undefined}
                type="radio"
                name="radio-a"
                id="radio-a3"
              >
                Radio C
              </FormCheckable>
              <FormCheckable
                textPlacement="right"
                checked={undefined}
                type="radio"
                name="radio-a"
                id="radio-a4"
              >
                Radio D
              </FormCheckable>
            </FormCheckableGroup>
          </FormGroupBody>
        </FormGroup>

        <FormFieldset>
          <FormFieldsetHeader>
            <FormLegend>Form legend</FormLegend>
            <Button
              variation="base-plain"
              size="small"
              hideText
              data-tip="This is a super helpful tool  tip."
            >
              Remove fieldset
            </Button>
          </FormFieldsetHeader>
          <FormFieldsetBody>
            <FormGroup>
              <FormGroupHeader>
                <FormLabel htmlFor="textarea-b">Form label</FormLabel>
              </FormGroupHeader>
              <FormGroupBody>
                <FormTextarea
                  size="large"
                  id="textarea-b"
                  placeholder="This is a textarea"
                />
                <FormHelper>
                  <FormHelperCounter>0 / 80</FormHelperCounter>
                </FormHelper>
              </FormGroupBody>
            </FormGroup>
          </FormFieldsetBody>
        </FormFieldset>

        <FormGroup>
          <FormGroupHeader>
            <FormLabel htmlFor="select-a" optional>
              Form label
            </FormLabel>
          </FormGroupHeader>
          <FormGroupBody>
            <FormSelect size="large" id="select-a">
              <option value="option-1">Option 1</option>
              <option value="option-2">Option 2</option>
              <option value="option-3">Option 3</option>
              <option value="option-4">Option 4</option>
            </FormSelect>
            <FormHelper>
              <FormHelperMessage>This is some help text.</FormHelperMessage>
            </FormHelper>
          </FormGroupBody>
        </FormGroup>

        <FormGroup>
          <FormGroupHeader>
            <FormLabel htmlFor="textarea-a">Form label</FormLabel>
          </FormGroupHeader>
          <FormGroupBody>
            <FormTextarea
              size="large"
              id="textarea-a"
              placeholder="This is a textarea"
              invalid
            />
            <FormHelper>
              <FormHelperMessage invalid>
                This is an error message.
              </FormHelperMessage>
            </FormHelper>
          </FormGroupBody>
        </FormGroup>
      </FormFieldsetBody>
    </FormFieldset>
  </Form>
</DevseedUiThemeProvider>

Usage

The following section explains the base structure of a form and how to use the different components.

Form

Form wrapper, should be the parent component in every form.

Form Groups

Except for some specific cases, the form elements shouldn't be used by themselves. They should be included in a form group with a header and a body. This allows for proper styling and adding companion components like for example a toolbar.

The normal form component structure is:

<FormGroup>
  <FormGroupHeader>
    <FormLabel>Form label</FormLabel>
  </FormGroupHeader>
  <FormGroupBody>
  </FormGroupBody>
</FormGroup>

The FormGroupHeader contains the FormLabel which for accessibility reasons should always be present. If the label is not desired, it can be hidden using <FormGroupHeader isHidden>.
The FormGroupBody is where the components can be added. Thus, the structure for a simple text input would be:

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader>
        <FormLabel htmlFor="input-text1">Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormInput type="text" id="input-text1" />
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

This is the base structure and should be used with all input types

Default Properties

The following properties are available for all the elements.

rows:
- Prop name: "name"
  Type: "string"
  Description: "String to be used as HTML property `name`"
  Default value: "N/A"
- Prop name: "id"
  Type: "string"
  Description: "String to be used as HTML property `id`"
  Default value: "N/A"
- Prop name: "title"
  Type: "string"
  Description: "String to be used as HTML property `title`"
  Default value: "N/A"

FormInput

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader>
        <FormLabel htmlFor="input-text2">Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormInput type="text" id="input-text2" />
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "type"
  Type: "string"
  Description: "Determines the type of input to render. One of (number | text | password)"
- Prop name: "invalid"
  Type: "boolean"
  Description: "Whether or not the field is invalid. Will render with the danger color"
  Default value: "false"
- Prop name: "stressed"
  Type: "boolean"
  Description: "Animates the field with the shake animation"
  Default value: "false"
- Prop name: "size"
  Type: "string"
  Description: "Size of the input field. One of (small | medium | large)"
  Default value: "medium"

FormTextarea

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader isHidden>
        <FormLabel htmlFor="textarea2">Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormTextarea id="textarea2" placeholder="This is a textarea" />
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "invalid"
  Type: "boolean"
  Description: "Whether or not the field is invalid. Will render with the danger color"
  Default value: "false"
- Prop name: "stressed"
  Type: "boolean"
  Description: "Animates the field with the shake animation"
  Default value: "false"
- Prop name: "size"
  Type: "string"
  Description: "Size of the input field. One of (small | medium | large)"
  Default value: "medium"

FormCheckable

Element to build radio or checkboxes. Wrapping them in FormCheckableGroup ensures a consistent display

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader>
        <FormLabel>Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormCheckableGroup>
          <FormCheckable
            checked={undefined}
            type="checkbox"
            name="checkbox2"
            id="checkbox2"
          >
            Checkbox A
          </FormCheckable>
          <FormCheckable
            checked={undefined}
            type="checkbox"
            name="checkbox3"
            id="checkbox3"
          >
            Checkbox B
          </FormCheckable>
        </FormCheckableGroup>
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "type"
  Type: "string"
  Description: "Determines the type of input to render, can be one of `checkbox` or `radio`"
  Default value: "N/A"
- Prop name: "checked"
  Type: "boolean"
  Description: "Whether or not the element is checked"
  Default value: "N/A"
- Prop name: "onChange"
  Type: "string"
  Description: "A function to execute on change"
  Default value: "N/A"
- Prop name: "children"
  Type: "string"
  Description: "Text content"
  Default value: "N/A"
- Prop name: "textPlacement"
  Type: "string"
  Description: "Where to position the text. `left` or `right` of the control"
  Default value: "right"
- Prop name: "hideText"
  Type: "boolean"
  Description: "Whether to visually hide the checkable text"
  Default value: "false"

FormSwitch

The FormSwitch has the same basic behavior as a single checkbox but with a different presentation. It is used mostly for binary type options.

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader isHidden>
        <FormLabel>Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormSwitch
          name="switch4"
          title="Toggle layer on/off"
          checked={true}
          onChange={() => {}}
        >
          Show all options
        </FormSwitch>
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "checked"
  Type: "boolean"
  Description: "Whether or not the element is checked"
  Default value: "N/A"
- Prop name: "onChange"
  Type: "string"
  Description: "A function to execute on change"
  Default value: "N/A"
- Prop name: "children"
  Type: "string"
  Description: "Text content"
  Default value: "N/A"
- Prop name: "textPlacement"
  Type: "string"
  Description: "Where to position the text. `left` or `right` of the control"
  Default value: "right"
- Prop name: "hideText"
  Type: "boolean"
  Description: "Whether to visually hide the switch text"
  Default value: "false"

FormSelect

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader isHidden>
        <FormLabel>Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormSelect id="select4">
          <option value="option-1">Option 1</option>
          <option value="option-2">Option 2</option>
          <option value="option-3">Option 3</option>
          <option value="option-4">Option 4</option>
        </FormSelect>
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "invalid"
  Type: "boolean"
  Description: "Whether or not the field is invalid. Will render with the danger color"
  Default value: "false"
- Prop name: "stressed"
  Type: "boolean"
  Description: "Animates the field with the shake animation"
  Default value: "false"
- Prop name: "size"
  Type: "string"
  Description: "Size of the input field. One of (small | medium | large)"
  Default value: "medium"

Helpers

The form helpers are used to display messages below the fields. There are 2 helpers available which should always be wrapped by the parent FromHelper and placed inside the FormGroupBody.

FormHelperMessage

Displays a simple message on the left side. Using the property invalid will display it using the theme danger color.

<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader>
        <FormLabel htmlFor="input-text5">Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormInput type="text" id="input-text5" />
        <FormHelper>
          <div>
            <FormHelperMessage>
              This is some help text.
            </FormHelperMessage>
            <FormHelperMessage invalid>
              This is an error message.
            </FormHelperMessage>
          </div>
        </FormHelper>
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "invalid"
  Type: "boolean"
  Description: "Whether or not the field is invalid. Will render with the danger color"
  Default value: "false"
- Prop name: "stressed"
  Type: "boolean"
  Description: "Animates the field with the shake animation"
  Default value: "false"
- Prop name: "children"
  Type: "node"
  Description: "The message content"
  Default value: ""

When using multiple FormHelperMessage (one for help and another for an error for example), they should be wrapped in an extra div to ensure they're correctly positioned.

<FormHelper>
  <div>
    <FormHelperMessage>
      This is some help text.
    </FormHelperMessage>
    <FormHelperMessage invalid>
      This is an error message.
    </FormHelperMessage>
  </div>
</FormHelper>

FormHelperCounter

Used to display a counter on the right side of the field, this is useful to indicate that the field has a maximum character count. The color of the text will change to warning when reaching the warnAt value and will change to danger when over the max.

state: {value: ''}
---
<DevseedUiThemeProvider>
  <Form>
    <FormGroup>
      <FormGroupHeader>
        <FormLabel htmlFor="input-text6">Form label</FormLabel>
      </FormGroupHeader>
      <FormGroupBody>
        <FormInput
          type="text"
          id="input-text6"
          value={state.value}
          onChange={(e) => setState({value: e.target.value})}
          placeholder='Type in something'
          />
        <FormHelper>
          <FormHelperCounter max={50} value={state.value.length} warnAt={35}/>
        </FormHelper>
      </FormGroupBody>
    </FormGroup>
  </Form>
</DevseedUiThemeProvider>

Properties

rows:
- Prop name: "max"
  Type: "Number"
  Description: "Maximum value allowed for the counter, after which the danger color is applied"
  Default value: ""
- Prop name: "warnAt"
  Type: "Number"
  Description: "Value after which the warning color is applied"
  Default value: "90% of max"
- Prop name: "value"
  Type: "Number"
  Description: "Current counter value"
  Default value: ""

FormFieldset

A form fieldset is useful to contain other form elements and must follow a structure similar to the form groups.

<FormFieldset>
  <FormFieldsetHeader>
    <FormLegend>Form legend</FormLegend>
  </FormFieldsetHeader>
  <FormFieldsetBody>
  </FormFieldsetBody>
</FormFieldset>

Example of a fieldset with am input field.

<DevseedUiThemeProvider>
  <CollecticonsGlobalStyle />
  <Form>
    <FormFieldset>
      <FormFieldsetHeader>
        <FormLegend>Form legend</FormLegend>
      </FormFieldsetHeader>
      <FormFieldsetBody>
        <FormGroup>
          <FormGroupHeader>
            <FormLabel htmlFor="input-text7">Form label</FormLabel>
          </FormGroupHeader>
          <FormGroupBody>
            <FormInput type="text" id="input-text7" />
          </FormGroupBody>
        </FormGroup>
      </FormFieldsetBody>
    </FormFieldset>
  </Form>
</DevseedUiThemeProvider>

Toolbar

Both the FormFieldset and FormGroup support the inclusion of a Toolbar in the header. This is useful to provide contextual actions for the fields.

The toolbar is part of a separate ui package, but will pair well with the form elements.

import {
  Toolbar,
  ToolbarButton,
  ToolbarLabel,
  ToolbarIconButton,
} from '@devseed-ui/toolbar';

Example:

<DevseedUiThemeProvider>
  <CollecticonsGlobalStyle />
  <Form>
    <FormFieldset>
      <FormFieldsetHeader>
        <FormLegend>Form legend</FormLegend>
        <Toolbar>
          <ToolbarIconButton useIcon="xmark--small">
            Close
          </ToolbarIconButton>
        </Toolbar>
      </FormFieldsetHeader>
      <FormFieldsetBody>
        <FormGroup>
          <FormGroupHeader>
            <FormLabel>Form label</FormLabel>
            <Toolbar size="small">
              <ToolbarLabel>Select</ToolbarLabel>
              <ToolbarButton>All</ToolbarButton>
              <ToolbarButton>None</ToolbarButton>
            </Toolbar>
          </FormGroupHeader>
          <FormGroupBody>
            <FormCheckableGroup>
              <FormCheckable
                checked={undefined}
                type="checkbox"
                name="checkbox8"
                id="checkbox8"
              >
                Checkbox A
              </FormCheckable>
              <FormCheckable
                checked={undefined}
                type="checkbox"
                name="checkbox9"
                id="checkbox9"
              >
                Checkbox B
              </FormCheckable>
            </FormCheckableGroup>
          </FormGroupBody>
        </FormGroup>
      </FormFieldsetBody>
    </FormFieldset>
  </Form>
</DevseedUiThemeProvider>

Forms with Formik

If you are using Formik, you can use the library components by passing it through the as prop like so

import { Formik, Field, Form, ErrorMessage } from "formik"
import {
  FormFieldset,
  FormFieldsetBody,
  FormGroup,
  FormGroupHeader,
  FormGroupBody,
  FormInput,
  FormLabel,
  FormHelper,
  FormHelperMessage,
} from "@devseed-ui/form"


const InputGroup = ({ id, label, placeholder, helperMessage }) => (
  <FormGroup>
    <FormGroupHeader>
      <FormLabel htmlFor={id}>{label}</FormLabel>
    </FormGroupHeader>
    <FormGroupBody>
      <Field
        as={FormInput}
        type="text"
        id={id}
        name={id}
        placeholder={placeholder}
      />
      <FormHelper>
        {helperMessage && (
          <FormHelperMessage>{helperMessage}</FormHelperMessage>
        )}
        <FormHelperMessage as={ErrorMessage} name={id} />
      </FormHelper>
    </FormGroupBody>
  </FormGroup>
)
4.1.0

2 years ago

4.0.0

2 years ago

4.0.2

2 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

1.0.0-rc.0

3 years ago

0.12.1

4 years ago

0.12.0

4 years ago

0.11.4

4 years ago

0.11.5

4 years ago

0.11.2

4 years ago

0.11.1

4 years ago

0.11.0

4 years ago

0.10.2

4 years ago

0.10.0

4 years ago

0.9.1

4 years ago