Form
A native form that consolidates server-style field errors and lays out its field and action regions with consistent rhythm.
Show codeHide code
Installation
import { Form, FormActions, FormBody } from "@makeplane/propel/components/form";Usage
import { Button } from "@makeplane/propel/components/button";
import {
CheckboxGroupField,
CheckboxGroupFieldOption,
} from "@makeplane/propel/components/checkbox-group-field";
import { Form, FormActions, FormBody } from "@makeplane/propel/components/form";
import { InputField } from "@makeplane/propel/components/input-field";
import {
RadioGroupField,
RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";
import { SelectField } from "@makeplane/propel/components/select-field";
import { SwitchField } from "@makeplane/propel/components/switch-field";
import * as React from "react";
const SERVER_TYPES = [
{ label: "General purpose", value: "general" },
{ label: "Compute optimized", value: "compute" },
{ label: "Memory optimized", value: "memory" },
];
type LaunchServerValues = {
allowedProtocols: string[];
homepage: string;
restartOnFailure: boolean;
serverType: string;
storageType: string;
};
export default function BasicDemo() {
const [homepage, setHomepage] = React.useState("https://example.com");
const [errors, setErrors] = React.useState<Record<string, string | string[]>>({});
return (
<Form<LaunchServerValues>
errors={errors}
onFormSubmit={(values) => {
if (values.homepage.includes("example.com")) {
setErrors({ homepage: "The example domain is not allowed." });
return;
}
setErrors({});
}}
>
<FormBody layout="single">
<InputField
size="lg"
orientation="vertical"
name="homepage"
label="Homepage"
type="url"
required
placeholder="https://plane.so"
value={homepage}
onValueChange={(nextHomepage) => {
setHomepage(nextHomepage);
if (errors.homepage) {
setErrors({});
}
}}
/>
<SelectField
name="serverType"
label="Server type"
size="lg"
options={SERVER_TYPES}
defaultValue="general"
required
description="Select the resource profile for this server."
/>
<RadioGroupField
name="storageType"
label="Storage type"
size="lg"
density="comfortable"
defaultValue="ssd"
required
>
<RadioGroupFieldOption value="ssd" label="SSD" />
<RadioGroupFieldOption value="hdd" label="HDD" />
</RadioGroupField>
<CheckboxGroupField
name="allowedProtocols"
label="Allowed protocols"
size="lg"
density="comfortable"
defaultValue={["https"]}
>
<CheckboxGroupFieldOption value="http" label="HTTP" />
<CheckboxGroupFieldOption value="https" label="HTTPS" />
<CheckboxGroupFieldOption value="ssh" label="SSH" />
</CheckboxGroupField>
<SwitchField
name="restartOnFailure"
label="Restart on failure"
switchSize="md"
size="lg"
defaultChecked
/>
</FormBody>
<FormActions layout="inline">
<Button stretch="auto" type="submit" variant="secondary" size="sm" label="Submit" />
</FormActions>
</Form>
);
}Examples
Async validation
The submit button holds its pending state while a server-style check resolves, then surfaces any returned error on the matching field.
Show codeHide code
Server function
Submitting through the form action with React.useActionState maps the action’s returned errors back onto the field by name.
Show codeHide code
Schema validation
One schema-style parse consolidates per-field errors and applies them across every field at once.
Show codeHide code
API Reference
Form
Native form element with Base UI consolidated error handling. Lays out its regions (`FormBody`, `FormActions`) with a consistent vertical rhythm; field spacing and the actions-bar treatment live on those parts. Grafts Base UI's form behavior onto the styled `Form` `<form>` frame.