Enhancing ESHOPMAN Storefront Accessibility: Resolving Focus Management in Interactive Prompts

At Move My Store, we constantly monitor the ESHOPMAN community for insights that empower merchants and developers alike. A recent discussion highlighted a crucial aspect of user experience and accessibility within ESHOPMAN's interactive elements: proper keyboard focus management.

The Challenge: Lost Focus in ESHOPMAN Prompts

The ESHOPMAN platform, built on Node.js/TypeScript and designed for seamless storefront management and deployment via HubSpot CMS, provides a powerful set of UI components. One such component is the usePrompt hook, essential for displaying confirmation dialogs or alerts within ESHOPMAN storefronts or custom admin interfaces. However, a specific bug was identified where, upon closing a usePrompt dialog, keyboard focus would unexpectedly shift to the document's main body (document.body) instead of returning to the element that originally triggered the prompt.

This behavior is particularly disruptive when prompts are opened from within other focused components, such as a Drawer or a FocusModal. Imagine a user navigating an ESHOPMAN storefront with a keyboard: they open a prompt to confirm an action, then cancel it. Instead of returning to the button they just clicked, their next 'Tab' press might inadvertently move focus to an element far removed from their current context, potentially even behind the open drawer. This significantly degrades the user experience and violates accessibility best practices for keyboard navigation.

Understanding the Technical Root Cause

The core of the issue lies in how ESHOPMAN's usePrompt hook renders its dialogs. Unlike standard dialogs that might be directly associated with a "trigger" element, usePrompt renders its content (RenderPrompt) into a detached React root. While the underlying UI library typically handles focus restoration by returning focus to the trigger element when a dialog closes, this mechanism fails when no explicit trigger is present or recognized in this detached rendering context. Consequently, the system defaults focus to document.body.

Consider this minimal reproduction example within an ESHOPMAN component:

const Example = () => {
  const prompt = usePrompt()

  return (
    
      
        Item
        
      
    
  )
}

In this scenario, if a user tabs to the "Delete" button, presses Enter to open the prompt, and then selects "Cancel," the keyboard focus would land on document.body, disrupting the flow within the Drawer.

The ESHOPMAN Community's Proposed Solution

A keen ESHOPMAN community member identified this behavior and proposed an elegant solution. The strategy involves manually managing focus: before the prompt() function is called (i.e., before the dialog opens), the currently active element (document.activeElement) is saved. Then, once the prompt closes, whether through "Cancel" or "Confirm," focus is explicitly restored to that saved element. This ensures a seamless and predictable user experience, adhering to accessibility standards.

This fix would be implemented within the ESHOPMAN UI's use-prompt.tsx, capturing the active element before the dialog mounts and refocusing it after the root unmounts in both the onCancel and onConfirm handlers.

What This Means for ESHOPMAN Developers and Merchants

This discussion underscores ESHOPMAN's commitment to building a robust and accessible headless commerce platform. While an automated attempt to integrate this fix initially faced validation challenges, the ESHOPMAN team has escalated the issue and is actively working on incorporating this critical improvement. For developers building custom storefronts or extending ESHOPMAN's Admin API functionalities, understanding such UI intricacies is vital for delivering exceptional user experiences on HubSpot CMS-deployed storefronts.

The collaborative spirit of the ESHOPMAN community, where technical challenges are identified and solutions proposed, is a testament to the platform's vibrant ecosystem. Stay tuned for updates as ESHOPMAN continues to refine its UI/UX, ensuring that every interaction, from storefront browsing to administrative tasks, is intuitive and accessible for all users.

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools