Forms

Forms are application contracts, not just input boxes. The Forms module owns fields, validation, context, and submit behavior.

Use Sass v2 form classes for the visual system, then attach real forms to H/B/F sections through Databoard mapping.

Component

Basic contact form

A normal form uses labels, helper text, controls, textarea, and a semantic submit button.

Labels and helper text come from the form definition.
Default
Basic form mapping text
data.item.css_class = stylesdoc-form-demo
data.description = dummy form HTML using antsand-form-control
Real pages should attach a Forms module record with data.form.id

Login application form

Login forms are application forms. They post to an HMVC endpoint and must not fall back to generic thank-you behavior.

Application
Login form contract text
form.application_mode = login
form.submit_url = /auth/session/login
form.generic_thank_you = disabled
HMVC action verifies password_hash and sets session.auth

Set password with server-owned email

The page provides form_context.email. The form renders it readonly and posts password plus confirmation.

Readonly because the controller owns this value.
Context
Context field contract text
field.email.view_source = form_context.email
field.email.readonly_when_context = true
field.password_confirm.validation = Matches Field
field.password_confirm.match_field = password

Validation states

Use explicit valid/invalid states and ARIA attributes so styling, JS validation, and server errors agree.

Looks good.
Password is required.
Validation
Validation classes html
<input class="antsand-form-control is-valid" aria-invalid="false">
<div class="antsand-valid-feedback">Looks good.</div>
<input class="antsand-form-control is-invalid" aria-invalid="true">
<div class="antsand-invalid-feedback">Password is required.</div>

Select, checkbox, and radio fields

Choice controls use the same form-group shell, then field-specific classes for select, checkbox, and radio controls.

Choices
Choice field classes html
<select class="antsand-form-select">...</select>
<label class="antsand-form-check"><input type="checkbox"><span>Email me updates</span></label>
<label class="antsand-form-check"><input type="radio" name="frequency"><span>Weekly</span></label>

Payment form mount

Checkout forms still use a server-rendered contract. The payment amount, currency, and store id must be present before Stripe initializes.

Premium membershipServer-rendered checkout item
$25.00 CAD
Stripe Payment Element mounts here
Payment
Payment mount contract html
<div class="antsand-stripe-payment-element"
  data-price-cents="2500"
  data-currency="cad"
  data-store-id="demo-store"></div>
<!-- Missing amount should fail early before creating payment intent. -->

Small, default, and large controls

Use size modifiers when the form density should match a compact toolbar or a large marketing page.

Sizing
Form size classes html
<input class="antsand-form-control antsand-form-sm">
<input class="antsand-form-control">
<input class="antsand-form-control antsand-form-lg">

Floating labels

Floating labels keep dense forms readable while preserving accessible label text.

Floating
Floating label structure html
<div class="antsand-form-floating">
  <input class="antsand-form-control" placeholder="name@example.com">
  <label>Email address</label>
</div>

Switch toggles

Switches are choice controls for settings, notification preferences, and dashboard toggles.

Switches
Switch classes html
<label class="antsand-form-switch">
  <input type="checkbox" checked>
  <span>Email notifications</span>
</label>

Input groups

Input groups attach prefixes, suffixes, or action buttons without custom wrapper CSS.

@
.com
Groups
Input group structure html
<div class="antsand-input-group">
  <span class="antsand-input-group-text">@</span>
  <input class="antsand-form-control">
</div>

Inline, horizontal, and multi-column rows

Form layout classes handle common composition without turning each generated form into custom HTML.

Layouts
Layout classes html
<div class="antsand-form-inline">...</div>
<div class="antsand-form-row-2">...</div>
<div class="antsand-form-horizontal">...</div>

Range, file, and dropzone controls

Upload-heavy applications need file and drag-drop affordances that still fit the same form shell.

Drop files hereor choose from Antsand media assets
Files
File and range classes html
<input class="antsand-form-range" type="range">
<input class="antsand-form-file" type="file">
<div class="antsand-form-dropzone">Drop files here</div>

Fieldset, legend, required marker, and helper text

Grouped forms should express meaning in the markup, not only with visual spacing.

Publishing settings
Required fields get a consistent accent.
Structure
Semantic grouping html
<fieldset class="antsand-fieldset">
  <legend class="antsand-legend">Publishing settings</legend>
  <label class="antsand-form-label antsand-required">Post title</label>
  <input class="antsand-form-control" required>
</fieldset>

Disabled and focus states

Disabled and focus-within states are CSS contracts, so server output and JS validation stay consistent.

The label and control respond through focus-visible/focus-within styling.
States
State selectors html
<input class="antsand-form-control" disabled>
<div class="antsand-form-group" aria-disabled="true">...</div>
<input class="antsand-form-control" aria-invalid="true">

Form card shell

Use a card shell when a form is the primary object on a page, such as signup, checkout, or account settings.

Create account

One card, one action.

Card
Form card shell html
<form class="antsand-form-card">
  <div class="antsand-form-card-header">...</div>
  <div class="antsand-form-card-body">...</div>
  <div class="antsand-form-card-footer">...</div>
</form>