Common Forms

Updated:

End-to-end examples of common banking forms — account registration, card controls, secure message, and check deposit — built with Tecton components and the layout rules from Designing Forms.

The examples on this page show how to assemble Tecton form primitives into the kinds of forms that come up over and over in a banking product. Each one follows the guidance in Designing Forms: fields stack in a single column by default, q2-form handles the vertical rhythm, and only naturally paired fields sit side-by-side at the md breakpoint. Every form is wrapped in a q2-surface to give it a card container with padding, a border, and rounded corners.

Data filters

Reach for this pattern when a user needs to narrow a list of results (transactions, statements, alerts). Filters are entered in parallel, not sequentially, so pair range fields (start/end date, min/max amount) side-by-side at md and use q2-form spacing="compact" since the panel sits alongside results rather than replacing them. Quick-filter toggles belong in a bordered inner surface at the side so common choices stay reachable without scanning the full field list.

Custom filters Dining Out Rent / Mortgage Shopping Utilities
<q2-surface background="default" inset="normal" border="default" radius="2">
  <q2-input type="search" label="Search" placeholder="Search" hide-label></q2-input>
  <q2-section label="Advanced" collapsible style="--tct-section-margin: 0; --tct-section-header-padding: 0; --tct-section-content-padding: 0;">
    <q2-surface inset-y="normal">
      <q2-grid columns="1" md-columns="2">
        <q2-grid-area>
          <strong>Custom filters</strong>
        </q2-grid-area>
        <q2-grid-area justify="end">
          <q2-link label="Edit" href="#" variant="standalone" icon-type="chevron-right">
          </q2-link>
        </q2-grid-area>
      </q2-grid>
      <q2-pill label="Clothing">
      </q2-pill>
      <q2-pill label="School supplies">
      </q2-pill>
      <q2-pill label="Travel">
      </q2-pill>
      <q2-pill label="Business">
      </q2-pill>
      <q2-pill label="AI">
      </q2-pill>
    </q2-surface>
    <q2-surface>
      <q2-grid columns="1" md-columns="3">
        <q2-grid-area column-span="1" md-column-span="2">
          <q2-form spacing="compact">
            <q2-select label="Categories" multiple>
              <q2-option value="1">Dining Out</q2-option>
              <q2-option value="2">Rent / Mortgage</q2-option>
              <q2-option value="3">Shopping</q2-option>
              <q2-option value="4">Utilities</q2-option>
            </q2-select>
            <q2-grid columns="1" md-columns="2">
              <q2-grid-area>
                <q2-calendar label="Start date">
                </q2-calendar>
              </q2-grid-area>
              <q2-grid-area>
                <q2-calendar label="End date">
                </q2-calendar>
              </q2-grid-area>
              <q2-grid-area>
                <q2-input type="currency" label="Minimum amount">
                </q2-input>
              </q2-grid-area>
              <q2-grid-area>
                <q2-input type="currency" label="Maximum amount">
                </q2-input>
              </q2-grid-area>
              <q2-grid-area>
                <q2-input type="number" label="Starting check #">
                </q2-input>
              </q2-grid-area>
              <q2-grid-area>
                <q2-input type="number" label="Ending check #">
                </q2-input>
              </q2-grid-area>
            </q2-grid>
          </q2-form>
        </q2-grid-area>
        <q2-grid-area column-span="1">
          <q2-surface border="default" inset="normal" radius="2">
            <q2-checkbox-group label="Quick Filters" style="margin: 0;">
              <q2-checkbox value="value-1" label="Uncategorized" type="toggle">
              </q2-checkbox>
              <q2-checkbox value="value-2" label="Categorized" type="toggle">
              </q2-checkbox>
              <q2-checkbox value="value-3" label="Debits" type="toggle">
              </q2-checkbox>
              <q2-checkbox value="value-4" label="Credits" type="toggle">
              </q2-checkbox>
              <q2-checkbox value="value-5" label="Checks" type="toggle">
              </q2-checkbox>
            </q2-checkbox-group>
          </q2-surface>
        </q2-grid-area>
      </q2-grid>
    </q2-surface>
  </q2-section>
</q2-surface>

Account registration

Reach for this pattern for high-commitment, one-time forms filled top to bottom (registration, KYC, application intake). The goal is a single unambiguous path down the page. Stack fields in one column; only pair fields at md that read as one thing — first/last name, city/state/ZIP. Keep the two password fields stacked so the user can't misread which label owns which input. Use show-visibility-toggle on sensitive fields (SSN, passwords). Put terms (required) and marketing opt-in (optional, unchecked) directly above the primary action, so consent is a genuine choice, not a dark pattern.

Create your account

