Skip to main content

Forms

Creating forms can be done using the Form, FormSection and FormRow components.

Form is a top-level container which renders a native <form> element and provides utilities for displaying a title and description, as well as managing the space between FormSection.

FormSection helps in rendering sections of a form, which group together multiple form fields. It can optionally render a title and description.

FormRow manages the horizontal layout of individual fields.

All these components are implemented in terms of the lower level layout components (namely Stack and Columns) and can be freely mixed and matched to create complex layout as needed.

Let's see a basic example:

<Form>
<FormSection>
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
</Form>

This form has a single section with two fields.

tip

It's good practice use FormSection to group fields together - even in case of a single section - in order to achieve consistent layouts.

Let's add a title and description to the form:

Sign-upWe will ask you some data in order to sign you up
<Form
title="Sign-up"
description="We will ask you some data in order to sign you up"
>
<FormSection>
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
</Form>

Forms are generally quite useless without a way of submitting them. The Form component provides a way of rendering a standard submit button:

Sign-upWe will ask you some data in order to sign you up
<Form
title="Sign-up"
description="We will ask you some data in order to sign you up"
submitButton={{
onPress: () => window.alert("Submitted!"),
label: "Sign up",
}}
>
<FormSection>
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
</Form>

In case we need to, we can also add a secondary button next to the submit button:

Sign-upWe will ask you some data in order to sign you up
<Form
title="Sign-up"
description="We will ask you some data in order to sign you up"
submitButton={{
onPress: () => window.alert("Submitted!"),
label: "Sign up",
}}
secondaryButton={{
onPress: () => window.alert("Canceled!"),
label: "Never mind",
}}
>
<FormSection>
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
</Form>

Let's add a few more sections to the form, this time adding some titles and descriptions:

Sign-upWe will ask you some data in order to sign you up
Personal information
AddressWe need this data for invoicing purposes
Tell us more about you
EUR
%
Select a value
1
4
10
What's your main income source?
<Form
title="Sign-up"
description="We will ask you some data in order to sign you up"
>
<FormSection title="Personal information">
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
<FormSection
title="Address"
description="We need this data for invoicing purposes"
>
<FormRow>
<ExampleTextField label="Street" />
<ExampleTextField label="Number" />
</FormRow>
<FormRow>
<ExampleTextField label="City" />
</FormRow>
<FormRow>
<ExampleTextField label="Country" />
</FormRow>
</FormSection>
<FormSection title="Tell us more about you">
<FormRow>
<ExampleNumberField
label="Average income"
kind="currency"
currency="EUR"
/>
<ExampleNumberField
label="% of income spent on candies"
kind="percentage"
/>
</FormRow>
<FormRow>
<ExampleSelectField
label="Select your gender"
options={[
{
label: "Male",
value: "M",
},
{
label: "Female",
value: "F",
},
{
label: "Other",
value: "O",
},
]}
/>
</FormRow>
<FormRow>
<ExampleSliderField
initialValue={4}
label="How would you rate yourself from 1 to 10?"
minValue={1}
maxValue={10}
/>
</FormRow>
<FormRow>
<ExampleRadioGroupField
label={"What's your main income source?"}
options={[
{
label: "Working",
value: "W",
},
{
label: "Inheritance",
value: "I",
},
{
label: "Other",
value: "O",
},
]}
/>
</FormRow>
</FormSection>
</Form>

The form looks good, but in some cases we may want to customize the width of single fields. By default, FormRow makes all fields in a row of the same width, filling the available space.

This can be customized by wrapping a field in a Column component. For example, let's make the number take only 1/5 of the space, so that the street name has more room. Similarly, let's also make the city and the country narrower, to better convey the expected length of such fields:

Sign-upWe will ask you some data in order to sign you up
Personal information
,
AddressWe need this data for invoicing purposes
Tell us more about you
EUR
%
Select a value
1
4
10
What's your main income source?
<Form
title="Sign-up"
description="We will ask you some data in order to sign you up"
>
<FormSection title="Personal information">
<FormRow>
<ExampleTextField label="First name" />
<ExampleTextField label="Last name" />
</FormRow>
</FormSection>
,
<FormSection
title="Address"
description="We need this data for invoicing purposes"
>
<FormRow>
<ExampleTextField label="Street" />
<Column width="1/5">
<ExampleTextField label="Number" />
</Column>
</FormRow>
<FormRow>
<Column width="1/2">
<ExampleTextField label="City" />
</Column>
</FormRow>
<FormRow>
<Column width="1/2">
<ExampleTextField label="Country" />
</Column>
</FormRow>
</FormSection>
<FormSection title="Tell us more about you">
<FormRow>
<ExampleNumberField
label="Average income"
kind="currency"
currency="EUR"
/>
<ExampleNumberField
label="% of income spent on candies"
kind="percentage"
/>
</FormRow>
<FormRow>
<Column width="1/2">
<ExampleSelectField
label="Select your gender"
options={[
{
label: "Male",
value: "M",
},
{
label: "Female",
value: "F",
},
{
label: "Other",
value: "O",
},
]}
/>
</Column>
</FormRow>
<FormRow>
<ExampleSliderField
initialValue={4}
label="How would you rate yourself from 1 to 10?"
minValue={1}
maxValue={10}
/>
</FormRow>
<FormRow>
<ExampleRadioGroupField
label={"What's your main income source?"}
options={[
{
label: "Working",
value: "W",
},
{
label: "Inheritance",
value: "I",
},
{
label: "Other",
value: "O",
},
]}
/>
</FormRow>
</FormSection>
</Form>

This API may look familiar and it's not by coincidence. The FormRow component is a thin wrapper around the Columns layout component, which sets the default spacing between fields and the collapse behavior (try resizing the window and you'll see form rows automatically collapse on small screens).