Giter Site home page Giter Site logo

react-sidebar's Introduction

React Sidebar npm version Build Status

React Sidebar is a sidebar component for React 0.14+. It offers the following features:

  • The sidebar can slide over the main content or dock next to it.
  • Touch enabled: swipe to open and close the sidebar like on a native mobile app.
  • Easy to combine with media queries to show the sidebar only when there's enough screen-width (see example).
  • Works on both the left and right side.
  • Tiny size: <2.5kB gzipped
  • MIT license

See a demo here.

Touch specifics

The touch interaction of the React Sidebar mimics the interactions that are supported by Android apps that implement the material design spec:

  • When the sidebar is closed, dragging from the left side of the screen will have the right side of the sidebar follow your finger.
  • When the sidebar is open, sliding your finger over the screen will only affect the sidebar once your finger is over the sidebar.
  • On release, it will call onSetOpen prop if the distance the sidebar was dragged is more than the dragToggleDistance prop.

Note: The sidebar touch functionality doesn't work on IOS because of the "swipe-to-go-back" feature. Therefore the functionality has been disabled on IOS.

Installation

npm install react-sidebar

If you use TypeScript, typings are available on DefinitelyTyped and can be installed with:

npm install @types/react-sidebar

Getting started

By design, React Sidebar does not keep track of whether it is open or not. This has to be done by the parent component. This allows the parent component to make changes to the sidebar and main content based on the open/docked state. An example could be to hide the "show menu" button from the main content when the sidebar is docked.

Because React Sidebar can be toggled by dragging the sidebar into its open/closed position, you will have to pass in an onSetOpen method as a prop to allow the sidebar to control the open state in the parent.

The minimum React component to integrate React Sidebar looks like this:

import React from "react";
import Sidebar from "react-sidebar";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sidebarOpen: true
    };
    this.onSetSidebarOpen = this.onSetSidebarOpen.bind(this);
  }

  onSetSidebarOpen(open) {
    this.setState({ sidebarOpen: open });
  }

  render() {
    return (
      <Sidebar
        sidebar={<b>Sidebar content</b>}
        open={this.state.sidebarOpen}
        onSetOpen={this.onSetSidebarOpen}
        styles={{ sidebar: { background: "white" } }}
      >
        <button onClick={() => this.onSetSidebarOpen(true)}>
          Open sidebar
        </button>
      </Sidebar>
    );
  }
}

export default App;

Responsive sidebar

A common use case for a sidebar is to show it automatically when there is enough screen width available. This can be achieved using media queries via window.matchMedia. This again has to be integrated into the parent component so you can use the information to make changes to the sidebar and main content.

import React from "react";
import Sidebar from "react-sidebar";

const mql = window.matchMedia(`(min-width: 800px)`);

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sidebarDocked: mql.matches,
      sidebarOpen: false
    };

    this.mediaQueryChanged = this.mediaQueryChanged.bind(this);
    this.onSetSidebarOpen = this.onSetSidebarOpen.bind(this);
  }

  componentWillMount() {
    mql.addListener(this.mediaQueryChanged);
  }

  componentWillUnmount() {
    mql.removeListener(this.mediaQueryChanged);
  }

  onSetSidebarOpen(open) {
    this.setState({ sidebarOpen: open });
  }

  mediaQueryChanged() {
    this.setState({ sidebarDocked: mql.matches, sidebarOpen: false });
  }

  render() {
    return (
      <Sidebar
        sidebar={<b>Sidebar content</b>}
        open={this.state.sidebarOpen}
        docked={this.state.sidebarDocked}
        onSetOpen={this.onSetSidebarOpen}
      >
        <b>Main content</b>
      </Sidebar>
    );
  }
}

export default App;

Supported props

