A react component that displays an unlimited deep menu

Overview

react-infinity-menu

Circle CI

Demo

Awesome demo

Installation

npm install react-infinity-menu

How to use

); } } ">
import InfinityMenu from "react-infinity-menu";
import "react-infinity-menu/src/infinity-menu.css";

class Example extends React.Component {
	onNodeMouseClick(event, tree, node, level, keyPath) {
		this.setState({
			tree: tree
		});
	}

	onLeafMouseClick(event, leaf) {
		console.log( leaf.id ); // Prints the leaf id
		console.log( leaf.name ); // Prints the leaf name
	}

	onLeafMouseUp(event, leaf) {
		console.log( leaf.id ); // Prints the leaf id
		console.log( leaf.name ); // Prints the leaf name
	}

	onLeafMouseDown(event, leaf) {
		console.log( leaf.id ); // Prints the leaf id
		console.log( leaf.name ); // Prints the leaf name
	}

	render() {
		return (
			<InfinityMenu
				tree={this.state.tree}
				onNodeMouseClick={this.onNodeMouseClick}
				onLeafMouseClick={this.onLeafMouseClick}/*optional*/
				onLeafMouseDown={this.onLeafMouseDown}/*optional*/
				onLeafMouseUp={this.onLeafMouseUp}/*optional*/
				maxLeaves={5}/*optional*/
			/>
		);
	}
}

Properties

tree(Array)

A tree to represent the folder structure. Here is the example data you could pass into the tree props.

[
	{
		name: "menu1", /*require*/
		id: 1, /*require*/
		isOpen: true, /*require*/
		customComponent: YOUR_OWN_COMPONENT_FOR_MENU,
		children: [
			{
				name: "submenu1",
				id: 1,
				isOpen: true,
				customComponent: YOUR_OWN_COMPONENT_FOR_SUB_MENU,
				children: [
					{
						name: "item1-1",
						id: 1
					},
					{
						name: "item1-2",
						id: 2
					}
				]
			},
			{
				name: "submenu2",
				id: 2,
				isOpen: true,
				customComponent: YOUR_OWN_COMPONENT_FOR_SUB_MENU,
				children: [
					{
						name: "item2-1",
						id: 1
					}
				]
			}
		]
	},
	{
		name: "menu2", /*require*/
		id: 2, /*require*/
		isOpen: true, /*require*/
		customComponent: YOUR_OWN_COMPONENT_FOR_MENU,
		children: [
			{
				name: "item3-1",
				id: 1
			}
		]
	}
];

disableDefaultHeaderContent (boolean)

A boolean to set if user want to display the default header search input. If user pass in headerContent, the default header will be disabled.

headerContent(React Component)

Subcomponent rendered above the tree.

headerContent is passed in to InfinityMenu. It is rendered above the tree subcomponent.

headerProps(object)

Additional props for headerContent.

  • headerProps is an optional prop of InfinityMenu. The props in this object are passed as props to a headerContent component. This is useful when extending InfinityMenu.

Passing the following into InfinityMenu as the headerProps prop sets the title prop on the headerContent component.

{
	title: "my great title"
}

customComponentMappings (object)

A mapping that let user to pass in customComponent as string.

var myComponentMappings = {
    "MyComponent1": MyComponent1,
    "MyComponent2": MyComponent2
}

customComponent(React Component)

A custom React component the user can pass in.

  • As the customComponent at the node level, you will receive props key, onClick, name, isOpen, data and isSearching.

  • As the customComponent at the leaf level, you will receive props key, onMouseDown, onMouseUp, onClick, name, icon and data.

    Example of customComponent

    class Node extends React.Component {
        render() {
            return (
                <div key={this.props.key} onClick={this.props.onClick}>
                    <label>{this.props.name}</label>
                </div>
            );
        }
    }

filter(function)[node, searchInput]

By default, when the menu is in searching mode, it will filter all nodes by whether their name is equal to the current searchInput. If the node name is equal to the searchInput, then the node will pass the filter and be displayed in tree (if it fails the filter, it will not be displayed in the tree).

This allows the user to specify their own filtering criteria. When the menu is in search mode, every node will be run against the filter() function:

  • If the function returns true, the node will pass the filter, and be displayed in the tree.
  • If the function returns false, the node will fail the filter, and will not be displayed in the tree.