Alabama Alaska Arizona Texas What was the name of your first pet? What elementary school did you attend? In what city were you born? Create account Cancel
<q2-surface background="default" inset="normal" border="default" radius="2">
  <h2>Create your account</h2>
  <q2-form>
    <q2-grid columns="1" md-columns="2" gap="comfortable">
      <q2-grid-area>
        <q2-input label="First name" autocomplete="given-name"></q2-input>
      </q2-grid-area>
      <q2-grid-area>
        <q2-input label="Last name" autocomplete="family-name"></q2-input>
      </q2-grid-area>
    </q2-grid>
    <q2-input label="Email address" type="email" autocomplete="email"></q2-input>
    <q2-input label="Phone number" type="phone" format-modifier="US" autocomplete="tel"></q2-input>
    <q2-calendar label="Date of birth" assume="past"></q2-calendar>
    <q2-input label="Social Security Number" type="ssn" show-visibility-toggle></q2-input>
    <q2-input label="Street address" autocomplete="street-address"></q2-input>
    <q2-grid columns="1" md-columns="6" gap="comfortable">
      <q2-grid-area column-span="1" md-column-span="3">
        <q2-input label="City" autocomplete="address-level2"></q2-input>
      </q2-grid-area>
      <q2-grid-area column-span="1" md-column-span="1">
        <q2-select label="State">
          <q2-option value="AL">Alabama</q2-option>
          <q2-option value="AK">Alaska</q2-option>
          <q2-option value="AZ">Arizona</q2-option>
          <q2-option value="TX">Texas</q2-option>
        </q2-select>
      </q2-grid-area>
      <q2-grid-area column-span="1" md-column-span="2">
        <q2-input label="ZIP code" type="postal" format-modifier="US"></q2-input>
      </q2-grid-area>
    </q2-grid>
    <q2-input label="Username" autocomplete="username"></q2-input>
    <q2-input label="Password" type="password" show-visibility-toggle autocomplete="new-password"></q2-input>
    <q2-input label="Confirm password" type="password" show-visibility-toggle autocomplete="new-password"></q2-input>
    <q2-select label="Security question">
      <q2-option value="pet">What was the name of your first pet?</q2-option>
      <q2-option value="school">What elementary school did you attend?</q2-option>
      <q2-option value="city">In what city were you born?</q2-option>
    </q2-select>
    <q2-input label="Security answer"></q2-input>
    <q2-checkbox label="I agree to the Terms & Conditions and Privacy Policy" value="terms"></q2-checkbox>
    <q2-checkbox label="Send me product updates and marketing emails" value="marketing"></q2-checkbox>
  </q2-form>
  <q2-action-group>
    <q2-btn intent="workflow-primary">Create account</q2-btn>
    <q2-btn intent="workflow-secondary">Cancel</q2-btn>
  </q2-action-group>
</q2-surface>

Card controls

Reach for this pattern for settings surfaces where the user flips a set of on/off switches on a single subject (card controls, notification preferences, permission grants). Put the subject selector at the top so every field below reads as "applies to the thing above." Use q2-checkbox type="toggle" for binary settings — the toggle affordance reads as current state more clearly than a checkbox. Group related toggles in a q2-checkbox-group so one label owns the set. Numeric limits are the exception; pair them at md when they form a natural range. checked reflects saved state, and the primary action is "Save", not "Submit."

Card controls

Debit •••• 4821 Rewards Credit •••• 7302 Save controls Cancel
<q2-surface background="default" inset="normal" border="default" radius="2">
  <h2>Card controls</h2>
  <q2-form>
    <q2-select label="Card">
      <q2-option value="debit">Debit •••• 4821</q2-option>
      <q2-option value="credit">Rewards Credit •••• 7302</q2-option>
    </q2-select>
    <q2-checkbox type="toggle" label="Card enabled" checked value="card-on"></q2-checkbox>
    <q2-checkbox-group label="Allowed transaction types">
      <q2-checkbox type="toggle" label="In-store purchases" checked value="in-store"></q2-checkbox>
      <q2-checkbox type="toggle" label="Online purchases" checked value="online"></q2-checkbox>
      <q2-checkbox type="toggle" label="ATM withdrawals" checked value="atm"></q2-checkbox>
      <q2-checkbox type="toggle" label="Contactless payments" checked value="contactless"></q2-checkbox>
    </q2-checkbox-group>
    <q2-checkbox-group label="Allowed merchant categories">
      <q2-checkbox type="toggle" label="Travel" checked value="travel"></q2-checkbox>
      <q2-checkbox type="toggle" label="Gas & fuel" checked value="gas"></q2-checkbox>
      <q2-checkbox type="toggle" label="Restaurants" checked value="restaurants"></q2-checkbox>
      <q2-checkbox type="toggle" label="Groceries" checked value="groceries"></q2-checkbox>
      <q2-checkbox type="toggle" label="Entertainment" value="entertainment"></q2-checkbox>
    </q2-checkbox-group>
    <q2-grid columns="1" md-columns="2" gap="comfortable">
      <q2-grid-area>
        <q2-input label="Limit per transaction" type="currency"></q2-input>
      </q2-grid-area>
      <q2-grid-area>
        <q2-input label="Daily spend limit" type="currency"></q2-input>
      </q2-grid-area>
    </q2-grid>
    <q2-checkbox type="toggle" label="Restrict to domestic transactions only" value="domestic"></q2-checkbox>
    <q2-checkbox-group label="Alert me on">
      <q2-checkbox type="toggle" label="In-store purchases" value="alert-in-store"></q2-checkbox>
      <q2-checkbox type="toggle" label="Online purchases" checked value="alert-online"></q2-checkbox>
      <q2-checkbox type="toggle" label="ATM withdrawals" checked value="alert-atm"></q2-checkbox>
      <q2-checkbox type="toggle" label="Declined transactions" checked value="alert-declined"></q2-checkbox>
    </q2-checkbox-group>
  </q2-form>
  <q2-action-group>
    <q2-btn intent="workflow-primary">Save controls</q2-btn>
    <q2-btn intent="workflow-secondary">Cancel</q2-btn>
  </q2-action-group>
