@stackup/inputs

React components for creating data-driven forms.

Usage no npm install needed!

<script type="module">
  import stackupInputs from 'https://cdn.skypack.dev/@stackup/inputs';
</script>

README

@stackup/inputs

Build Version Size License

A set of helpful input components that take the burden out of building forms with React.

This library depends on @stackup/form to manage the state of form values.

Components

Checkbox

Manages the state of a boolean value using a checkbox.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<Checkbox
  label="I agree"
  help="Did you read all 7,000 lines?"
  field={useField(form, "confirmation")}
/>

Props

Name Type Required Description
field FormField<boolean> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

CheckboxItem

Manages an array of values, represented by checkboxes.

In addition to the props listed below, this component accepts all props for an HTML input.

Note that this component will not render error messages. For that, you'll want to wrap your checkboxes in a FieldSet.

Example

<FieldSet legend="Sport" field={useField(form, "sport")}>
  <CheckboxItem
    label="Soccer"
    value={{ name: "Soccer" }}
    field={useField(form, "sport")}
  />
  <CheckboxItem
    label="Baseball"
    value={{ name: "Baseball" }}
    field={useField(form, "sport")}
  />
</FieldSet>

Props

Name Type Required Description
value Value Toggle the inclusion of this value in the array.
field FormField<Value[]> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

FieldSet

Fields that are composed of multiple components (e.g. Radio and CheckboxItem) should always be rendered within a fieldset.

If an error is associated with the field, it will be rendered within the fieldset, rather than on a Radio or CheckboxItem.

Example

<FieldSet legend="Sport" field={useField(form, "sport")}>
  <Radio
    label="Soccer"
    value={{ name: "Soccer" }}
    field={useField(form, "sport")}
  />
  <Radio
    label="Baseball"
    value={{ name: "Baseball" }}
    field={useField(form, "sport")}
  />
</FieldSet>

Props

Name Type Required Description
field FormField<any> See @stackup/form
legend ReactNode Content to appear in the legend
help ReactNode Extra help info
children ReactNode Content that should appear inside the fieldset
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
className string An additional class name for the fieldset
legendClassName string An additional class name for the legend
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error

FileInput

Renders an <input type="file" />.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<FileInput label="Image" field={useField(form, "image")} />

Props

Name Type Required Description
field FormField<File> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

FileListInput

Renders an <input type="file" multiple />.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<FileListInput label="Images" field={useField(form, "images")} />

Props

Name Type Required Description
field FormField<FileList> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

Input

Renders an <input />, which whatever type you provide.

The value of this input will always be a string, but you should use a validation library such as @stackup/validate to parse and validate the entry before submission.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<Input type="email" label="Email" field={useField(form, "email")} />

Props

Name Type Required Description
type InputType
field FormField<string> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

Radio

Renders an <input type="radio" /> and manages the state of any type of value.

Note that this component will not render error messages. For that, you'll want to wrap your radio options in a FieldSet.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<FieldSet legend="Sport" field={useField(form, "sport")}>
  <Radio
    label="Soccer"
    value={{ name: "Soccer" }}
    field={useField(form, "sport")}
  />
  <Radio
    label="Baseball"
    value={{ name: "Baseball" }}
    field={useField(form, "sport")}
  />
</FieldSet>

Props

Name Type Required Description
value Value The value of the option to be selected
field FormField<Value> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLInputElement> A ref to the input element

Select

Renders a <select /> tag with whatever options you provide.

You can provide a placeholder, which will render a disabled option with a blank value.

In addition to the props listed below, this component accepts all props for an HTML select.

Example

<Select
  label="Sport"
  placeholder="Choose a sport"
  field={useField(form, "sport")}
>
  <option value="baseball">Baseball</option>
  <option value="soccer">Soccer</option>
</Select>

Props

Name Type Required Description
placeholder string
field FormField<string> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLSelectElement> A ref to the input element

Switch

Renders a <button /> to toggle the state of a boolean value.

You can style this element with CSS by selecting the [aria-checked] value.

In addition to the props listed below, this component accepts all props for an HTML button.

Example

<Switch type="enabled" label="Show preview" field={useField(form, "enabled")} />

Props

Name Type Required Description
field FormField<boolean> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLButtonElement> A ref to the input element

TextArea

Renders a <textarea />.

In addition to the props listed below, this component accepts all props for an HTML input.

Example

<TextArea type="comment" label="Comment" field={useField(form, "comment")} />

Props

Name Type Required Description
field FormField<string> See @stackup/form
label ReactNode Content to appear in the label
help ReactNode Extra help info that will be rendered within the label
variant string \| boolean \| FieldVariant[] Variant class name to append to all elements
prepend ReactNode Content to render before the input
append ReactNode Content to render after the input
className string An additional class name for the field
inputClassName string An additional class name for the input
labelClassName string An additional class name for the label
helpClassName string An additional class name for the help
errorClassName string An additional class name for the error
innerRef Ref<HTMLTextAreaElement> A ref to the input element

ThemeProvider

Render a ThemeProvider at the top of your component tree to provide a global theme.

See createTheme for an example of how to define your theme.

Example

<ThemeProvider value={theme}>
  <App />
</ThemeProvider>

Utilities

concat

Concatenate multiple class names.

concat("field", touched && error && "field--invalid");

createTheme

Create a new theme. This can be used in combination with the ThemeProvider to apply class names to fields.

export const theme = createTheme({
  field: props => {
    return concat(
      "field",
      props.touched && props.error && "field--invalid",
      ...props.types.map(type => `field--${type}`),
      ...props.variants.map(variant => variant && `field--${variant}`)
    );
  }
});

formatDateTime

Convert ISO-8601 to input[type=datetime-local]. This can be used to populate the initial value for your inputs.

When given an invalid value, this function will throw an error.

formatDateTime("2020-07-08T16:30:00.000Z");

formatTime

Convert ISO-8601 to input[type=time]. This can be used to populate the initial value for your inputs.

When given an invalid value, this function will throw an error.

formatTime("08:28:00Z");

formatNumber

Convert a number to input[type=number]. This can be used to populate the initial value for your inputs.

When given an invalid value, this function will throw an error.

formatNumber(0);

parseDateTime

Convert input[type=datetime-local] to ISO-8601. This can be used to parse and validate information entered by the user.

When given an invalid value, this function will return undefined.

parseDateTime("2020-07-08T12:30");

parseTime

Convert input[type=time] to ISO-8601. This can be used to parse and validate information entered by the user.

When given an invalid value, this function will return undefined.

parseTime("04:28");

parseNumber

Convert input[type=number] to a number. This can be used to parse and validate information entered by the user.

When given an invalid value, this function will return undefined.

parseNumber("1");