Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-dd-menu-portal

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-dd-menu-portal

A fork of react-dd-menu built with React portals to hoist dropdown menus in the DOM.

  • 0.0.9
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

react-dd-menu-portal

A fork of the react-dd-menu project. With (hard-coded) support for React portals. Undocumented and very dirty implementation. Use at own risk.

Live Example: React Dropdown Menu

NOTE: I am no longer actively developing this project since it has met most of the initial goals and I will be spending most of my time developing the bigger project react-md. I am more than happy to keep review/accepting pull requests with new features/bugfixes though.

Installation

$ npm install -S react-dd-menu \
                 # If you haven't installed already
                 react \
                 react-dom \
                 react-transition-group
Props
DropdownMenu
  static MENU_SIZES = ['sm', 'md', 'lg', 'xl']
  static ALIGNMENTS = ['center', 'right', 'left']

  static propTypes = {
    isOpen: PropTypes.bool.isRequired,
    close: PropTypes.func.isRequired,
    toggle: PropTypes.node.isRequired,
    children: PropTypes.node,
    inverse: PropTypes.bool,
    align: PropTypes.oneOf(ALIGNMENTS),
    animAlign: PropTypes.oneOf(ALIGNMENTS),
    textAlign: PropTypes.oneOf(ALIGNMENTS),
    menuAlign: PropTypes.oneOf(ALIGNMENTS),
    className: PropTypes.string,
    size: PropTypes.oneOf(MENU_SIZES),
    upwards: PropTypes.bool,
    animate: PropTypes.bool,
    enterTimeout: PropTypes.number,
    leaveTimeout: PropTypes.number,
    closeOnInsideClick: PropTypes.bool,
    closeOnOutsideClick: PropTypes.bool,
  }

  static defaultProps = {
    inverse: false,
    align: 'center',
    animAlign: null,
    textAlign: null,
    menuAlign: null,
    className: null,
    size: null,
    upwards: false,
    animate: true,
    enterTimeout: 150,
    leaveTimeout: 150,
    closeOnInsideClick: true,
    closeOnOutsideClick: true,
  }
  • isOpen - Boolean for telling if the menu is open. This was passed in as a prop instead of having the component's own state so you can decide when to close the menu on your own.
  • close - a function to call that turns the isOpen boolean to false
  • toggle - any renderable item that will be used to toggle the menu open. So normally a button or any other content.
  • inverse - boolean if it is an inversed color menu
  • align - the alignment for the animation, text, and menu if the specific props are not given. Defaults to center
  • animAlign - the alignment/direction that the menu will appear from
  • textAlign - the alignment of each list item's text
  • menuAlign - the alignment of the menu to the toggle element
  • size - the size of the menu. Defaults to auto size.
  • className - any additional css classes to add the the dropdown menu container. (.dd-menu)
  • upwards - boolean if the menu should go upwards. Defaults to false
  • animate - boolean if the menu should animate on open and close. Defaults to true
  • enterTimeout - the amount of time in ms to end the CSSTransitionGroup. Defaults to 150
  • leaveTimeout - the amount of time in ms to end the CSSTransitionGroup. Defaults to 150
  • closeOnInsideClick - a boolean if the menu should close when you click inside the menu. Defaults to true
  • closeOnOutsideClick - a boolean if the menu should close when you click elsewhere on the page. Defaults to true
NestedDropdownMenu
  static propTypes = {
    toggle: PropTypes.node.isRequired,
    children: PropTypes.node,
    nested: PropTypes.oneOf(['inherit', 'reverse', 'left', 'right']),
    animate: PropTypes.bool,
    direction: PropTypes.oneOf(['left', 'right']),
    upwards: PropTypes.bool,
    delay: PropTypes.number,
    enterTimeout: PropTypes.number,
    leaveTimeout: PropTypes.number,
    openOnMouseover: PropTypes.bool,
  }

  static defaultProps = {
    nested: 'reverse',
    animate: false,
    direction: 'right',
    upwards: false,
    delay: 500,
    enterTimeout: 150,
    leaveTimeout: 150,
    openOnMouseover: true,
  }
  • toggle - an renderable item that will open the nested menu on hover. It gets wrapped in a li element, so it might be best to have a button or a link tag.
  • nested - the nested menu's expansion direction. The default case should hopefully be the only used case.
    • Inherit - If the main dropdown menu is aligned left, the nested menu will appear to the left as well.
    • Reverse - If the main dropdown menu is aligned left, the nested menu will appear to the right.
    • Left - Force the menu to appear to the left of the menu.
    • Right - Force the menu to appear to the right of the menu.
  • animate - boolean if the nested menu should animate when appearing. Defaults to false
  • direction - The animation direction.
  • upwards - boolean if the nested menu should render upwards. Defaults to false
  • delay - A number in ms to allow the mouse to be off of the dropdown menu to close it. Defaults to 500ms
  • enterTimeout - the amount of time in ms to end the CSSTransitionGroup. Defaults to 150
  • leaveTimeout - the amount of time in ms to end the CSSTransitionGroup. Defaults to 150
  • openOnMouseover - boolean if the menu can be opened/close by mouseover/mouseleave events