</q2-surface>

Secure message

Reach for this pattern when the user composes a free-form message routed to another human (support tickets, disputes, advisor requests). Put routing metadata (category, related account) above the body so triage fields don't get skipped — category is required, the account is optional since not every inquiry belongs to one. Give q2-textarea rows="6" or more; cramped textareas produce shorter, less useful messages. Use q2-file-picker variant="browse-drop" because attachments (screenshots, receipts) are often the point of the message. Priority is a checkbox at the bottom, not a top-of-form dropdown — most messages aren't urgent, and the default should reflect that.

Send a secure message

General inquiry Transaction dispute Account access Loan servicing Checking •••• 0745 Savings •••• 1290 Rewards Credit •••• 7302 Send message Save draft
<q2-surface background="default" inset="normal" border="default" radius="2">
  <h2>Send a secure message</h2>
  <q2-form>
    <q2-select label="Category">
      <q2-option value="general">General inquiry</q2-option>
      <q2-option value="dispute">Transaction dispute</q2-option>
      <q2-option value="account">Account access</q2-option>
      <q2-option value="loan">Loan servicing</q2-option>
    </q2-select>
    <q2-select label="Related account" optional>
      <q2-option value="checking-0745">Checking •••• 0745</q2-option>
      <q2-option value="savings-1290">Savings •••• 1290</q2-option>
      <q2-option value="credit-7302">Rewards Credit •••• 7302</q2-option>
    </q2-select>
    <q2-input label="Subject"></q2-input>
    <q2-textarea label="Message" rows="6"></q2-textarea>
    <q2-file-picker
      label="Attachments"
      variant="browse-drop"
      file-types="jpg, jpeg, png, pdf"
      optional
      style="--tct-file-picker-drop-zone-max-width: 100%"
    ></q2-file-picker>
    <q2-checkbox label="Mark this message as high priority" value="priority"></q2-checkbox>
  </q2-form>
  <q2-action-group>
    <q2-btn intent="workflow-primary">Send message</q2-btn>
    <q2-btn intent="workflow-secondary">Save draft</q2-btn>
  </q2-action-group>
</q2-surface>

Check deposit

Reach for this pattern when the user submits images or documents alongside a small amount of structured data (check deposit, ID verification, claim receipts). Capture destination fields (account, amount) before images so the form can fail fast on invalid inputs before the user photographs anything. Pair front/back file pickers at md — they're one artifact split in two, and pairing makes both feel required. Use max-files="1" on each picker and restrict file-types to images. Put any legal acknowledgment checkbox directly above the primary action so the attestation reads as part of the act of submitting, not fine print.

Deposit a check

Checking •••• 0745 Savings •••• 1290 Submit deposit Cancel
<q2-surface background="default" inset="normal" border="default" radius="2">
  <h2>Deposit a check</h2>
  <q2-form>
    <q2-select label="Deposit to">
      <q2-option value="checking-0745">Checking •••• 0745</q2-option>
      <q2-option value="savings-1290">Savings •••• 1290</q2-option>
    </q2-select>
    <q2-input label="Amount" type="currency"></q2-input>
    <q2-grid columns="1" md-columns="2" gap="comfortable">
      <q2-grid-area>
        <q2-file-picker
          label="Front of check"
          variant="browse-drop"
          file-types="jpg, jpeg, png"
          max-files="1"
        ></q2-file-picker>
      </q2-grid-area>
      <q2-grid-area>
        <q2-file-picker
          label="Back of check (endorsed)"
          variant="browse-drop"
          file-types="jpg, jpeg, png"
          max-files="1"
        ></q2-file-picker>
      </q2-grid-area>
    </q2-grid>
    <q2-input label="Memo" optional></q2-input>
    <q2-checkbox label="I confirm the check has been endorsed and understand deposited funds may not be available immediately" value="ack"></q2-checkbox>
  </q2-form>
  <q2-action-group>
    <q2-btn intent="workflow-primary">Submit deposit</q2-btn>
    <q2-btn intent="workflow-secondary">Cancel</q2-btn>
  </q2-action-group>
</q2-surface>

Related