Guidelines for text fields design

Text fields are probably one of the most used interface components; contact forms, payment details, account creation, lead generation. Users definitely need to interact with text fields when using your product. The purpose of this post is to highlight some of the key guidelines which I follow when it comes to designing better text fields.

It’s pretty basic things that, unfortunately, a lot of people seem to forget.

Guidelines for text fields design →

💵 This linked article is stuck behind Medium’s metered paywall, which may prevent you from reading it. Open the link in an incognito window to bypass Medium’s ridiculous reading limit.

Methods for assigning an accessible name to a form control

Adrian Roselli:

Too often folks will grab ARIA first to provide an accessible name for a thing. Or they may sprinkle hidden content around a form. In most cases the impact of those decisions is unknown. The assumption that they do the same thing, give the same output to all users, is wrong.

In short, here’s the priority he follows when assigning an accessible name to a control:

  1. Native HTML techniques,
  2. aria-labelledby pointing at existing visible text,
  3. Visibly-hidden content that is still in the page,
  4. aria-label.

Good ole’ HTML first, the rule of least power in action 😉

My Priority of Methods for Labeling a Control →

React: You May Not Need Controlled Form Components

To work with forms in React two approaches are to either use Controlled Components or use Uncontrolled Components (as detailed here). Swyx shares a third way of working with forms:

A lower friction way to handle form inputs is to use HTML name attributes. As a bonus, your code often turns out less React specific!

The key is to add an onchange handler onto the form. From there you can access event.currentTarget to get the form, and then add .nameOfTheInput to it.

// 31 lines of code
function NameForm() {
  const handleSubmit = (event) => {
    event.preventDefault();
    if (event.currentTarget.nameField.value === 'secretPassword') {
      alert('congrats you guessed the secret password!')
    } else if (event.currentTarget.nameField.value) {
      alert('this is a valid submission')
    }
  }
  const handleChange = event => {
    let isDisabled = false
    if (!event.currentTarget.nameField.value) isDisabled = true
    if (event.currentTarget.ageField.value <= 13) isDisabled = true
    event.currentTarget.submit.disabled = isDisabled
  }
  return (
    <form onSubmit={handleSubmit} onChange={handleChange}>
      <label>
        Name:
        <input type="text" name="nameField" placeholder="Must input a value"/>
      </label>
      <label>
        Age:
        <input type="number" name="ageField" placeholder="Must be >13" />
      </label>
      <div>
        <input type="submit" value="Submit" name="submit" disabled />
      </div>
    </form>
  );
}

Feels weird to manipulate the form’s submit button disabled state directly 😅

You May Not Need Controlled Form Components →

Why you should probably avoid using <input type="number" />

The fine folks at GOV.UK:

Until now, the GOV.UK Design System date input component used the HTML element <input type="number" /> to provide a number keypad when a user enters dates.

However, we recently moved away from <input type="number"> to <input type="text" inputmode="numeric" pattern="[0-9]*">

Why the GOV.UK Design System team changed the input type for numbers →

Sounds familiar? That’s because the same recommendation was done in the HTML attributes to improve your users’ two factor authentication experience post 🙂

Netlify Forms – Manage forms and submissions without any server-side code

Wow, this is an awesome addition to Netlify:

On Netlify, any HTML form can instantly accept submissions—no backend code or infrastructure required. As soon as your form is deployed, you start seeing submissions appear in your Netlify dashboard.

Just add the netlify attribute to any form and everything gets wired up automatically.

Netlify will automatically create some backend code to handle the form submissions. The submissions will be stored and then shown in your control panel. Comes with a free tier of 100 submissions/month.

Netlify Forms →

Video by Phil Hawksworth

HTML attributes to improve your users’ two factor authentication experience

There are plenty of opportunities for friction in the user experience when logging in, particularly while entering a two factor authentication code. As developers we should be building applications that support the need for account security but don’t detract from the user experience. Sometimes it can feel as though these requirements are in a battle against each other.

In this post we will look at the humble <input> element and the HTML attributes that will help speed up our users’ two factor authentication experience.

The final markup to trigger the correct keyboard and have the browser autocomplete the received SMS code is this:

<input
  type="text"
  name="token"
  id="token"
  inputmode="numeric"
  pattern="[0-9]*"
  autocomplete="one-time-code"
