npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@whatoplay/react-drawer

v0.8.0

Published

Material Components React Drawer

Downloads

5

Readme

React Drawer

A React version of an MDC Drawer.

Installation

npm install @material/react-drawer

Usage

Styles

with Sass:

import '@material/react-drawer/index.scss';

with CSS:

import "@material/react-drawer/dist/drawer.css";

Javascript Instantiation

Basic Usage

Below is the basic example of a drawer. <SomeDrawerContent /> is not defined, but can be any element. Guidelines state it should be navigational content. Typically it is a list.

import React, {Component} from 'react';
import Drawer from '@material/react-drawer';

class MyApp extends Component {
  render() {
    return (
      <Drawer>
        <SomeDrawerContent />
      </Drawer>
    );
  }
}

Header and Content Variant

You may want to include a header, which MDC Web has already styled for you. For convenience, we've included <DrawerHeader />, <DrawerSubtitle />, <DrawerTitle />, and <DrawerContent /> components. DrawerHeader and DrawerContent default to a <div> tag, while the DrawerTitle and DrawerSubtitle default to an h3 and h6 tag respectively, but can be customized with the tag prop (example shown below).

import React, {Component} from 'react';
import Drawer, {
  DrawerHeader,
  DrawerSubtitle,
  DrawerTitle,
  DrawerContent,
} from '@material/react-drawer';

class MyApp extends Component {
  render() {
    return (
      <Drawer>
        <DrawerHeader> {/*defaults to div*/}
          <DrawerTitle tag='h2'> {/*defaults to h3*/}
            Inbox
          </DrawerTitle>
          <DrawerSubtitle> {/*defaults to h6*/}
            [email protected]
          </DrawerSubtitle>
        </DrawerHeader>

        <DrawerContent tag='main'>  {/*defaults to div*/}
          <SomeDrawerContent />
        </DrawerContent>
      </Drawer>
    );
  }
}

Dismissible Variant

The 2 previous examples are both permanent drawer examples, which are stationary. If you have a smaller screen, or want to keep focus on your main content you may want to use a dismissible drawer. The dismissible drawer will expand and collapse based on the open prop.

You will also want to use the <DrawerAppContent /> component, which will wrap around your content, that should animate in/out with the dismissible drawer.

import React, {Component} from 'react';
import Drawer, {DrawerAppContent} from '@material/react-drawer';

class MyApp extends Component {
  state = {open: false};

  render() {
    return (
      <div>
        <Drawer
          dismissible
          open={this.state.open}
        >
          <SomeDrawerContent />
        </Drawer>
        <DrawerAppContent>
          Your really cool app content here
          <button onClick={() => this.setState({open: !this.state.open})}>
            {this.state.open ? 'Open' : 'Close'} Drawer
          </button>
        </DrawerAppContent>
      </div>
    );
  }
}

Usage with Top App Bar

Full height drawer

If you want the dismissible drawer or permanent drawer to appear to the side of the top app bar (take the full height of the screen) as shown in the below image, please follow this markup:

adjacent

import React, {Component} from 'react';
import TopAppBar, {TopAppBarFixedAdjust} from '@material/react-top-app-bar';
import Drawer, {DrawerAppContent, DrawerContent, DrawerHeader, DrawerTitle} from '@material/react-drawer';
import MaterialIcon from '@material/react-material-icon';
import List, {ListItem, ListItemGraphic, ListItemText} from '@material/react-list';

// includes imports for drawer, list, material icon and top app bar styles
import './App.scss';

export default class App extends Component {
  state = {selectedIndex: 0};

  render() {
    return (
      <div className='drawer-container'>
        <Drawer>
          <DrawerHeader>
            <DrawerTitle tag='h2'>
              [email protected]
            </DrawerTitle>
          </DrawerHeader>

          <DrawerContent>
            <List singleSelection selectedIndex={this.state.selectedIndex}>
              <ListItem>
                <ListItemGraphic graphic={<MaterialIcon icon='folder'/>} />
                <ListItemText primaryText='Mail' />
              </ListItem>
            </List>
          </DrawerContent>
        </Drawer>

        <DrawerAppContent className='drawer-app-content'>
          <TopAppBar
            title='Inbox'
            navigationIcon={<MaterialIcon icon='menu' />}
          />

          <TopAppBarFixedAdjust>
            Your inbox content
          </TopAppBarFixedAdjust>
        </DrawerAppContent>
      </div>
    );
  }
}

You will also need these styles:


.drawer-container {
  display: flex;
  flex-direction: row;
  height: 100vh;
  overflow: hidden;
}

.drawer-app-content {
  flex: auto;
  overflow: auto;
}
Dismissible or Permanent drawer below top app bar

If you want the dismissible drawer or permanent drawer to appear below the top app bar as shown in the below image, please follow this markup:

below

import React, {Component} from 'react';
import TopAppBar, {TopAppBarFixedAdjust} from '@material/react-top-app-bar';
import Drawer, {DrawerAppContent, DrawerContent, DrawerHeader, DrawerTitle} from '@material/react-drawer';
import MaterialIcon from '@material/react-material-icon';
import List, {ListItem, ListItemGraphic, ListItemText} from '@material/react-list';

// includes imports for drawer, list, material icon and top app bar styles
import './App.scss';

