Troubleshooting Focus Trap Issues with Entri Connect

Last updated: August 15, 2025

Overview

This guide helps developers resolve focus trap conflicts that can occur when integrating Entri Connect with React UI libraries.

What is a Focus Trap?

A focus trap is an accessibility feature that constrains keyboard navigation (Tab key) within a specific area of your application, typically a modal or dialog. When a modal opens, the focus trap ensures that:

  • Focus moves to the first focusable element inside the modal

  • Tab navigation cycles only through elements within the modal

  • Focus cannot escape to background content until the modal is closed

  • Screen readers and keyboard users can navigate the modal effectively

Focus traps are essential for accessibility compliance and provide a better user experience for keyboard navigation and assistive technologies.

The Problem

When using Entri Connect alongside React UI libraries that implement their own focus management (such as Reach UI's Dialog component), you may experience:

  • Focus conflicts: Two systems trying to control focus simultaneously

  • Broken tab navigation: Tab key not working as expected within modals

  • Accessibility issues: Screen readers unable to navigate properly

  • Poor user experience: Unpredictable focus behavior

This occurs because both Entri Connect and your modal library are competing for focus control, creating a "battle" between the two systems.

Issue Details

Our development team has identified that this issue specifically occurred with the Reach UI Dialog component, but it doesn't mean it could occur with other libraries like Radix UI.

The Reach UI Dialog applies aggressive focus locking and a conflict arises when Entri Connect attempts to regain focus control.

Solutions

We provide two primary solutions based on our development team's analysis:

Solution 1: Embedded Mode Integration (Recommended)

Mount the Entri Connect modal inside your existing Reach UI Dialog using embedded mode.

import { Dialog, DialogOverlay, DialogContent } from "@reach/dialog";
import "@reach/dialog/styles.css";

function MyComponent() {
  const [isOpen, setIsOpen] = useState(false);

  const handleEntriSetup = () => {
    window?.entri.showEntri({
      applicationId: "your-app-id",
      token: "your-jwt-token",
      dnsRecords: [/* your DNS records */],
      whiteLabel: {
        customProperties: {
          general: {
            embeddedMode: {
              selector: "#entri-container", // Target container
              containerStyles: {
                boxShadow: "none", // Remove default shadow 
                borderRadius: "0px", // Remove border radius
                width: "100%",
                height: "100%",
              },
            },
          }
        }
      }
    });
  };

  React.useEffect(() => {
    if (isOpen) {
      handleEntriSetup();
    }
  }, [isOpen]);

  return (
    <Dialog isOpen={isOpen} onDismiss={() => setIsOpen(false)}>
      <DialogOverlay>
        <DialogContent>
          <div id="entri-container">
            {/* Entri Connect will render here */}
          </div>
        </DialogContent>
      </DialogOverlay>
    </Dialog>
  );
}

Solution 2: Custom Focus Management

Use Reach UI components with manual focus control and delegate focus to Entri Connect when needed.

import { DialogOverlay, DialogContent } from "@reach/dialog";
import FocusLock from "react-focus-lock";

function CustomFocusModal() {
  const [isOpen, setIsOpen] = useState(false);
  const [entriActive, setEntriActive] = useState(false);

  const launchEntri = () => {
    setEntriActive(true);
    
    window?.entri.showEntri({
      applicationId: "your-app-id",
      token: "your-jwt-token",
      dnsRecords: [/* your DNS records */]
    });
  };

  const handleEntriClose = () => {
    setEntriActive(false);
  };

  useEffect(() => {
    window.addEventListener('onEntriClose', handleEntriClose);
    return () => window.removeEventListener('onEntriClose', handleEntriClose);
  }, []);

  return (
    <DialogOverlay isOpen={isOpen}>
      <DialogContent>
        <FocusLock disabled={entriActive}>
          <div>
            <h2>Your Modal Content</h2>
            <button onClick={launchEntri}>Setup Domain</button>
          </div>
        </FocusLock>
      </DialogContent>
    </DialogOverlay>
  );
}

Implementation Guidelines

For Embedded Mode

  • Use the correct embedded mode configuration with general.embeddedMode.selector

  • Include containerStyles to customize the appearance within your modal

  • Call handleEntriSetup() when your modal opens using useEffect

  • Ensure the target container element exists before calling window?.entri.showEntri()

For Custom Focus Management

  • Use window?.entri.showEntri() to access the global Entri instance

  • Use react-focus-lock or similar library for fine-grained control

  • Disable your focus trap when Entri Connect is active using the disabled prop

  • Re-enable focus management after Entri Connect closes


Need additional help? Contact our support team through the Entri dashboard or visit our help center for more resources.