The function takes the following arguments:

  • node (object) is the folder(node) the user clicked on. Includes the following properties: id, name, isOpen and children.
  • searchInput (string) The current search term

emptyTreeComponent (React Component)

If the tree prop is an empty array or if the menu is in searching mode and no nodes match the filter, then the tree is considered "empty".

By default, nothing will be displayed in an empty tree.

However, if this prop is passed in, the specified component will be rendered when the tree is empty.

This allows you have a very customized "empty tree" message/image.

emptyTreeComponentProps (object)

Allows you to specify props to pass to the emptyTreeComponent.

By default, this is an empty object.

onNodeMouseClick(function)[event, tree, node, level, keyPath]

This function will get call when user click on the folder(node). The function arguments include event, tree, node and level.

  • event is the mouse click event.
  • tree is the updated tree, you should update your own tree accordingly.
  • node is the folder(node) the user clicked on. Including the id, name, isOpen and children.
  • level is the distance from the root.
  • keyPath is the path from root to current node

onLeafMouseClick(function)[event, leaf]

Bind to the onClick on the leaf. This function will get call when user click on the item(leaf). The function arguments include event, leaf.

  • event is the click event.
  • leaf is the item user clicked on. Includes name, id, keyPath and all data the user inputs when they pass in the tree.

onLeafMouseDown(function)[event, leaf]

Bind to the onMouseDown on the leaf. This function will get call when user mouse down on the item(leaf). The function arguments include event, leaf.

  • event is the click event.
  • leaf is the item user clicked on. Includes name, id, keyPath and all data the user inputs when they pass in the tree.

onLeafMouseUp(function)[event, leaf]

Bind to the onMouseUp on the leaf. This function will get call when user mouse up on the item(leaf). The function arguments include event, leaf.

  • event is the click event.
  • leaf is the item user clicked on. Includes name, id, keyPath and all data the user inputs when they pass in the tree.

maxLeaves(integer)

Sets the maximum number of leaf to show initially. Also used as an increment when then load more is pressed.

shouldComponentUpdate(function) [currProps, currState, nextProps, nextState]

A function that will be called inside shouldComponentUpdate. It's a good place to optimize update.

Styles

There is a default style sheet you can use if you so desire. /src/infinity-menu.css

License

