Search code examples
javascriptdommaterial-uifocus

How to allow focus on two components, TextField and Popover, at the same time


I have a popover component that is rendered below a textfield component. The use case is to toggle a menu when a user types a special key such as : in to the textfield. The user can then click one of these menu items "autocomplete" the textfield.

A good example of this is GitHubs Hidden text expander feature.

github feature gif

I have two implementations. One implementation, which mui implements by default, creates a focus trap on the menu when it is opened, preventing the user from freely typing in to the textedit component. The menu component is then accessible with the keyboard controls such as ESC, ENTER, TAB as well as closes on blur.

To allow the user to continue typing in to the textfield while the menu is still open, I have disabled the autofocus on the popover menu component using some of the apis mui offers.

How can I accomplish something likes GitHubs feature that allows the component to have some accessibility while continuing to allow the user to freely type in to the textfield?

Here is the implementation that disables the focusing feature for the popover menu.

  return (
    <>
      <div className="card">
        <TextField
          fullWidth
          inputRef={inputRef}
          value={text}
          id="filled-basic"
          label="Filled"
          variant="filled"
          onChange={(e) => handleChange(e)}
        />
        <Menu
          id="demo-positioned-menu"
          aria-labelledby="demo-positioned-button"
          open={activeToken?.word === "#"}
          onClose={handleClick}
          anchorReference="anchorPosition"
          autoFocus={false}
          disableAutoFocus={true}
          disableEnforceFocus={true}
          anchorPosition={{
            top: t + 20,
            left: l
          }}
          anchorOrigin={{
            vertical: 'bottom',
            horizontal: 'right',
          }}
          transformOrigin={{
            vertical: 'top',
            horizontal: 'left',
          }}
        >
          <MenuItem onClick={() => handleClose('JavaScript')}>#JavaScript</MenuItem>
          <MenuItem onClick={() => handleClose('Clojure')}>#Clojure</MenuItem>
          <MenuItem onClick={() => handleClose('Python')}>#Python</MenuItem>
        </Menu>
      </div>
    </>
  )

Solution

  • I'm afraid you cannot focus on two elements at the same time. But you can handle the keyboard click event on the enclosing div, then do things according to which key is clicked.