Property name Type Default Description
children Anything React can render n/a The main content
rootClassName string n/a Add a custom class to the root component
sidebarClassName string n/a Add a custom class to the sidebar
contentClassName string n/a Add a custom class to the content
overlayClassName string n/a Add a custom class to the overlay
defaultSidebarWidth number 0 Width in pixles of the sidebar on render. Use this to stop the sidebar from poping in after intial render. (Overrides transitions)
sidebar Anything React can render n/a The sidebar content
onSetOpen function n/a Callback called when the sidebar wants to change the open prop. Happens after sliding the sidebar and when the overlay is clicked when the sidebar is open.
docked boolean false If the sidebar should be always visible
open boolean false If the sidebar should be open
transitions boolean true If transitions should be enabled
touch boolean true If touch gestures should be enabled
touchHandleWidth number 20 Width in pixels you can start dragging from the edge when the sidebar is closed.
dragToggleDistance number 30 Distance the sidebar has to be dragged before it will open/close after it is released.
pullRight boolean false Place the sidebar on the right
shadow boolean true Enable/Disable sidebar shadow
styles object See below Inline styles. These styles are merged with the defaults and applied to the respective elements.
rootId string n/a Add an id to the root component
sidebarId string n/a Add an id to the sidebar
contentId string n/a Add an id to the content. The driving use case for adding an element id to content was to allow react-scroll to scroll the content area of the site using react-sidebar.
overlayId string n/a Add an an id to the overlay

Styles

Styles are passed as an object with 5 keys, root, sidebar, content, overlay and dragHandle, and merged to the following defaults:

{
  root: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    overflow: "hidden"
  },
  sidebar: {
    zIndex: 2,
    position: "absolute",
    top: 0,
    bottom: 0,
    transition: "transform .3s ease-out",
    WebkitTransition: "-webkit-transform .3s ease-out",
    willChange: "transform",
    overflowY: "auto"
  },
  content: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    overflowY: "auto",
    WebkitOverflowScrolling: "touch",
    transition: "left .3s ease-out, right .3s ease-out"
  },
  overlay: {
    zIndex: 1,
    position: "fixed",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    opacity: 0,
    visibility: "hidden",
    transition: "opacity .3s ease-out, visibility .3s ease-out",
    backgroundColor: "rgba(0,0,0,.3)"
  },
  dragHandle: {
    zIndex: 1,
    position: "fixed",
    top: 0,
    bottom: 0
  }
};

Acknowledgements

My goal was to make a React Component that implements the material design spec for navigation drawers. My initial attempt was to improve hamburger-basement by arnemart but I quickly figured that I better start from scratch. Still, that project helped me a ton to get started.

react-sidebar's People

Contributors

ababol avatar balloob avatar bdav24 avatar benjeffery avatar cjlarose avatar cristian-sima avatar elliottsj avatar factorize avatar fallenstedt avatar jeroenvervaeke avatar joeflack4 avatar kulesa avatar leifdalan avatar lostdalek avatar lucascalazans avatar markusenglund avatar michaelwschultz avatar milllertime avatar sauzy34 avatar sugarshin avatar vildehav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-sidebar's Issues

Support for alternate CSS? (not absolutely positioned content area)

Is there any way we could not absolutely position the "main page content"?

I run into issues with things like bootstrap media queries and joyride... where the content area is absolutely positioned over to right... Instead, if we could just make the content area positioned normally and add padding-left vs left it seems like a more simple solution.

It may be that there are very good reasons why this isn't the case. But I am running into problems with the current setup. ideas?

Compiling the example code

This is probably a dumb question, but I'm new to this ecosystem. How do you compile the example in your repo? I see that you're using webpack, but I'm not sure what parameters to pass to the command. Thanks in advance for your help!

React v0.15.2+ unknown prop error `onTouchTap`

I don't even use the onTouchTap prop in my code, so it appears to be an invalid passthrough

Stacktrace:

warning.js?8a56**:44Warning: Unknown prop `onTouchTap` on <div> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
    in div (created by Sidebar)
    in div (created by Sidebar)
    in Sidebar (created by MainNavSide)
    in MainNavSide

Sidebar on right?

Perhaps this is an obvious question but can you have the sidebar on the right instead of the left? That's what I'd like for my design.

Sidebar Pull Right props

I'm using your responsive example.
I'm curious, is it not working if I add pullRight props to the responsive one?

If I add pullRight props, sidebar will always docked and didn't want to close.

Thanks.

Error: Invariant Violation - React 0.14+