export default class App extends Component {
  state = {selectedIndex: 0};

  render() {
    return (
      <div className='drawer-container'>
        <TopAppBar title='Inbox'/>

        <TopAppBarFixedAdjust>
          <Drawer>
            <DrawerHeader>
              <DrawerTitle tag='h2'>
                [email protected]
              </DrawerTitle>
            </DrawerHeader>

            <DrawerContent>
              <List singleSelection selectedIndex={this.state.selectedIndex}>
                <ListItem>
                  <ListItemGraphic graphic={<MaterialIcon icon='folder'/>} />
                  <ListItemText primaryText='Mail' />
                </ListItem>
              </List>
            </DrawerContent>
          </Drawer>

          <DrawerAppContent className='drawer-app-content'>
            Your inbox content
          </DrawerAppContent>
        </TopAppBarFixedAdjust>
      </div>
    );
  }
}

You will also need these styles:

.drawer-container {
  display: flex;
  flex-direction: row;
  height: 100vh;
  overflow: hidden;
}

.drawer-app-content {
  flex: auto;
  overflow: auto;
}

There is a known issue with the dismissible drawer styles when putting the drawer below the top app bar. To get around this, you must update the .mdc-drawer--dismissible class in your CSS stylesheets.

.mdc-drawer--dismissible {
  top: auto;
}

NOTE: Ordering of the markup is imperative.

Modal Variant

If you are on a smaller screen and do not want to animation your content, you may want to use the modal drawer. The modal drawer will expand and collapse based on the open prop overlayed your application content.

You should also implement the onClose callback prop, which is triggered after the drawer closes. This is your opportunity to set the open state variable to false.

NOTE: Closes with esc key or scrim click.

import React, {Component} from 'react';
import Drawer, {DrawerAppContent} from '@material/react-drawer';

class MyApp extends Component {
  state = {open: false};

  render() {
    return (
      <div>
        <Drawer
          modal
          open={this.state.open}
          onClose={() => this.setState({open: false})}
        >
          <SomeDrawerContent />
        </Drawer>
        <div>
          Your really cool app content here
          <button onClick={() => this.setState({open: !this.state.open})}>
            {this.state.open ? 'Open' : 'Close'} Drawer
          </button>
        </div>
      </div>
    );
  }
}

Accessibility

Focus Management

It is recommended to shift focus to the first focusable element in the main content when drawer is closed or one of the destination items is activated. (By default, MDC React Drawer restores focus to the menu button which opened it.)

NOTE: There is also a known bug due to the use of . There must be a focusable item in your drawer when using the modal variant. For now, insert an empty <a /> into your drawer as a workaround.

Dismissible Drawer

Restore focus to the first focusable element when a list item is activated or after the drawer closes. Do not close the drawer upon item activation, since it should be up to the user when to show/hide the dismissible drawer.

import React, {Component} from 'react';
import Drawer from '@material/react-drawer';
import Button from '@material/react-button';

class Drawer extends Component {
  mainContentEl = React.createRef();

  focusFistFocusableItem = () => {
    this.mainContentEl.current.querySelector('input, button').focus();
  }

  onDrawerClose = () => {
    this.setState({open: false});
    this.focusFistFocusableItem();
  }

  render() {

    return (
      <div>
        <Drawer
          modal
          open={this.state.open}
          onClose={this.drawerOnClose}
        >
          <List>
            <ListItem onClick={this.focusFistFocusableItem}>
              <ListItemText primaryText='list item' />
            </ListItem>
          </List>
        </Drawer>
        <div ref={this.mainContentEl}>
          <Button raised>Click me!</Button>
        </div>
      </div>
    );
  }
}

Modal Drawer

Close the drawer when an item is activated in order to dismiss the modal as soon as the user performs an action. Only restore focus to the first focusable element in the main content after the drawer is closed, since it's being closed automatically.

import React, {Component} from 'react';
import Drawer from '@material/react-drawer';
import Button from '@material/react-button';

class Drawer extends Component {
  mainContentEl = React.createRef();

  onDrawerClose = () => {
    this.setState({open: false});
    this.mainContentEl.current.querySelector('input, button').focus();
  }

  onListItemClick = () => this.onDrawerClose();

  render() {

    return (
      <div>
        <Drawer
          modal
          open={this.state.open}
          onClose={this.drawerOnClose}
        >
          <List>
            <ListItem onClick={this.onListItemClick}>
              <ListItemText primaryText='list item' />
            </ListItem>
          </List>
        </Drawer>
        <div ref={this.mainContentEl}>
          <Button raised>Click me!</Button>
        </div>
      </div>
    );
  }
}

Props

Drawer

Prop Name | Type | Description --- | --- | --- className | String | Classes to be applied to the drawer element. onOpen | Function() => void | Callback after the drawer has opened. onClose | Function() => void | Callback after the drawer has closed. modal | Boolean | Indicates that the drawer is of type modal. dismissible | Boolean | Indicates that the drawer is of type dismissible. tag | String | Customizes the drawer tag type (default to <aside>). open | boolean | If true, opens drawer. If false, closes drawer.

Sass Mixins

Sass mixins may be available to customize various aspects of the Components. Please refer to the MDC Web repository for more information on what mixins are available, and how to use them.

Advanced Sass Mixins