Documentation Index Fetch the complete documentation index at: https://mintlify.com/formsmd/formsmd/llms.txt
Use this file to discover all available pages before exploring further.
Slides enable you to create multi-step forms where users progress through one section at a time. Each slide can contain multiple form fields, content blocks, and navigation controls.
Overview
Forms.md uses slides to break long forms into manageable sections. Each slide:
Can contain multiple form fields and content
Has its own submit/next button
Can show progress indicators
Supports conditional display via jump conditions
Can post data incrementally
const composer = new Composer ({
page: "form-slides" ,
slideDelimiter: "---"
});
// First slide
composer . textInput ( "name" , { question: "Your name?" });
// Create new slide
composer . slide ({ pageProgress: "50%" });
// Second slide
composer . emailInput ( "email" , { question: "Your email?" });
Creating slides
Use the slide() method to create a new slide:
composer . slide ({
pageProgress: "50%" ,
jumpCondition: "age >= 18" ,
buttonAlignment: "center" ,
post: true ,
disablePrevious: false
});
Slide parameters
Progress indicator shown at top (e.g., "50%" or "1/2")
JavaScript expression that must evaluate to true for the slide to be shown
buttonAlignment
'start' | 'center' | 'end' | 'stretch'
Alignment of the slide’s CTA button
If true, posts form data up to this slide when going to the next one
If true, disables the previous/back button on this slide
Slide types
Forms.md supports three types of slides: body slides, start slides, and end slides.
Body slides (default)
Regular slides containing form fields and content:
const composer = new Composer ({ id: "survey" });
// First slide (default body slide)
composer . textInput ( "name" , {
question: "What's your name?" ,
required: true
});
// Second slide
composer . slide ({ pageProgress: "50%" });
composer . emailInput ( "email" , {
question: "What's your email?" ,
required: true
});
Start slides
Create a welcome or intro slide with custom button text:
composer . startSlide ({
buttonText: "Begin Survey" ,
buttonAlignment: "center"
});
composer . free ( `
# Welcome to our survey
This will take approximately 5 minutes to complete.
` );
Start slides can be the first slide or appear later in the form. They use special styling and button text.
End slides
Create a completion or thank you slide:
composer . endSlide ({
redirectUrl: "https://example.com/thank-you"
});
composer . free ( `
# Thank you!
Your response has been recorded.
` );
If you don’t explicitly create an end slide, Forms.md automatically generates a default one.
Page progress
Show users their progress through the form with progress indicators.
Percentage progress
Use percentage values to show progress:
composer . slide ({ pageProgress: "25%" });
composer . slide ({ pageProgress: "50%" });
composer . slide ({ pageProgress: "75%" });
composer . endSlide ();
Fraction progress
Use fractions for automatic percentage calculation:
composer . slide ({ pageProgress: "1/4" }); // 25%
composer . slide ({ pageProgress: "2/4" }); // 50%
composer . slide ({ pageProgress: "3/4" }); // 75%
composer . endSlide ();
Fractions are automatically converted to percentages using CSS calc(), so "1/4" becomes calc(100% * (1/4)).
Global progress control
Control progress indicator globally via settings:
const composer = new Composer ({
pageProgress: "show" // "show" | "hide" | "decorative"
});
Or via Formsmd options:
const formsmd = new Formsmd ( template , container , {
pageProgress: "decorative" // Progress bar that doesn't update
});
Slide navigation
Users navigate between slides using buttons in the slide and/or footer.
Each slide has a next/submit button. Control visibility globally:
const composer = new Composer ({
slideControls: "show" // "show" | "hide"
});
The footer shows previous/next buttons:
const formsmd = new Formsmd ( template , container , {
slideControls: "show" ,
footer: "show"
});
Prevent users from going back on specific slides:
composer . slide ({
disablePrevious: true
});
Post form data incrementally as users progress through slides:
const composer = new Composer ({
postUrl: "/api/save-progress"
});
// Slide 1: Basic info
composer . textInput ( "name" , { question: "Name?" , required: true });
composer . emailInput ( "email" , { question: "Email?" , required: true });
// Slide 2: Will post slide 1 data when advancing
composer . slide ({
post: true ,
pageProgress: "50%"
});
composer . choiceInput ( "plan" , {
question: "Select a plan" ,
choices: [ "Basic" , "Pro" , "Enterprise" ],
required: true
});
The post parameter only works on slides that are part of a form (page type "form-slides") and contain at least one form field.
Complete example
Multi-step form
Conditional slides
import { Composer , Formsmd } from "formsmd" ;
const composer = new Composer ({
id: "onboarding" ,
title: "User Onboarding" ,
postUrl: "/api/onboard" ,
pageProgress: "show"
});
// Start slide
composer . startSlide ({
buttonText: "Get Started" ,
buttonAlignment: "center"
});
composer . free ( `
# Welcome!
Let's set up your account in a few easy steps.
` );
// Slide 1: Personal info
composer . slide ({ pageProgress: "33%" });
composer . textInput ( "fullName" , {
question: "What's your full name?" ,
required: true
});
composer . emailInput ( "email" , {
question: "What's your email?" ,
required: true
});
// Slide 2: Company info
composer . slide ({
pageProgress: "66%" ,
post: true // Save progress
});
composer . textInput ( "company" , {
question: "Company name?"
});
composer . selectBox ( "companySize" , {
question: "Company size?" ,
options: [ "1-10" , "11-50" , "51-200" , "201+" ],
required: true
});
// Slide 3: Preferences
composer . slide ({ pageProgress: "100%" });
composer . choiceInput ( "interests" , {
question: "What are you interested in?" ,
choices: [ "Marketing" , "Sales" , "Support" , "Engineering" ],
multiple: true
});
// End slide
composer . endSlide ();
composer . free ( `
# All set!
Your account has been created successfully.
` );
const formsmd = new Formsmd (
composer . template ,
document . getElementById ( "container" ),
{ saveState: true }
);
formsmd . init ();
Slide templates
Behind the scenes, slides are parsed using templates defined in src/slides-parse.js. Each slide type (form/div, start, end) has its own template structure.
Slide template structure
// Form slide with submit button
< form class = "fmd-slide fmd-first-slide" data-fmd-page-progress = "50%" >
< div class = "fmd-grid" >
{ content }
< div class = "fmd-next-controls" >
< button type = "submit" class = "fmd-submit-btn" > Submit </ button >
</ div >
</ div >
</ form >
// Non-form slide with next button
< div class = "fmd-slide" data-fmd-jump = "condition" >
< div class = "fmd-grid" >
{ content }
< div class = "fmd-next-controls" >
< button type = "button" class = "fmd-next-btn" > Next </ button >
</ div >
</ div >
</ div >
Programmatic navigation
Use Formsmd methods to control slides programmatically:
const formsmd = new Formsmd ( template , container );
formsmd . init ();
// Get current active slide
const activeSlide = document . querySelector ( ".fmd-slide.fmd-active-slide" );
// Go to next slide
formsmd . nextSlide ( activeSlide );
// Go to previous slide
formsmd . prevSlide ( activeSlide );
// Get next slide (respects jump conditions)
const { slide , index } = formsmd . getNextSlide ();
// Get previous slide (respects jump conditions)
const { slide , index } = formsmd . getPrevSlide ();
Best practices
Keep slides focused
Each slide should have a single purpose or related group of fields. Don’t overcrowd slides.
Show progress
Always use pageProgress on multi-step forms to help users understand how much is left.
Save progress incrementally
Use post: true on important slides to save user progress and prevent data loss.
Use start slides
Add a start slide to explain the form’s purpose and estimated completion time.
Consider mobile
Test slide navigation on mobile devices. Footer buttons are especially important for small screens.
Next steps
Conditional logic Add dynamic slide behavior with jump conditions
Composer Learn more about building templates
Formsmd Explore rendering and initialization options