Hi.

After upgrading React and react-sidebar I am getting this error:

invariant.js:39 Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of App.jsx

Using React 0.14, 0.14.8 and 0.15+

When I was testing the examples in the repo I got another error:
Cannot set property 'propTypes' of undefined Using React 0.14 and 0.15.

I have used react-sidebar earlier with react 0.13.

Is there any known issues with newer versions of React ? I have the latest react-sidebar version.

Printing Main Content

So, when I go to print content that's in the main area, it's being truncated after on one page with a scrollbar visible. What's up with that?

screenshot from 2015-12-10 12-01-10

That's a screenshot of what I'm talking about. If I were to select the content (images) and do a "print selection", I get two pages of images, as opposed to one page (truncated) and a scrollbar. Any thoughts?

Cannot get scrollTop position?

Hi,
I need to track the scroll position of the main content but it doesn't work when I use the Sidebar component? Do you know how I can track it?

Best

Swipe in iOS?

Swipe from left goes back in browser history and swipe from right goes forward.

Unfortunately I cannot test it myself on iOS..

Does this component works around this? How?

I would love to reuse this trick with other components if I need to use swipes from left or right.

Missing Typings for DT or @types

I am currently using combination of React and Typescript and I was wandering if it is possible to find react-sidebar declarations for typescript. Right now I am forced to use ambient module declaration.

Update Example Code in Readme

I installed react-sidebar today and got version 2.1.1 from npm. I think latest version uses new es7 module syntax.

But Readme in github uses commonjs syntax.

Scroll main content independently of sidebar

This is an awesome component - thank you for sharing it!

Currently scroll is disabled in the main content area when the sidebar is activated. Do you know how I can get scroll to work in both the main content area as well as the sidebar at the same time?

pullRight, Redux and Responsive

I got the responsive sidebar working in Redux and ES6 finally, but I can't get it to be on the right side, even with adding pullRight as a prop. What am I doing wrong here?

constructor(props) {
    super(props);
    this.state = {
      pullRight: true,
      sidebarOpen: false,
      sidebarDocked: false,
    }

    this.toggleOpen = this.toggleOpen.bind(this);    
    this.onSetOpen = this.onSetOpen.bind(this);
    this.mediaQueryChanged = this.mediaQueryChanged.bind(this);

  } 

