Free

2026-09-11

base-uileptosfocus-managementreverse-engineering

Reverse-engineering Base UI's useDialog: the focus trap, mapped

Base UI's useDialog hook implements a sophisticated focus management system that ensures accessibility while providing a smooth user experience. This reverse-engineering analysis breaks down the focus trap mechanism and outlines strategies for porting to Leptos.

# Focus trap mechanics

The focus trap implementation in Base UI follows these key principles:

  1. Initial focus: When a dialog opens, focus is automatically moved to the first focusable element
  2. Tab navigation: Tab and Shift+Tab keys are intercepted to keep focus within the dialog
  3. Escape handling: The Escape key closes the dialog and returns focus to the trigger element
  4. Click outside: Clicks outside the dialog close it and restore focus

# Leptos porting considerations

The challenge with Leptos is that it doesn't have direct equivalents to React's imperative focus management. We'll need to:

dialog.rs
// Leptos equivalent concept (pseudocode)
#[component]
pub fn Dialog(children: Children) -> impl IntoView {
  let focus_manager = FocusManager::new();
  
  view! {
    <div
      on:focus=move |ev| { focus_manager.handle_focus(ev) }
      on:keydown=move |ev| { focus_manager.handle_keydown(ev) }
    >
      {children}
    </div>
  }
}

# Implementation patterns

The Base UI source reveals several important patterns:

  • Focusable element detection: Uses querySelectorAll with a specific selector
  • Focus restoration: Maintains a reference to the previously focused element
  • Event delegation: Uses a single event listener on the dialog container

This analysis provides the foundation for building an accessible Leptos dialog component.