Skip to content

[popover][dialog] Select whole text in initially focused input#3751

Open
michaldudak wants to merge 6 commits intomui:masterfrom
michaldudak:select-input-content-in-popover
Open

[popover][dialog] Select whole text in initially focused input#3751
michaldudak wants to merge 6 commits intomui:masterfrom
michaldudak:select-input-content-in-popover

Conversation

@michaldudak
Copy link
Copy Markdown
Member

When a Popover or Dialog contains a text input, the input is now correctly focused with all text selected upon opening, matching native popover behavior.

Changes

  • Added isSelectableInput() utility to detect text inputs/textareas that support selection
  • Enhanced enqueueFocus() to accept an onFocused callback that runs immediately after focus
  • Updated FloatingFocusManager to automatically select text in inputs when focused

Implementation Details

Text selection happens in the same requestAnimationFrame as the focus operation, ensuring no visual flicker and matching native platform behavior. The changes are backward compatible and only affect text inputs/textareas (excludes checkboxes, radios, etc.).

Fixes #1523

@michaldudak michaldudak added component: dialog Changes related to the dialog component. component: popover Changes related to the popover component. labels Jan 15, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 15, 2026

  • vite-css-base-ui-example

    pnpm add https://pkg.pr.new/mui/base-ui/@base-ui/react@3751
    
    pnpm add https://pkg.pr.new/mui/base-ui/@base-ui/utils@3751
    

commit: 8be7c1d

@mui-bot
Copy link
Copy Markdown

mui-bot commented Jan 15, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+117B(+0.03%) 🔺+51B(+0.04%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 15, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 8be7c1d
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/697091c2fea7600008971a3f
😎 Deploy Preview https://deploy-preview-3751--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@michaldudak michaldudak marked this pull request as ready for review January 16, 2026 10:23
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jan 16, 2026

Greptile Summary

This PR implements automatic text selection for input fields when popovers and dialogs open, matching native platform behavior.

  • Added isSelectableInput() utility to safely detect text inputs/textareas that support .select(), excluding checkboxes, radios, file inputs, and other non-text types
  • Extended enqueueFocus() with an onFocused callback that executes immediately after focusing, within the same requestAnimationFrame
  • Integrated text selection in FloatingFocusManager by calling .select() on selectable inputs when they receive initial focus
  • Added comprehensive test coverage for various input types and edge cases

The implementation is clean, backward compatible, and includes proper error handling with try-catch around .select() calls.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is well-architected with proper separation of concerns, comprehensive test coverage, defensive error handling, and backward compatibility. The changes are isolated and follow established patterns in the codebase.
  • No files require special attention

Important Files Changed

Filename Overview
packages/react/src/floating-ui-react/utils/element.ts Added isSelectableInput() utility function to detect text inputs/textareas that support selection, excluding non-selectable types like checkboxes and disabled inputs
packages/react/src/floating-ui-react/utils/enqueueFocus.ts Enhanced with onFocused callback parameter that executes immediately after focus in the same requestAnimationFrame
packages/react/src/floating-ui-react/components/FloatingFocusManager.tsx Integrated text selection behavior by calling isSelectableInput() and .select() via the onFocused callback when focusing inputs on popover/dialog open
packages/react/src/popover/popup/PopoverPopup.test.tsx Added comprehensive test coverage for text selection behavior including inputs, textareas, checkboxes, empty values, readonly inputs, and custom initialFocus

Sequence Diagram

sequenceDiagram
    participant User
    participant PopoverTrigger
    participant FloatingFocusManager
    participant enqueueFocus
    participant InputElement

    User->>PopoverTrigger: Click trigger
    PopoverTrigger->>FloatingFocusManager: Open popover
    FloatingFocusManager->>FloatingFocusManager: Determine element to focus
    FloatingFocusManager->>enqueueFocus: Call with element & onFocused callback
    enqueueFocus->>enqueueFocus: Schedule in requestAnimationFrame
    enqueueFocus->>InputElement: focus()
    enqueueFocus->>FloatingFocusManager: Invoke onFocused(element)
    FloatingFocusManager->>FloatingFocusManager: Check isSelectableInput(element)
    alt Is selectable text input
        FloatingFocusManager->>InputElement: select()
        InputElement->>User: Text is fully selected
    else Not selectable (checkbox, radio, etc)
        FloatingFocusManager->>User: Element focused without selection
    end
Loading

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jan 16, 2026
Comment on lines +89 to +94
export function isSelectableInput(
element: Element | null,
): element is HTMLInputElement | HTMLTextAreaElement {
if (!element || !isHTMLElement(element)) {
return false;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unnecessary. Form just checks if the tagName === 'INPUT' because if it's type="checkbox" etc., it doesn't actually do anything (and doesn't error either)

I also don't think <textarea>s should be selected (which Form also doesn't do)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Makes sense to have it consistent.

@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Jan 19, 2026
@atomiks
Copy link
Copy Markdown
Contributor

atomiks commented Jan 21, 2026

I'm kind of wondering if this is even actually a good default that Radix does?

It feels better not to select the whole text in the first example to me.

Radix: https://ui.shadcn.com/docs/components/radix/dialog
Base: https://ui.shadcn.com/docs/components/base/dialog

However, Radix's is better in the share example since you actually want the text selected explicitly:
https://ui.shadcn.com/docs/components/radix/dialog#custom-close-button

@michaldudak
Copy link
Copy Markdown
Member Author

In the wild, there's a mix of both approaches. For example, macOS dialogs seem to select the text initially, but the native HTML <dialog> does not. Tabbing between fields selects the content, though.

@atomiks
Copy link
Copy Markdown
Contributor

atomiks commented Jan 22, 2026

Maybe as a compromise, we can delay the initialFocus function call into the rAF/enqueueFocus (to avoid scroll issues), so users can just do initialFocus={() => inputRef.current?.select()}

@michaldudak
Copy link
Copy Markdown
Member Author

This could be a bit hard to use, as they don't know which input will be initially focused. A better option, DX-wise, would be to have an onInitiallyFocused(element: HTMLElement) prop

@atomiks
Copy link
Copy Markdown
Contributor

atomiks commented Jan 22, 2026

This could be a bit hard to use, as they don't know which input will be initially focused. A better option, DX-wise, would be to have an onInitiallyFocused(element: HTMLElement) prop

But it's always the first one by default, so it should be clear which ref to attach? Also, .select() both focuses and selects, so focus will be taken from whichever other input was chosen

I think the explicit .select() for copy inputs as in the shadcn example, where you need to attach a ref, is fine/explicit

@michaldudak
Copy link
Copy Markdown
Member Author

If you have a reusable Dialog component, you won't have a ref to what's inside. Also requiring a ref moves the responsibility to call this to the styled component user, whereas onInitiallyFocused allows handling it on the design system component level.

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: dialog Changes related to the dialog component. component: popover Changes related to the popover component. PR: out-of-date The pull request has merge conflicts and can't be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[popover] Select inputs on focus

3 participants