@devseed-ui/form

    1.0.4 • Public • Published

    @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>
    )
    

    Install

    npm i @devseed-ui/form

    DownloadsWeekly Downloads

    55

    Version

    1.0.4

    License

    MIT

    Unpacked Size

    160 kB

    Total Files

    43

    Last publish

    Collaborators

    • avatar
    • avatar
    • avatar