mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.96k stars 32.27k forks source link

[TreeItem] override the default key handling #35032

Closed kartikKarekarGSLAB closed 1 year ago

kartikKarekarGSLAB commented 2 years ago

Duplicates

Latest version

Summary 💡

Hi,

I will be using the @mui/labs version "^5.0.0-alpha.98". I have added the implementation of the TreeView. I want the default key handling behaviour to be overriden by the custom one. I have passed the function for the same using the prop "onKeyDown" but, looking from the source code of the source code of TreeItem, the function passed as prop will be called at the last of the key event handler function.

const handleKeyDown = event => {
    let flag = false;
    const key = event.key;

    if (event.altKey || event.currentTarget !== event.target) {
      return;
    }

    const ctrlPressed = event.ctrlKey || event.metaKey;

    switch (key) {
      case ' ':
        if (nodeRef.current === event.currentTarget) {
          if (multiSelect && event.shiftKey) {
            selectRange(event, { end: nodeId });
          } else if (multiSelect) {
            selectNode(event, nodeId, true);
          } else {
            selectNode(event, nodeId);
          }

          flag = true;
        }
        event.stopPropagation();
        break;
      case 'Enter':
        if (nodeRef.current === event.currentTarget && expandable) {
          toggleExpansion(event);
          flag = true;
        }
        event.stopPropagation();
        break;
      case 'ArrowDown':
        if (multiSelect && event.shiftKey) {
          selectNextNode(event, nodeId);
        }
        focusNextNode(nodeId);
        flag = true;
        break;
      case 'ArrowUp':
        if (multiSelect && event.shiftKey) {
          selectPreviousNode(event, nodeId);
        }
        focusPreviousNode(nodeId);
        flag = true;
        break;
      case 'ArrowRight':
        if (theme.direction === 'rtl') {
          flag = handlePreviousArrow(event);
        } else {
          flag = handleNextArrow(event);
        }
        break;
      case 'ArrowLeft':
        if (theme.direction === 'rtl') {
          flag = handleNextArrow(event);
        } else {
          flag = handlePreviousArrow(event);
        }
        break;
      case 'Home':
        if (multiSelect && ctrlPressed && event.shiftKey) {
          rangeSelectToFirst(event, nodeId);
        }
        focusFirstNode();
        flag = true;
        break;
      case 'End':
        if (multiSelect && ctrlPressed && event.shiftKey) {
          rangeSelectToLast(event, nodeId);
        }
        focusLastNode();
        flag = true;
        break;
      default:
        if (key === '*') {
          expandAllSiblings(event, nodeId);
          flag = true;
        } else if (multiSelect && ctrlPressed && key.toLowerCase() === 'a') {
          selectAllNodes(event);
          flag = true;
        } else if (isPrintableCharacter(key)) {
          flag = printableCharacter(event, key);
        }
    }

    if (flag) {
      event.preventDefault();
      event.stopPropagation();
    }

    if (onKeyDown) {
      onKeyDown(event);
    }
  };

Please find the sample of the my code snippet as ,

<TreeItem
      nodeId={nodes?.id}
      onKeyDown={(event: React.SyntheticEvent) => {
          console.debug('RenderTreeNode.onKeyDown the keydown event callback');
          event.stopPropagation();
          event.preventDefault();
      }}></TreeItem>

I want the default key event handler to be overriden by the props function.

Please suggest me the better way to do the same.

ZeeshanTamboli commented 2 years ago

@kartikKarekarGSLAB What is the issue? Does your onKeyDown prop passed to TreeItem not get executed? It doesn't matter if it's in the last. Can you provide a CodeSandbox that showcases your problem? The issue template is a good starting point.

kartikKarekarGSLAB commented 2 years ago

Hey, @gzrae @michaldudak and @siriwatknp for adding tags and looking into the same.

Hope you guys are cleared with the issue I am facing for the TreeView's TreeItem component.

Please let me know if more inputs reuired

kartikKarekarGSLAB commented 2 years ago

Hi @ZeeshanTamboli,

Thank you for adding the respond. I have added the TreeView implementation as below,

<TreeView
      ref={extendedTreeViewRef}
      // The default icon used to collapse the node.
      defaultCollapseIcon={<ArrowDropDownIcon className="icon-responsive" />}
      // The default icon used to expand the node.
      defaultExpandIcon={<ArrowRightIcon className="icon-responsive" />}
      // Callback fired when tree items are selected/unselected.
      onNodeSelect={props?.onNodeSelect}
      // Styling for the tree.
      className={props?.className}
      {...props?.other}
      onKeyDown={(event: React.SyntheticEvent) => {
          console.debug('RenderTreeNode.onKeyDown the keydown event callback. From TreeView. event=', event);
          event.stopPropagation();
          event.preventDefault();
      }}>
                /*Here treeItems where inside the loop*/
</TreeView>

And also added theh calback,

<TreeItem
      label={<TreeLeafNode labelText={labelText} labelInfo={labelInfo} focusKey={props?.nodeId} />}
      {...other}
      onKeyDown={(event: React.SyntheticEvent) => {
          console.debug('Render TreeItem.onKeyDown this callback is for the TreeItem);
          event.stopPropagation();
          event.preventDefault();
      }}
/>

I have added the callback at both the places,. Please do check and let me know which is the right place for adding the keyDown callback.

ZeeshanTamboli commented 2 years ago

@kartikKarekarGSLAB But what is the issue exactly?

Please do check and let me know which is the right place for adding the keyDown callback.

oKeyDown callback is on TreeView component. See https://codesandbox.io/s/keen-fermat-ur2zsb?file=/src/App.tsx.

kartikKarekarGSLAB commented 2 years ago

@ZeeshanTamboli The issue I am facing is as below,

The default implementation for keys 'left', 'right', 'down', 'up' needed to be overriden.

Default key down callback implementation. (The library code added in the description of this issue )

I have added the tree as navigation menu for the application, and when right arrow click I want to trasfer the control to the Main section.

ZeeshanTamboli commented 2 years ago

@kartikKarekarGSLAB The tree view is fully accessible. You can make a Controlled tree view and navigate as per your use case. See https://mui.com/material-ui/react-tree-view/#controlled-tree-view.

Can you provide a minimal reproduction in a CodeSandbox that I can look into and replicate your use case? The issue template is a good starting point. It's difficult to understand different use cases without a reproduction and decide whether it's possible or not with the current API.

Also its better to ask this type of question on Stack Overflow first.

github-actions[bot] commented 1 year ago

Since the issue is missing key information and has been inactive for 7 days, it has been automatically closed. If you wish to see the issue reopened, please provide the missing information.