Buttons
@saastro/forms provides three button types for form navigation and submission:
| Button | Purpose | When Shown |
|---|---|---|
submit | Submit the form | On the last step |
next | Go to next step | On non-final steps |
back | Return to previous step | When there’s step history |
Basic Configuration
const config = FormBuilder.create('wizard')
.addField('name', (f) => f.type('text').label('Name'))
.addField('email', (f) => f.type('email').label('Email'))
.addStep('step1', ['name'])
.addStep('step2', ['email'])
.buttons({
submit: {
type: 'submit',
label: 'Send',
variant: 'default',
},
next: {
type: 'next',
label: 'Continue',
variant: 'default',
},
back: {
type: 'back',
label: 'Back',
variant: 'outline',
},
})
.build();
Button Properties
Common Properties
| Property | Type | Default | Description |
|---|---|---|---|
type | 'submit' | 'next' | 'back' | - | Button type (required) |
label | string | Auto | Button text |
variant | string | 'default' | Visual style |
size | string | 'md' | Button size |
icon | ReactNode | - | Icon element |
iconPosition | 'left' | 'right' | 'right' | Icon placement |
disabled | boolean | false | Disable button |
Variants
variant: 'default'; // Primary solid background
variant: 'secondary'; // Secondary muted background
variant: 'outline'; // Border only
variant: 'ghost'; // No background, subtle hover
variant: 'destructive'; // Red/danger style
variant: 'link'; // Looks like a link
Sizes
size: 'xs'; // Extra small
size: 'sm'; // Small
size: 'md'; // Medium (default)
size: 'lg'; // Large
size: 'xl'; // Extra large
Effects
Special hover/interaction effects:
effect: 'default'; // Standard button
effect: 'expandIcon'; // Icon expands on hover
effect: 'ringHover'; // Ring appears on hover
effect: 'shine'; // Continuous shine animation
effect: 'shineHover'; // Shine on hover only
effect: 'gooeyRight'; // Gooey effect to right
effect: 'gooeyLeft'; // Gooey effect to left
effect: 'underline'; // Underline always visible
effect: 'hoverUnderline'; // Underline on hover
Button Icons
Add icons to buttons using React components:
import { ArrowRight, ArrowLeft, Send } from 'lucide-react';
.buttons({
submit: {
type: 'submit',
label: 'Send Message',
icon: <Send className="h-4 w-4" />,
iconPosition: 'right',
},
next: {
type: 'next',
label: 'Continue',
icon: <ArrowRight className="h-4 w-4" />,
iconPosition: 'right',
},
back: {
type: 'back',
label: 'Go Back',
icon: <ArrowLeft className="h-4 w-4" />,
iconPosition: 'left',
},
})
Button Alignment
Control horizontal alignment of the button container:
.buttons({
align: 'start', // Left aligned
align: 'center', // Center aligned
align: 'end', // Right aligned (default)
align: 'between', // Space between (back left, next/submit right)
align: 'responsive', // Stacked on mobile, right-aligned on desktop
// ...
})
Visual Examples
align: 'start'
[Back] [Submit]
align: 'center'
[Back] [Submit]
align: 'end'
[Back] [Submit]
align: 'between'
[Back] [Submit]
align: 'responsive' (mobile)
[Submit]
[Back]
align: 'responsive' (desktop)
[Back] [Submit]
Inline Buttons
Place buttons on the same row as fields (useful for search forms):
const config = FormBuilder.create('search')
.layout('manual')
.columns(12)
.addField('query', (f) =>
f.type('text').label('Search').hideLabel().placeholder('Search...').columns({ default: 10 }),
)
.addStep('main', ['query'])
.buttons({
inline: true, // Same row as fields
submit: {
type: 'submit',
label: 'Search',
},
})
.build();
Multi-Step Form Example
Complete example with navigation buttons:
import { FormBuilder } from '@saastro/forms';
import { ArrowRight, ArrowLeft, Check } from 'lucide-react';
const config = FormBuilder.create('onboarding')
.layout('manual')
.columns(12)
// Step 1: Personal Info
.addField('name', (f) =>
f.type('text').label('Full Name').required().columns({ default: 12, md: 6 }),
)
.addField('email', (f) =>
f.type('email').label('Email').required().columns({ default: 12, md: 6 }),
)
// Step 2: Preferences
.addField('theme', (f) =>
f
.type('select')
.label('Theme')
.options([
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
{ value: 'system', label: 'System' },
]),
)
// Step 3: Confirmation
.addField('terms', (f) =>
f.type('checkbox').label('I accept the terms and conditions').required(),
)
// Define steps
.addStep('personal', ['name', 'email'])
.addStep('preferences', ['theme'])
.addStep('confirmation', ['terms'])
.initialStep('personal')
// Configure buttons
.buttons({
align: 'between',
submit: {
type: 'submit',
label: 'Complete',
icon: <Check className="h-4 w-4" />,
variant: 'default',
},
next: {
type: 'next',
label: 'Continue',
icon: <ArrowRight className="h-4 w-4" />,
variant: 'default',
},
back: {
type: 'back',
label: 'Previous',
icon: <ArrowLeft className="h-4 w-4" />,
iconPosition: 'left',
variant: 'outline',
},
})
.build();
Custom Button Actions
Override default button behavior:
.buttons({
back: {
type: 'back',
label: 'Cancel',
action: () => {
// Custom action instead of going back
if (confirm('Are you sure you want to cancel?')) {
window.location.href = '/';
}
},
},
})
API Reference
FormButtons Interface
interface FormButtons {
submit?: ButtonConfig;
next?: ButtonConfig;
back?: ButtonConfig;
align?: 'start' | 'center' | 'end' | 'between' | 'responsive';
inline?: boolean;
}
ButtonConfig Interface
interface ButtonConfig {
type: 'button' | 'submit' | 'next' | 'back';
label?: string;
action?: () => void;
loading?: boolean;
icon?: ReactNode;
iconPosition?: 'left' | 'right';
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
effect?:
| 'default'
| 'expandIcon'
| 'ringHover'
| 'shine'
| 'shineHover'
| 'gooeyRight'
| 'gooeyLeft'
| 'underline'
| 'hoverUnderline';
rounded?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
disabled?: boolean;
}