mui-x icon indicating copy to clipboard operation
mui-x copied to clipboard

[tree view] Can't focus input inside TreeItem label

Open IDrumsey opened this issue 1 year ago • 5 comments

Steps to reproduce

Yeah sry, codesandbox was giving me trouble and this is pretty simple I think. I just want to be able to disable the focusing of TreeItems.

The culprit lines I believe are just these.

https://github.com/mui/mui-x/blob/ef40e06213d4721c51d498328f4fadf8e545b3e7/packages/x-tree-view/src/TreeItem/TreeItem.tsx#L292-L297

Maybe we can add a prop or something to just disable running that?

Current behavior

If you do something like

<SimpleTreeView>
  <TreeItem itemId={1} label={<input type="text"/>} />
</SimpleTreeView>

when you click on the input, the TreeItem overrides focusing on the input in favor of the tree item, which essentially means you can't actually use the input.

Expected behavior

Would like to be able to use the input. See suggested solution above.

Context

No response

Your environment

npx @mui/envinfo
System:
    OS: Windows 11 10.0.22631
  Binaries:
    Node: 18.19.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: Not Found
  Browsers:
    Chrome: Not Found
    Edge: Chromium (123.0.2420.65)
  npmPackages:
    @emotion/react: ^11.11.4 => 11.11.4 
    @emotion/styled: ^11.11.0 => 11.11.0
    @mui/base:  5.0.0-beta.40
    @mui/core-downloads-tracker:  5.15.14
    @mui/icons-material: ^5.15.14 => 5.15.14
    @mui/material: ^5.15.14 => 5.15.14
    @mui/material-nextjs: ^5.15.11 => 5.15.11
    @mui/private-theming:  5.15.14
    @mui/styled-engine:  5.15.14
    @mui/system:  5.15.14
    @mui/types:  7.2.14
    @mui/utils:  5.15.14
    @mui/x-tree-view: ^7.1.0 => 7.1.0
    @types/react: ^18 => 18.2.67
    react: ^18 => 18.2.0
    react-dom: ^18 => 18.2.0
    typescript: ^5 => 5.4.3

Search keywords: treeitem

IDrumsey avatar Mar 30 '24 21:03 IDrumsey

Hi, @IDrumsey 👋

Thanks for opening this issue 😄

I double checked and you are right. The focus is always set to the root of the tree item with a specific itemId, and we don't support focusing inner elements of the tree items 😬

A workaround I can think of is using the onItemFocus callback and implement a custom behavior

 onItemFocus={(e, itemId) => {
    const input = document.getElementById(`input-${itemId}`);
    input.focus();
 }}

I will add this to the list of topics to discuss with the team to see if we can come up with a nicer solution 👌

noraleonte avatar Apr 01 '24 12:04 noraleonte

Is it a regression from https://github.com/mui/material-ui/pull/18894? But the test we added in that PR is still present:

https://github.com/mui/mui-x/blob/ef40e06213d4721c51d498328f4fadf8e545b3e7/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx#L2325-L2350

oliviertassinari avatar Apr 01 '24 13:04 oliviertassinari

If you're preventing default then that's probably why it's working.

IDrumsey avatar Apr 02 '24 12:04 IDrumsey

Hi, @IDrumsey 👋

Thanks for opening this issue 😄

I double checked and you are right. The focus is always set to the root of the tree item with a specific itemId, and we don't support focusing inner elements of the tree items 😬

A workaround I can think of is using the onItemFocus callback and implement a custom behavior

 onItemFocus={(e, itemId) => {
    const input = document.getElementById(`input-${itemId}`);
    input.focus();
 }}

I will add this to the list of topics to discuss with the team to see if we can come up with a nicer solution 👌

Hi @noraleonte , The suggested workaround does not work when other items are not text inputs. Consider the following example:

<SimpleTreeView
     onItemFocus={(e, itemId) => {
      const input = document.getElementById(`input-${itemId}`);
      input?.focus();
   }}
  >
  <TreeItem itemId="1" label={<input type="text" id="input-1" />} />
  <TreeItem itemId="2" label="B Item" />
  <TreeItem itemId="3" label="C Item" />
</SimpleTreeView>

In this case, as soon as I'll type the B or C letters the focus will switch to another item.

coxantohi avatar Aug 23 '24 12:08 coxantohi

Hey @coxantohi 👋 I think that in a generic use case, you should be able to work around this issue with a tabIndex and potentially some checks on the callbacks. But I think I would need a more specific reproduction case to figure it out. However, if what you are trying to solve is an editable tree item, we just released a label editing feature available for the RichTreeView and it might be interesting for you 😸

noraleonte avatar Aug 23 '24 12:08 noraleonte

I've discovered another workaround that utilizes event.stopPropagation to capture event bubbling. This method effectively prevents parent nodes from reacting to click and keydown events.

Here's a working example from my implementation:

<TreeItem
  key={`${nodeId}-empty`}
  itemId={`${nodeId}-empty`}
  label={
    <input
      onKeyDownCapture={(e) => e.stopPropagation()}
      onClickCapture={(e) => e.stopPropagation()}
    />
  }
/>

mnixry avatar Sep 10 '24 16:09 mnixry

Same problem here: Screencast from 2024-09-18 11-28-57.webm

"@mui/material": "^5.15.14",
"@mui/x-tree-view": "^7.0.0"
<TreeItem
    ref={(ref) => autoFocus ? autoFocusRef(ref) : null}
    sx={{'& .MuiTreeItem-iconContainer': {display: 'none'}}}
    itemId={nodeId}
    label={
        <Box
            component={'form'}
            onSubmit={handleSubmit}
            sx={{display: 'flex', flexDirection: 'row', alignItems: 'center', flex: 1}}>
            <TextField
                inputRef={autoFocus}
                autoFocus
                variant="standard"
                size="small"
                sx={{flex: 1}}
                value={value}
                onChange={handleChange}
                InputProps={{
                    endAdornment:
                        <ButtonGroup
                            color="inherit"
                            variant="text"
                            aria-label="text button group">
                            <Button onClick={submitFunc}>
                                <DoneIcon sx={{fontSize: 18}}/>
                            </Button>
                            <Button onClick={cancelFunc}>
                                <CloseIcon sx={{fontSize: 18}}/>
                            </Button>
                        </ButtonGroup>
                }}
            />
        </Box>}
/>

I had to use @mnixry solution and worked, but it's a quirk

stephzero1 avatar Sep 18 '24 09:09 stephzero1