componentWillMount() {
    const mql = window.matchMedia(`(min-width: 660px)`);
    mql.addListener(this.mediaQueryChanged);
    this.setState({mql: mql, docked: mql.matches});
    this.setState({pullRight: true});
  }

  componentWillUnmount() {
    this.state.mql.removeListener(this.mediaQueryChanged);
  }

  onSetOpen(open) {
    this.setState({open: open});
  }

  mediaQueryChanged() {
    this.setState({docked: this.state.mql.matches});
  }

  toggleOpen(ev) {
    if (ev) {
      ev.preventDefault();
    }
    this.setState({open: !this.state.open});
  }

  render() {

    const sidebar = <SidebarContent />;

    const contentHeader = (
      <span>
        {!this.state.docked &&
        <a onClick={this.toggleOpen} href="#" style={styles.contentHeaderMenuLink}><i className="fa fa-bars"></i></a>}
        <span>Header</span>
      </span>);

    const sidebarProps = {
      sidebar: sidebar,
      pullRight: this.state.pullRight,
      docked: this.state.docked,
      open: this.state.open,
      onSetOpen: this.onSetOpen,
    };

return (
      <div  className="main_area">
        <Sidebar {...sidebarProps}>
          <MaterialTitlePanel title={contentHeader}>
            <div style={styles.content}>
            </div>
          </MaterialTitlePanel>
        </Sidebar>
       </div>
)

On scroll event

There is a problem with the CSS positioning in sidebar. If you want to create an scroll listener the callback function won't be triggered.

Parent container returns warning message

Just like the responsive demo I implemented react-sidebar with MaterialTitlePanel and SidebarContent and could not get it working. I'm running React 15.0.0 and react-sidebar 2.1.2.

warning.js:44Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of MainContainer.

invariant.js:38Uncaught Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of MainContainer.

image

Using with universal app

When using with universal react app, window is not defined error is shown. The problem is in responsive example, not in module itself.

var mql = window.matchMedia('(min-width: 800px)');

It think it shall be inside componentDidMount event instead of componentWillMount.

overflow:auto as an option?

I'd prefer that the scrollbars only appear when there is enough content to overflow. Would it be possible to enable this?

Thanks!

Issue With reactBootstrap

Hi,

The sidebar works fine with my Application but it not working well with reactBootstrap.
popover and tooltip components misplaced .

Any idea why it is ??

Fastclick interferes with the sidebar

I have noticed a possible issue with sidebar.

In my mobile app, I have added menuButtonClick to all the side menu items to collapse the menu and navigate to a new page. Swipe right/left works perfectly, but clicking on the menu item partially collapses the menu and it gets frozen.

It only happens when fast click is enabled. I think the following might be confusing sidebar.

Internally, FastClick uses document.createEvent to fire a synthetic click event as soon as touchend is fired by the browser.

As a temporary fix, I am excluding the sidemenu from being fastclicked. But we need to find a more elegant solution for it.

Is it possible to have more than one sidebar?

I'd like to have one on each side, but not sure if this is possible.

Edit: it does not appear to be possible. I had already written a custom sidebar, but I don't have the great touch support like this library. For now, I'll be applying some of this functionality to my own component, but I think this would be a great enhancement.

How do I use this?

Could you please ELI5 how I would go about including this component with my project? Sorry, I am still new to react and not quite sure how to include 3rd party components.

Currently I am using node/express and rendering everything client side.

Running on server

Can't render on server because of window object usage - would be nice to have isClient/isServer checking during initialization

Some advices

I want you to use this component, but the code contains a lot of styles, it should be put into a separate css file, and thus it will be easy to customize.

How do I use sidebar with a fullwidth top header?

I'm trying to use this plugin to create the sidebar, but I need a top header aswell for the entire viewport. As it is now, the sidebar dominates the left (or right) side, leaving the attempts to create a fullwidth header div out.

Is there anyway to achieve this?

Multiple Sidebar

Hi,

How can i have multiple sidebar .. in right and left side

any possibility with this ??

Overlay tap delay

I noticed the overlay had a tap delay on touch devices. It appears the "react-tap-event-plugin" module is a dependency which automatically fixes this, but I could only figure this out by browsing the source code (the onTouchTap event). So I think this module should be a peer dependency?

Relative Positioning & Custom styles for content - left/right not working

This is sort of two interconnected issues with one underlying cause.

  1. I have a scenario where I need to use relative positioning of the sidebar and contents. This will work for the most part if I set style as:
           let style = {
            root: {
                position: 'relative',
                display: 'inline-block'
            },
            sidebar: {
                position: 'relative',
                display: 'inline-block',
                'vertical-align': 'top'
            },
            content: {
                position: 'relative',
                display: 'inline-block',
                background: 'white',
            }
        };

But the left position is still being overridden by code mentioned in problem two.

  1. Currently doesn't respect if left style is set. All left positioning is automatically overridden by:
if (this.props.pullRight) {
     contentStyle.right = this.state.sidebarWidth + 'px';
} else {
      contentStyle.left = this.state.sidebarWidth + 'px';
 }

The behavior is largely correct for any absolute positioning. So a simple fix might be just address the case of relative positioning by wrapping the contentStyle code above inside:

if (contentStyle.position !== 'relative') {
    //your existing code 
}

Uncaught TypeError: Cannot read property 'mql' of undefined

I am trying the example from the README where the sidebar responds to the browser width, and I get the following error when I resize my browser manually and cross over the threshold of 800px going in either direction:

Uncaught TypeError: Cannot read property 'mql' of undefined

Is this the expected behavior?

Move zIndex to props.

The zIndex option (options?) for overlay and sidebar should be moved to the props. It's pretty common to have other floating elements on the page spinners, modals etc. with greater zIndexes and they overlap the sidebar and overlay where they shouldn't.

Scroll on iOS Safari

I feel a bit laggy when i scrolled on Safari (iOS).
Is there any solution to fix this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.