One of the things I find constantly grating about living in Europe is the low standard of web-development. Perhaps it’s a symptom of having to waste development effort on ridiculous EU-specific “privacy” protections, but I hardly think that’s an excuse.

One of those super annoying and completely pointless EU cookie dialogs. This one is on DHL's website.

A lot of the websites in question seem to be developed with React—they typically look quite modern and exhibit some common behaviors of React widget libraries—and I suspect this might be a root cause.

Screen capture of a phone-number field on's website. It's written in React.

Here’s a phone number field from‘s account page. It’s written in React (as if you couldn’t tell) and just look at all that stuff. It even knows it’s a type="tel" field and requires has its pattern set. But they didn’t bother to configure autocomplete so I need to type my phone number in manually.

The problem is that React and Typescript are both hostile to <input> fields:

  • React by doesn’t update <input> fields properly and so you need a convenient wrapper to prevent weird misbehavior from selections and unnecessary redraws.
  • Typescript doesn’t really deal with DOM manipulation nicely. E.g. just setting the value of an <input> to a number requires unnecessary type conversions or ridiculous assertions or flat-out overrides:
    • inputElement.value = String(numberValue)
    • inputElement.value = numberValue as unknown as string
    • // eslint-disable-next-line
      inputElement.value = numberValue
      and it’s even more painful if you obtained the inputElement using a query…)

As far as I can tell, it’s impossible to declare types for most DOM elements correctly in Typescript. I’d call that a design failure, but apparently it’s wonderful and reduces errors-per-line-of-code by almost as much as it increases lines-of-code.

So, rather than deal with all that, many developers use React components instead, and React components typically don’t support all the incredible usability benefits of basic HTML <input> elements without a fair bit of extra effort.

This is the problem with having useless, leaky abstraction layers. There’s no UI library I’ve found that gives you an <input> field replacement that exposes all of the fantastic functionality built into a basic <input> field, and certainly none that uses as few resources or is as easy to code. But, by wrapping it in a component, whether it’s a React component, an Angular component, or a web-component, you are definitely:

  • damaging accessibility,
  • increasing load time and resource overhead,
  • and preventing developers from learning stuff that will be useful as long as web-browsers exist. Hint: this will be longer than the component library you’re using.

What’s really depressing is that you’re also typically getting a less-functional <input> element.

The most annoying things I come across involve poor support for autocomplete typically accompanied by poor support for data-entry. You’ll often have to enter special numeric codes (e.g. in Finland every bill has a reference number that’s quite long) or phone numbers and:

  1. Often, assuming they’re using an <input> they won’t even set its type properly (e.g. to number or tel or email) so instead of getting the correct dedicated keyboard on your mobile device, you get the full qwerty keyboard and need to switch around to enter hyphens or manually type bits of urls. DHL went to the trouble of disabling autocomplete in their phone number field for setting up tracking options—and if you enter a phone number with spaces in it they tell you to remove them rather than just doing it themselves. I tried to leave feedback for them, but they’ve wisely made this impossible.
  2. Even if they get the <input>‘s type right, they’ll almost certainly not set the autocomplete values properly. This is something that literally takes a few minutes of coding to get right in basic HTML—and probably saves several minutes, and quite a bit of frustration, for every mobile user. It would have saved me from writing this rant.

I don’t have accessibility issues (beyond poor but corrected eyesight) so I have no clue how much additional suffering this is inflicting on impaired users. One of the nicest things about using <input> fields is that not only have they been thoroughly tested over the years, but screen-readers not only leverage their native behavior, but have a pretty good chance of figuring out how to use them if misconfigured. But once they’re wrapped in your widget library, who knows?