Buttons Guide
Buttons & Navigation Controls
Section titled “Buttons & Navigation Controls”Buttons are more than decoration—they drive the user flow and communicate state. @enlolab/forms ships with three first-class buttons—submit, next, and back—which you can fully customise via the buttons property in FormConfig.
Key takeaway – Every button is just a configuration object; no need to re-implement React components unless you want to.
1. Default configuration
Section titled “1. Default configuration”If you omit buttons, @enlolab/forms injects sensible defaults:
| Button | Default Label | Variant | Size |
|---|---|---|---|
submit | Submit | default | md |
next | Siguiente → | outline | md |
back | ← Atrás | ghost | md |
They automatically appear at the end of each step:
- Back is hidden on the first step (when
stepHistory.length === 0). - Next is replaced by Submit on the last step (when
isLast === true).
2. ButtonConfig reference
Section titled “2. ButtonConfig reference”| Property | Type | Required | Description |
|---|---|---|---|
type | "button" | "submit" | "next" | "back" | ✔︎ | Determines behaviour & placement. |
label | string | ✖︎ | Text shown inside the button. |
variant | ShadCN variant | ✖︎ | default, destructive, outline, secondary, ghost, link. |
size | "xs" "sm" "md" "lg" "xl" | ✖︎ | Tailwind-based size classes. |
effect | See Effects below | ✖︎ | Adds interactive motion using CSS. |
icon | ReactNode | string | ✖︎ | Pass a Lucide element or an Iconify string. |
iconPosition | "left" | "right" | ✖︎ | Defaults to left. |
disabled | boolean | (values) => boolean | ✖︎ | Control interactively. |
action | () => void | ✖︎ | Custom onClick handler (ignored for submit). |
loading | boolean | ✖︎ | Overrides the spinner state. |
colSpan | Grid span | ✖︎ | Make the button wider/narrower. |
3. Variants & sizes
Section titled “3. Variants & sizes”Variants map directly to ShadCN UI classes—you inherit its full design system. Combine with size for compact or prominent CTAs:
buttons: { submit: { variant: "destructive", size: "lg" }}4. Effects (micro-animations)
Section titled “4. Effects (micro-animations)”Built-in effects are pure CSS and cost zero JS:
| Key | Description |
|---|---|
expandIcon | Icon glides slightly when hovered. |
ringHover | Shows a subtle ring outline on hover. |
shine | Animated diagonal shine (continuous). |
shineHover | Shine only on hover. |
gooeyRight | Gooey blob animation moving right. |
gooeyLeft | Gooey blob moving left. |
underline | Classic underline expansion. |
hoverUnderline | Underline appears only on hover. |
Example:
buttons: { next: { effect: "ringHover"; }}5. Adding icons
Section titled “5. Adding icons”Icons improve scannability. You can pass:
import { ArrowRight } from "lucide-react";buttons: { next: { icon: <ArrowRight />, // React element iconPosition: "right" }, submit: { icon: "mdi:send", // Iconify string effect: "expandIcon" }}Internally @enlolab/forms delegates to the helper getIcon() which supports both React nodes and Iconify names.
6. Conditional disabling & loading
Section titled “6. Conditional disabling & loading”Need to disable Submit until terms are accepted? Use a function:
buttons: { submit: { disabled: (values) => !values.agreeToTerms; }}To show a spinner during async work set loading: true. @enlolab/forms automatically adds a Loading… label but you can override via label.
7. Custom actions
Section titled “7. Custom actions”While submit triggers the internal handleSubmit logic, next and back can invoke custom callbacks:
buttons: { next: { action: () => { console.log("analytics: user clicked next"); }; }}Note: The internal navigation is still executed after your action.
You can also create additional arbitrary buttons by adding a field of type button inside fields and placing it in any step.
8. Accessibility & best practices
Section titled “8. Accessibility & best practices”- Use semantic
<button>elements – already handled by @enlolab/forms. - Provide clear, descriptive labels (
labelprop). Avoid jargon. - Ensure sufficient color contrast when changing variants.
- Display a loading indicator for operations > 500 ms.
- Disable buttons only when absolutely necessary; explain why.
Related guides
Section titled “Related guides”- Submit Guide – Configure networking & reCAPTCHA.
- Layout Guide – Align buttons using grid spans.
- Getting Started – Build your first form.