Skip to main content
ProComponents provides multiple form layout components to suit different use cases, from basic forms to complex multi-step wizards and modal/drawer forms.

ProForm

The base form component with vertical layout. All other form layouts extend from this component.
import { ProForm, ProFormText } from '@ant-design/pro-components';

const BasicForm = () => {
  return (
    <ProForm
      onFinish={async (values) => {
        console.log(values);
        return true;
      }}
    >
      <ProFormText name="name" label="Name" />
      <ProFormText name="email" label="Email" />
    </ProForm>
  );
};

Key Props

PropTypeDescription
onFinish(values: T) => Promise<boolean | void>Form submission handler. Return true to indicate success
loadingbooleanShow loading state on submit button
submitterSubmitterProps | falseConfigure or hide submit/reset buttons
initialValuesTInitial form values
request(params: U) => Promise<T>Async data loader for initial values
readonlybooleanSet all form fields to read-only mode

Static Methods

// Access Form utilities
ProForm.useForm(); // Get form instance
ProForm.Item; // Access ProFormItem
ProForm.Group; // Access ProForm.Group
ProForm.useWatch; // Watch form field changes

ModalForm

A form displayed inside a modal dialog. Perfect for create/edit operations that don’t require full-page navigation.
import { ModalForm, ProFormText } from '@ant-design/pro-components';
import { Button } from 'antd';

const CreateUser = () => {
  return (
    <ModalForm
      title="Create New User"
      trigger={<Button type="primary">New User</Button>}
      onFinish={async (values) => {
        await createUser(values);
        return true; // Close modal on success
      }}
    >
      <ProFormText name="username" label="Username" required />
      <ProFormText.Password name="password" label="Password" required />
    </ModalForm>
  );
};

Key Props

PropTypeDescription
triggerReact.JSX.ElementElement that triggers modal to open
openbooleanControlled visibility state
onOpenChange(open: boolean) => voidCallback when visibility changes
modalPropsOmit<ModalProps, 'open'>Additional Ant Design Modal props
titleModalProps['title']Modal title
widthModalProps['width']Modal width (default: 800)
submitTimeoutnumberDisable cancel button during submit (milliseconds)
The onFinish handler should return true to close the modal, or false to keep it open (e.g., if validation fails).

Behavior

  • Form resets automatically when modal closes (with destroyOnHidden in modalProps)
  • Submit button shows loading state during async operations
  • Cancel button is disabled during submitTimeout period

DrawerForm

