Skip to content

Layout Schema

type FormLayoutConfig = SinglePageLayoutConfig | WizardLayoutConfig | TabsLayoutConfig;
type FormLayoutConfig =
| SinglePageLayoutConfig
| WizardLayoutConfig
| TabsLayoutConfig
| AccordionLayoutConfig;
interface SinglePageLayoutConfig {
kind?: "single-page";
children?: FormLayoutNode[];
}

Use for:

  • one-page custom UIs
  • sectioned dashboards
  • review or analyst screens
interface WizardLayoutConfig {
kind: "wizard";
steps: WizardStepConfig[];
}

Use for:

  • multi-step flows
  • onboarding
  • staged data collection
  • step-by-step review
interface TabsLayoutConfig {
kind: "tabs";
tabs: TabLayoutConfig[];
}

Use for:

  • free section switching
  • app-like shells with persistent submit
  • analytical workflows that should not validate on navigation
interface WizardStepConfig {
id?: string;
title: string;
description?: string;
children: FormLayoutNode[];
}

Rules:

  • steps must not be empty
  • each step must contain at least one node
  • each field must belong to exactly one step
  • id is optional and auto-generated from title
interface TabLayoutConfig {
id?: string;
title: string;
description?: string;
children: FormLayoutNode[];
}

Rules:

  • tabs must not be empty
  • each tab must contain at least one node
  • each field must belong to exactly one tab
  • id is optional and auto-generated from title
  • switching tabs does not validate
interface AccordionLayoutConfig {
kind: "accordion";
sections: AccordionSectionConfig[];
}

Use for:

  • progressive disclosure
  • dense forms on mobile
  • review flows where multiple regions can remain open
interface AccordionSectionConfig {
id?: string;
title: string;
description?: string;
children: FormLayoutNode[];
defaultOpen?: boolean;
}

Rules:

  • sections must not be empty
  • each section must contain at least one node
  • each field must belong to exactly one section
  • first section defaults to open unless overridden
type FormLayoutNode =
| {
kind: "section";
id?: string;
title?: string;
description?: string;
children: FormLayoutNode[];
}
| { kind: "group"; id?: string; columns?: 1 | 2 | 3; children: FormLayoutNode[] }
| { kind: "field"; field: string }
| { kind: "report"; report: string }
| { kind: "explanation"; explanation: string };

Use section for semantic grouping and copy.

{
kind: "section",
title: "Applicant",
description: "Core identity data.",
children: [
{ kind: "field", field: "name" },
{ kind: "field", field: "email" },
],
}

Use group for visual grouping and column hints.

{
kind: "group",
columns: 2,
children: [
{ kind: "field", field: "city" },
{ kind: "field", field: "zip" },
],
}

References a field id from the normalized form schema.

{ kind: "field", field: "name" }

References a report id.

{ kind: "report", report: "risk" }

References an explanation id.

{ kind: "explanation", explanation: "why" }

When layout is explicit:

  • every field must appear exactly once
  • reports may appear zero or one time
  • explanations may appear zero or one time
  • unknown references fail creation immediately
  • missing fields fail creation immediately

MLForm auto-generates ids for:

  • sections
  • groups
  • wizard steps

Generated ids are slug-based and stable relative to config order.

{
kind: "single-page",
children: [
{
kind: "section",
title: "Profile",
children: [
{ kind: "field", field: "name" },
{ kind: "field", field: "email" },
],
},
{
kind: "section",
title: "Outputs",
children: [{ kind: "report", report: "risk" }],
},
],
}
{
kind: "wizard",
steps: [
{
title: "Profile",
children: [{ kind: "field", field: "name" }],
},
{
title: "Assessment",
children: [{ kind: "field", field: "score" }],
},
{
title: "Review",
children: [
{ kind: "report", report: "risk" },
{ kind: "explanation", explanation: "why" },
],
},
],
}
{
kind: "tabs",
tabs: [
{
title: "Profile",
children: [{ kind: "field", field: "name" }],
},
{
title: "Assessment",
children: [
{ kind: "field", field: "score" },
{ kind: "report", report: "risk" },
],
},
],
}
{
kind: "accordion",
sections: [
{
title: "Profile",
children: [{ kind: "field", field: "name" }],
},
{
title: "Assessment",
children: [
{ kind: "field", field: "score" },
{ kind: "report", report: "risk" },
],
},
],
}