Styling

In the dist folder, there is a react-dd-menu.css and a react-dd-menu.min.css with the default css stylings. If you have SASS, the source is located in src/scss.

If you don't want the default css or to edit the default, the layout is this:

.dd-menu
| -- toggle component
| -- .dd-menu-items
|    | -- ul
|    |    | [role="separator"], .separator

The separator can be any element with a classname of .separator or any element with a role of separator (or both). To get the best styling, it should probably be applied to an li element.

Usage

import React from 'react';
import DropdownMenu from 'react-dd-menu';

export default class Example extends React.Component {
  constructor() {
    super();
    this.state = {
        isMenuOpen: false
    };
    this.click = this.click.bind(this);
    this.toggle = this.toggle.bind(this);
    this.close = this.close.bind(this);
  }

  toggle() {
    this.setState({ isMenuOpen: !this.state.isMenuOpen });
  }

  close() {
    this.setState({ isMenuOpen: false });
  }

  click() {
    console.log('You clicked an item');
  }

  render() {
    const menuOptions = {
      isOpen: this.state.isMenuOpen,
      close: this.close,
      toggle: <button type="button" onClick={this.toggle}>Click me!</button>,
      align: 'right'
    };
    return (
      <DropdownMenu {...menuOptions}>
        <li><a href="#">Example 1</a></li>
        <li><button type="button" onClick={this.click}>Example 2</button></li>
      </DropdownMenu>
    );
  }
}

or..

var React = require('react');
var DropdownMenu = require('react-dd-menu');

var Example = React.createClass({
  getInitialState: function() {
    return { isMenuOpen: false };
  },

  toggle: function() {
    this.setState({ isMenuOpen: !this.state.isMenuOpen });
  },

  close: function() {
    this.setState({ isMenuOpen: false });
  },

  click: function() {
    console.log('You clicked an item');
  },

  render: function() {
    var menuOptions = {
      isOpen: this.state.isMenuOpen,
      close: this.close,
      toggle: <button type="button" onClick={this.toggle}>Click me!</button>,
      align: 'right'
    }
    return (
      <DropdownMenu {...menuOptions}>
        <li><a href="#">Example 1</a></li>
        <li><button type="button" onClick={this.click}>Example 2</button></li>
      </DropdownMenu>
    );
  }
});
Nested Menu Example
'use strict';

import React from 'react';
import DropdownMenu, { NestedDropdownMenu } from 'react-dd-menu';

class Example extends React.Component {
  state = { isMenuOpen: false };

  toggle = () => {
    this.setState({ isMenuOpen: !this.state.isMenuOpen });
  }

  close = () => {
    this.setState({ isMenuOpen: false });
  };

  click = () => {
    console.log('You clicked an item');
  };

  render() {
    const menuOptions = {
      isOpen: this.state.isMenuOpen,
      close: this.close,
      toggle: <button type="button" onClick={this.toggle}>Click me!</button>,
      align: 'right',
    };

    const nestedProps = {
      toggle: <a href="#">Hover me for Nested Menu!</a>,
      animate: true,
    };

    return (
      <DropdownMenu {...menuOptions}>
        <li><a href="#">Example 1</a></li>
        <li><button type="button" onClick={this.click}>Example 2</button></li>
        <li role="separator" className="separator" />
        <NestedDropdownMenu {...nestedProps}>
          <li><a href="#">I am in a Nested Menu!</a></li>
        </NestedDropdownMenu>
      </DropdownMenu>
    );
  }
}

Contributors/Local Changes

To rebuild the source:

$ npm run build

This will output all the css and js files into ./dist;

Versions

  • 0.0.1 - add React portal support

Keywords

FAQs

Package last updated on 05 Dec 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc