Milly Software
InsightsEngagementMaking a Shopify Chat Widget Actually Usable With a Keyboard and a Screen Reader
Engagement··6 min read

Making a Shopify Chat Widget Actually Usable With a Keyboard and a Screen Reader

We put the Milly Chat widget through a systematic accessibility pass and found thirteen shopper-facing defects — invisible tab stops, focus thrown to the top of the page, a quiz that could not be finished with a keyboard, and a bottom bar covering the storefront footer. Here is what was broken and what we changed.

V
Viet Le
co-founder · Milly Software

A chat widget is a small piece of a storefront, which is exactly why its accessibility problems go unnoticed. Nobody files a support ticket saying the thumbs-up button disappeared from their tab order. They just stop using it.

We ran a systematic pass over the shopper-facing side of Milly Chat — every widget format, at every viewport, with a keyboard and a screen reader — and found thirteen defects. Each one was reproduced before the fix and verified after. This is what they were, because the pattern is more useful than the list.

Disabling a button under someone's finger

The most common failure by far, and it showed up in four separate places: a control disables itself the moment it is pressed.

With a mouse this is invisible. With a keyboard it is not. Focus was sitting on that button, the button left the accessibility tree, and the browser did the only thing it can do — it dropped focus back to the top of the document. On a normal storefront that is about 37 tab presses back to where the shopper was. On the quiz it happened at every single question.

The same shape appeared on the "Helpful?" vote under a reply, where both thumbs disabled on click. That one was worse: the control was removed from the tab order permanently. We counted past 120 tab presses without ever reaching it again. And it happened twice in a row on the checkout-critical path, when adding a recommended multi-variant product to the cart.

The fix is the same everywhere. A control that is about to disappear has to hand focus somewhere deliberate first, and a control that has finished its job should stay in the tab order in a settled state rather than vanish from it.

Controls that were reachable but not visible

The banner and slideout formats keep their chat panel mounted while closed, parked outside the viewport. It was still fully in the tab order. A keyboard shopper tabbing off the storefront footer walked through seven invisible focus stops — a message input among them — with nothing on screen to explain where they were.

The quiz overlay had the inverse problem. It painted over the chat panel but was never actually modal, so six controls stayed live underneath it, including a message input that really did send messages the shopper could not see.

Nothing was announced at all

Sending a message announced nothing to a screen reader. The widget had no live region anywhere in it, so a reply arriving was, from assistive technology's point of view, not an event. Combined with the focus problem above — the composer's disabled state threw focus to the document body, and our own repair then called focus on a still-disabled input — a screen-reader user had no way to tell whether anything had happened.

Product cards had the same gap in a quieter form: variant swatches exposed no selection state, so the only signal that a size had been chosen was a visual one.

Layout failures that lock people out

Three of the thirteen were not assistive-technology issues at all. They were ordinary layout bugs that happened to make something unreachable, which is the same outcome.

  • The banner format's passive bar pushed its own chat input and Send button off-screen at every viewport between roughly 500px and 1140px, with no way to scroll to them.
  • That same fixed bar permanently covered the last 72 to 100 pixels of every page, which on most themes is the footer row carrying refund, privacy and shipping links. On mobile product pages it also hid the theme's own sticky add-to-cart bar.
  • On a landscape phone, or any viewport under about 624px tall, the chat panel's header scrolled above the top of the screen — and in that format the header holds the only close button. No escape key, no outside click, no scroll could reach it.

Two that were about honesty, not access

A failed send told the shopper to try again while deleting the question they had typed, so their only route back was to retype it. And a reply cut off mid-sentence by a dropped connection was presented as the finished answer — a half sentence the widget then invited them to rate, with the product recommendation it had already delivered silently discarded.

Both now say what actually happened and offer a real retry.

What we took from it

None of these were exotic. Every one of them is a pattern that a mouse user will never encounter and a keyboard user hits immediately, which is precisely why they survived months of ordinary testing. If you run any interactive widget on your storefront, the cheapest version of this audit is to unplug your mouse and try to buy something.

All thirteen fixes are live for every store, with nothing to turn on. For the rest of what shipped last month, see the July round-up.

Try Milly Chat

Want to see how this fits your store?
We'll set up a working session.

Get it on ShopifyTalk to sales →