A form displayed in a side drawer. Great for forms with many fields or when you need more space.
import { DrawerForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
import { Button } from 'antd';

const EditProfile = () => {
  return (
    <DrawerForm
      title="Edit Profile"
      trigger={<Button>Edit Profile</Button>}
      drawerProps={{
        destroyOnHidden: true,
      }}
      onFinish={async (values) => {
        await updateProfile(values);
        return true;
      }}
    >
      <ProFormText name="name" label="Name" />
      <ProFormText name="email" label="Email" />
      <ProFormTextArea name="bio" label="Bio" />
    </DrawerForm>
  );
};

Key Props

PropTypeDescription
triggerReact.JSX.ElementElement that triggers drawer to open
openbooleanControlled visibility state
drawerPropsOmit<DrawerProps, 'open'>Additional Ant Design Drawer props
widthDrawerProps['size']Drawer width
resizeCustomizeResizeType | booleanEnable drawer resizing
submitTimeoutnumberDisable cancel during submit

Resizable Drawer

<DrawerForm
  resize={{
    minWidth: 300,
    maxWidth: 800,
    onResize: () => console.log('Resized'),
  }}
  // ... other props
/>
Or simply:
<DrawerForm resize // Use default resize settings
  // ... other props
/>

StepsForm

A multi-step wizard form for complex data entry workflows.
import { StepsForm, ProFormText, ProFormDatePicker } from '@ant-design/pro-components';

const MultiStepForm = () => {
  return (
    <StepsForm
      onFinish={async (values) => {
        console.log('All steps completed:', values);
        return true; // Reset to step 0
      }}
    >
      <StepsForm.StepForm name="basic" title="Basic Info">
        <ProFormText name="name" label="Name" required />
        <ProFormText name="email" label="Email" required />
      </StepsForm.StepForm>
      
      <StepsForm.StepForm name="address" title="Address">
        <ProFormText name="street" label="Street" />
        <ProFormText name="city" label="City" />
      </StepsForm.StepForm>
      
      <StepsForm.StepForm name="confirm" title="Confirm">
        <ProFormDatePicker name="startDate" label="Start Date" />
      </StepsForm.StepForm>
    </StepsForm>
  );
};

Key Props

PropTypeDescription
currentnumberControlled current step (0-based)
onCurrentChange(current: number) => voidCallback when step changes
stepsPropsStepsPropsProps for Ant Design Steps component
stepsRender(steps, defaultDom) => React.ReactNodeCustom steps renderer
formRefReact.MutableRefObjectRef to current step’s form
formMapRefReact.MutableRefObjectRef to all form instances
submitterSubmitterProps | falseButton configuration

StepForm Props

PropTypeDescription
namestringUnique name for this step
titleReact.ReactNodeStep title in progress indicator
stepPropsStepPropsProps for individual step item

Layout Options

<StepsForm
  stepsProps={{
    direction: 'horizontal',
  }}
>
  {/* Steps */}
</StepsForm>

Custom Layout

<StepsForm
  layoutRender={({ stepsDom, formDom }) => (
    <div>
      <div style={{ width: 200 }}>{stepsDom}</div>
      <div style={{ flex: 1 }}>{formDom}</div>
    </div>
  )}
>
  {/* Steps */}
</StepsForm>

QueryFilter

A collapsible filter form typically used with ProTable or ProList.
import { QueryFilter, ProFormText, ProFormSelect } from '@ant-design/pro-components';

const SearchFilter = () => {
  return (
    <QueryFilter
      onFinish={async (values) => {
        console.log('Filter values:', values);
      }}
      defaultCollapsed={false}
    >
      <ProFormText name="name" label="Name" />
      <ProFormSelect
        name="status"
        label="Status"
        options={[
          { label: 'Active', value: 'active' },
          { label: 'Inactive', value: 'inactive' },
        ]}
      />
      <ProFormText name="email" label="Email" />
    </QueryFilter>
  );
};

Key Props

PropTypeDescription
defaultCollapsedbooleanInitial collapsed state (default: true)
collapsedbooleanControlled collapsed state
onCollapse(collapsed: boolean) => voidCollapse state change callback
spanSpanConfigGrid span configuration
labelWidthnumber | 'auto'Label width (default: 80)
splitbooleanShow divider between rows
searchGutterRowProps['gutter']Grid gutter spacing
defaultColsNumbernumberItems per row when collapsed
searchTextstringCustom search button text
resetTextstringCustom reset button text
optionRender(config, props, dom) => React.ReactNode[]Custom action buttons

Responsive Grid

<QueryFilter
  span={{
    xs: 24,
    sm: 12,
    md: 8,
    lg: 6,
    xl: 6,
    xxl: 6,
  }}
>
  {/* Form fields */}
</QueryFilter>

LightFilter

A lightweight inline filter component with popover support.
import { LightFilter, ProFormText, ProFormSelect } from '@ant-design/pro-components';

const InlineFilter = () => {
  return (
    <LightFilter
      onFinish={async (values) => {
        console.log(values);
      }}
    >
      <ProFormText name="name" label="Name" />
      <ProFormSelect
        name="status"
        label="Status"
        secondary // Show in "More" dropdown
        options={[{ label: 'Active', value: 'active' }]}
      />
    </LightFilter>
  );
};

Key Props

PropTypeDescription
collapsebooleanShow all fields in dropdown
collapseLabelReact.ReactNodeCustom collapse trigger label
variant'outlined' | 'filled' | 'borderless'Style variant (default: ‘borderless’)
placementTooltipPlacementPopover placement
footerRender(onConfirm, onClear) => React.ReactNodeCustom footer
Fields with secondary={true} prop are grouped into a “More Filters” dropdown.

LoginForm

A pre-styled form designed for authentication pages.
import { LoginForm, ProFormText } from '@ant-design/pro-components';

const Login = () => {
  return (
    <LoginForm
      logo="https://example.com/logo.png"
      title="My Application"
      subTitle="Welcome back"
      onFinish={async (values) => {
        await login(values);
      }}
    >
      <ProFormText name="username" placeholder="Username" />
      <ProFormText.Password name="password" placeholder="Password" />
    </LoginForm>
  );
};

Key Props

PropTypeDescription
logoReact.ReactNodeLogo (URL string or ReactNode)
titleReact.ReactNode | falseApplication title
subTitleReact.ReactNode | falseSubtitle text
messageReact.ReactNode | falseError/info message area
actionsReact.ReactNodeAdditional actions (e.g., social login)
contentStyleReact.CSSPropertiesForm content styles
containerStyleReact.CSSPropertiesContainer styles

Comparison

LayoutUse CaseKey Feature
ProFormStandard formsBasic vertical layout
ModalFormQuick editsOpens in modal dialog
DrawerFormDetailed formsSide panel with more space
StepsFormComplex workflowsMulti-step wizard
QueryFilterData filteringCollapsible with responsive grid
LightFilterInline filteringCompact with popover
LoginFormAuthenticationPre-styled login page

Common Features

Form Submission

All form layouts support async submission with loading states:
onFinish={async (values) => {
  await apiCall(values);
  return true; // Indicates success
}}

Initial Data Loading

<ProForm
  request={async (params) => {
    const data = await fetchData(params);
    return data;
  }}
  params={{ id: 1 }}
/>

Form Instance

const formRef = useRef<ProFormInstance>();

<ProForm
  formRef={formRef}
  onFinish={async () => {
    // Access form methods
    const values = formRef.current?.getFieldsValue();
    formRef.current?.resetFields();
  }}
/>

Build docs developers (and LLMs) love