/>

HTML attributes to improve your users’ two factor authentication experience →

🚨 Do note that 2FA using SMS is not secure, mainly due to the lacking policies at SIM providers easily allowing SIM port hacks. The recently announced origin-bound OTP addition as proposed by Webkit/Apple won’t make any difference in the case of a SIM hack.

React Hook Form – Form Validation Hook based on Uncontrolled Components

Now this is an interesting approach, building further upon Uncontrolled Components:

The React Hook Form (react-hook-form) library provides a new form validation mechanism which embraces uncontrolled form validation and support controlled components.

The core idea is to register HTML input’s ref into the custom hook and therefore subscribe to its input value, validate and evaluate the form submission.

I guess this one makes more sense to many as it immediately gives you a values object containing all form values. Validation is also built-in

import React from "react";
import useForm from "react-hook-form";

const Example = () => {
  const { handleSubmit, register, errors } = useForm();
  const onSubmit = values => {
    console.log(values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="email"
        ref={register({
          required: 'Required',
          pattern: {
            value: /^[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}$/i,
            message: "invalid email address"
          }
        })}
      />
      {errors.email && errors.email.message}

      <input
        name="username"
        ref={register({
          validate: value => value !== "admin" || "Nice try!"
        })}
      />
      {errors.username && errors.username.message}

      <button type="submit">Submit</button>
    </form>
  );
};

React Hook Form Presentation (Twitter Thread) →
React Hook Form →

💡 The React Hook Form Twitter Thread was compiled from its origin tweet to one single page using Threader

Making a Better Custom Select Element

24ways – the advent calendar for web geeks – is back! First post is “Making a Better Custom Select Element” in which Julie Grundy tries to create an accessible Custom Select Element:

Sometimes, I can’t recommend the select input. We want a way for someone to choose an item from a list of options, but it’s more complicated than just that. We want autocomplete options. We want to put images in there, not just text. The optgroup element is ugly, hard to style, and not announced by screen readers. The focus styles are low contrast. I had high hopes for the datalist element, but although it works well with screen readers, it’s no good for people with low vision who zoom or use high contrast themes.

Here’s a pen with the result:

Making a Better Custom Select Element →

An HTML attribute potentially worth $4.4M to Chipotle

Jason Grigsby:

I recently found myself racing to fill out Chipotle’s online order form before my mother could find her credit card. In the process, I discovered a bug that could cost Chipotle $4.4 million annually.

The form didn’t play nice with autocomplete and therefore would not get sent …

The culprit? A JS library which enforced a 2-digit pattern on the card details’ year field, thus truncating the autocompleted value (202320).

The solution? The pattern attribute, which the autocomplete feature can detect, thus passing in a correctly shortened valued (202323)

An HTML attribute potentially worth $4.4M to Chipotle →

Button Placement in Forms

Button placement on forms is often ignored or prioritised based on what looks good.

But button placement can make or break a form, and a form can make or break a user’s experience. That’s why it’s essential to get it right.

Here I’ll explain where to put buttons across a range of different forms based on research and best practice.

Where to put buttons on forms →

🤔 I found this one highly interesting to read as I tend to do the exact opposite when it comes to placing buttons. Inspired by macOS I place the primary button on the right, the secondary button to the left of the primary one, and the cancel option at the very left.

I’m wondering what Johan (Interface Designer) and Roel (Digital Accessibility Nerd) their take is on this …

UPDATE 2019.09.18: Thanks to (requested) input by Johan/Roel/Xavier we can safely conclude that the mentioned guidelines are not perfect.

As Johan mentions in the comments below:

I agree with your take mentioned in this blog post.

When there is only a single submit at the bottom of a typical form I do agree with aligning it left (in the linked post).

Roel also chimes in on placing the primary button on the right as all OS conventions do so. He however does wonder:

But, then again: web forms are not dialog windows…

As Xavier mentions on Twitter:

It doesn’t matter how your primary button is aligned. What matters is where all of the other buttons are relative to your primary action & inputs.

I think the main gist is that:

  • As the OS places primary actions on the right (in a left-to-right language that is), it’s a good idea to do so to as users are used to that.
  • If you do diverge from it, be consistent (cfr. Design Principle #9)

Thanks for the input y’all!