[popover][dialog] Select whole text in initially focused input#3751
[popover][dialog] Select whole text in initially focused input#3751michaldudak wants to merge 6 commits intomui:masterfrom
Conversation
commit: |
Bundle size report
Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Greptile SummaryThis PR implements automatic text selection for input fields when popovers and dialogs open, matching native platform behavior.
The implementation is clean, backward compatible, and includes proper error handling with try-catch around Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
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
|
| export function isSelectableInput( | ||
| element: Element | null, | ||
| ): element is HTMLInputElement | HTMLTextAreaElement { | ||
| if (!element || !isHTMLElement(element)) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
👍 Makes sense to have it consistent.
|
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 However, Radix's is better in the share example since you actually want the text selected explicitly: |
|
In the wild, there's a mix of both approaches. For example, macOS dialogs seem to select the text initially, but the native HTML |
|
Maybe as a compromise, we can delay the |
|
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 |
But it's always the first one by default, so it should be clear which ref to attach? Also, I think the explicit |
|
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 |
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
isSelectableInput()utility to detect text inputs/textareas that support selectionenqueueFocus()to accept anonFocusedcallback that runs immediately after focusFloatingFocusManagerto automatically select text in inputs when focusedImplementation Details
Text selection happens in the same
requestAnimationFrameas 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