Copyright (C) 2017 Social Tables, Inc. (https://www.socialtables.com) All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • Having trouble with search

    Having trouble with search

    Hey there,

    I really like what you've built here. I am currently using this to create a tree-view of data for an internal application. I am trying to pass "input" as my headerContent, which renders but i'm not sure how to get the search functionality going for this.

    This is my render function right now: render () { return ( <InfinityMenu tree={this.state.tree} headerContent={"input"} headerProps={{className: 'form-control'}} onNodeMouseClick={this.onNodeMouseClick.bind(this)} onLeafMouseClick={this.onLeafMouseClick}/*optional*/ onLeafMouseDown={this.onLeafMouseDown}/*optional*/ onLeafMouseUp={this.onLeafMouseUp}/*optional*/ /> ); }

    Thanks in advance for taking a look!

    opened by jamesoh 11
  • Update component while searching

    Update component while searching

    First of all, awesome component! I'm customizing this component to show a leaf as "selected" when it is clicked. I do this by setting an "onClick" function to the leaf which goes and updates the leaf with a customComponent. This work just fine when the component is not in searching mode. When it is in searching mode, my function updates the particular leaf with the customComponent but the changes are not reflected until I clear out my search. I'm not sure how to force the component to update even when it's in searching mode.

    Thanks!

    opened by dyseh 8
  • Some thoughts for a load more option.

    Some thoughts for a load more option.

    This is an incomplete but workable proof of concept for fixes #33 . Added added a quantifier property to the top level component which is pushed down to a new property on branch nodes to track how many leafs should be visible. Load more increments that value and displays the indexes in the visible range. Should work with the search but I'm not using that feature in production.

    opened by skoschik 7
  • Too much recursion

    Too much recursion

    Passing any react component instances in the tree results in a "Too much recursion" error on Firefox. Similar error on Google Chrome.

            this.state = {
                tree: [
                    {
                        name: "controls",
                        id: 0,
                        isOpen: false,
                        customComponent: ControlManage,
                        children: [],
                        controlItems: controlItems
                    } ....
    

    This seems to be a problem of the deep-copy library. I tried switching to deepcopy however it seems to somehow change the state of InfinityMenu.

    In the render method of InfinityMenu.

    assert(this.state == {searching: {...}}
    const tree = deepcopy(this.props.tree);
    assert(this.state == {}}
    
    opened by Freakazo 6
  • in

    in "onLeafMouseClick", an "data-reactid" of the leaf is passed in instead of the "leaf" object when using customComponent for leaf

    Background:

    Leaf is using customized component, and in customized component, onClick = { onClick } just do exactly like the doc. (Everything is normal for Node component even if I use customComponent for nodes. )
    

    And in InfinityMenu, this prop is set :

    onLeafMouseClick={this.onLeafMouseClick.bind(this)},

    However,

    
    onLeafMouseClick(event, leaf) {
      console.log(leaf); // it is a string which is the leaf's data-reactid, not leaf object, but everything works well if I don't use customzied component
    }
    

    Is that a bug I guess ?

    opened by LogicMonsters 5
  • Search functionality not working as expected with numeric values

    Search functionality not working as expected with numeric values

    When I enter a numeric value in the search box, the tree filters and shows correct results but when I erase the search input(numeric value) from search box then it's not showing the original tree instead it's still showing filtered results. Interestingly it's working as expected with alphabets.

    Initially, I was using version 3.0.1 later I upgraded to version 3.2.0 but the issue still exists.

    Any help greatly appreciated.

    opened by arjuturu 4
  • Uncaught TypeError: _react2.default.unmountComponentAtNode is not a function

    Uncaught TypeError: _react2.default.unmountComponentAtNode is not a function

    I have added a Tooltip to one of the children components (https://github.com/romainberger/react-portal-tooltip) and after the tooltip is displayed and I tried to collapse or open one of the parent nodes I get this:

    Uncaught TypeError: _react2.default.unmountComponentAtNode is not a function

    You can see exactly what happens here: http://www.giphy.com/gifs/l3q2BwUPU2tjvMY36

    opened by ferpintado 4
  • Convert custom component string

    Convert custom component string

    @tiansijie The project I am currently working on involves a React/Redux front-end powered by a Ruby on Rails backend. The data for the infinity menu is being served by the Rails server as json, which led to the problem of customComponent having to be a component. I am proposing a solution that allows for both a String and a React.Component type. For usage, this would have to be passed to the <InfinityMenu /> component:

    // Data can now set the customComponent field to be a string (a JSON payload in my example)
    [
       {
           name: "menu1",
            id: 1,
            isOpen: true,
            customComponent: "MyComponent1"
       },
      {
           name: "menu2",
            id: 2,
            isOpen: true,
            customComponent: "MyComponent2"
       }
    ];
    
    // Define your mappings
    var myComponentMappings = {
        "MyComponent1": MyComponent1, 
        "MyComponent2": MyComponent2 
    }
    
    <InfinityMenu customComponentMappings={ customComponentMappings } />
    

    Please let me know what you guys think and if this is an acceptable solution. I think I may be exploring optimizing search and implementing drag and drop as well if you guys are at all interested in integrating such features. Thanks for taking the time to look over.

    opened by jamesoh 4
  • removing onClose prop

    removing onClose prop

    Since you can now pass custom props for a header, there really is no use for this prop.

    If you wanted to have a custom close handler, you would just define a function prop on headerProps called onClose, and trigger it within the custom headerComponent

    we'll have to do a major bump with this after merging since it is a breaking API change

    opened by rovolution 3
  • Is there a way to add animation?

    Is there a way to add animation?

    Hi, I am currently using this component for a project I am working on and I loved it.

    Is there any way to add an animation when the submenu opens, collapse animation perhaps?

    Thanks in advance.

    opened by ferpintado 2
  • too many leaves

    too many leaves

    Would love a way to set a limit for the maximum number of leaves that should be rendered initially. With the ability to 'load more' or something, nothing fancy haha. Not sure if something like that fits into the scope here but i thought it would be a nice add, really helps if you have a lot of child nodes. Not sure how or if i could tap into doing something like this.

    ...i guess i could do something with the data i feed into react-infinity-menu through props... but that seems to defeat the purpose.

    Any thoughts?

    opened by skoschik 2
Owner
Social Tables
Social Tables
React component for building accessible menu, dropdown, submenu, context menu and more.

React-Menu An accessible and keyboard-friendly React menu library. Live examples and docs Features React menu components for easy and fast web develop

Zheng Song 837 Jan 9, 2023
Left navigation menu. Get data from JSON file and display simple form menu.

Left Navbar Menu Left navigation menu. Get data from JSON file and display simple form menu. User Interface created using React and Typescript. App st

Wojtek 5 May 24, 2021
Simple Context menu component for react showing all parent's node menus in theirs contexts.

Simple Context menu component for react showing all inherited parents menu with SSR compatibility.

Nathan Braun 6 Nov 13, 2022
A simple, data-driven, light-weight React Tree Menu component

React Simple Tree Menu Inspired by Downshift, a simple, data-driven, light-weight React Tree Menu component that: does not depend on any UI framework

Huang-Ming Chang 120 Dec 1, 2022
A simple sliding side menu component for React

Cheeseburger Menu A simple sliding side menu component for React. This component provides the sliding menu only, not the hamburger button. For your bu

Eddie McLean 19 May 27, 2022
Animated hamburger menu icons for React (1.5 KB) 🍔

‌ ‌ Animated hamburger menu icons for React Hamburger menu icons for React, with CSS-driven transitions. Created to be as elegant and performant as po

Luuk de Vlieger 709 Dec 31, 2022
React Dropdown Menu

React Dropdown Menu

Mikkel Laursen 142 Dec 3, 2022
Hamburger Menu React JS Using Third Party Package ReactJS - Popup

In this project, let's build a Hamburger Menu app by applying the concepts we have learned till now. Refer to the image below: Design Files Click to v

null 2 Dec 6, 2021
React dropdown menu components

react-menu-list This project is a set of components for building menus. This project works well for dropdown and autocomplete menus. The menus are cor

Streak 79 Nov 16, 2022
Add a context menu to your react app with ease

Documentation Go here. Installation Using yarn $ yarn add react-contexify Using npm $ npm install --save react-contexify The gist import React from 'r

Fadi Khadra 868 Jan 8, 2023
Radial Menu for FiveM,built with React

BCS Radial Menu This project is to freshen up the options for free radial menu f

BagusCodeStudio 13 Nov 7, 2022
🍪 A stylized command menu for React.

?? Superkey is under development and is not ready for production. If you have any bugs or problems please create an issue. ?? Website (working ?? ) •

Pablo Hdez 57 Dec 31, 2022
📱 A performant, easy to use hold to open context menu for React Native powered by Reanimated 🚀

React Native Hold Menu A performant, easy to use hold to open context menu for React Native powered by Reanimated. ?? This package is experimental and

Enes 1k Jan 6, 2023
Smart data-driven menu rendered in an overlay

React Data Menu Smart data-driven menu rendered in an overlay. Hints-based aligning with custom renderers and factories. Never clipped by other compon

Danko Kozar 106 Sep 11, 2022
:hamburger: An off-canvas sidebar component with a collection of effects and styles using CSS transitions and SVG path animations

react-burger-menu An off-canvas sidebar React component with a collection of effects and styles using CSS transitions and SVG path animations. Using R

Imogen 4.8k Jan 8, 2023
Simple lightweight (<2kb) animated slider component.

react-slide-out Simple lightweight (<2kb) animated slider component. Usability import Slider from 'react-slide-out'; and include css file import 'reac

Gogo 14 Aug 22, 2020
:art: Off-canvas menus for React.

React Off-Canvas Off-canvas menus for React. Installation $ npm install --save react-offcanvas Usage Basic Usage <OffCanvas width={300} transition

Vu Tran 38 Nov 10, 2022
A react lib for building circular menus in a very easy and handy way.

react-planet A react lib for building circular menus in a very easy and handy way. Live-Demo: STORYBOOK Read the full story @ Medium or innFactory-Blo

innFactory 140 Nov 16, 2022
A simple Hook for creating fully accessible dropdown menus in React

This Hook handles all the accessibility logic when building a dropdown menu, dropdown button, etc., and leaves the design completely up to you. It also handles the logic for closing the menu when you click outside of it.

Sparksuite 111 Dec 22, 2022