Writing custom step layouts
Every form in each step rendered in the frontend uses the default form layout from react-jsonschema-form. It is possible to override this behaviour by supplying a ui:ObjectFieldTemplate property for a particular step:
parameters:
  - title: Fill in some steps
    ui:ObjectFieldTemplate: TwoColumn
This is the same field used by react-jsonschema-form but we need to add a couple of steps to ensure that the string value of TwoColumn above is resolved to a react component.
Registering a React component as a custom step layout
The createScaffolderLayout function is used to mark a component as a custom step layout:
import { scaffolderPlugin } from '@backstage/plugin-scaffolder';
import {
  createScaffolderLayout,
  LayoutTemplate,
} from '@backstage/plugin-scaffolder-react';
import { Grid } from '@material-ui/core';
const TwoColumn: LayoutTemplate = ({ properties, description, title }) => {
  const mid = Math.ceil(properties.length / 2);
  return (
    <>
      <h1>{title}</h1>
      <h2>In two column layout!!</h2>
      <Grid container justifyContent="flex-end">
        {properties.slice(0, mid).map(prop => (
          <Grid item xs={6} key={prop.content.key}>
            {prop.content}
          </Grid>
        ))}
        {properties.slice(mid).map(prop => (
          <Grid item xs={6} key={prop.content.key}>
            {prop.content}
          </Grid>
        ))}
      </Grid>
      {description}
    </>
  );
};
export const TwoColumnLayout = scaffolderPlugin.provide(
  createScaffolderLayout({
    name: 'TwoColumn',
    component: TwoColumn,
  }),
);
After you have registered your component as a custom layout then you need to provide the layouts to the ScaffolderPage:
import { MyCustomFieldExtension } from './scaffolder/MyCustomExtension';
import { TwoColumnLayout } from './components/scaffolder/customScaffolderLayouts';
const routes = (
  <FlatRoutes>
    ...
    <Route path="/create" element={<ScaffolderPage />}>
      <ScaffolderLayouts>
        <TwoColumnLayout />
      </ScaffolderLayouts>
    </Route>
    ...
  </FlatRoutes>
);
Using the custom step layout
Any component that has been passed to the ScaffolderPage as children of the ScaffolderLayouts component can be used as a ui:ObjectFieldTemplate in your template file:
parameters:
  - title: Fill in some steps
    ui:ObjectFieldTemplate: TwoColumn