DevExtreme React - Getting Started with Navigation Drawer
The Drawer is a dismissible or permanently visible panel used for navigation in responsive web application layouts.
DevExtreme provides an application template for Angular. It implements a responsive layout that uses the Drawer. You can use this template instead of following the tutorial. Refer to the documentation on GitHub for more information.
If you do not use Angular or the template is unsuitable, follow the instructions in this tutorial. We create a Drawer that allows a user to switch between pages. The Drawer is opened and closed via a button on a toolbar.
Refer to the subtopics for details on every configuration step. You can also see the full code below:
- import React from "react";
- import "devextreme/dist/css/dx.common.css";
- import "devextreme/dist/css/dx.light.css";
- import "./DxComponent.css";
- import { Drawer } from "devextreme-react/drawer";
- import { Toolbar, Item } from "devextreme-react/toolbar";
- import NavigationList from "./NavigationList.js";
- import { Router, Route } from "react-router-dom";
- import Inbox from "./views/Inbox.js";
- import Trash from "./views/Trash.js";
- import SentMail from "./views/SentMail.js";
- import Spam from "./views/Spam.js";
- import history from "./history";
- class DxComponent extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- isOpened: false
- };
- this.buttonOptions = {
- icon: "menu",
- onClick: () => {
- this.setState({ isOpened: !this.state.isOpened })
- }
- };
- }
- render() {
- return (
- <React.Fragment>
- <Toolbar id="toolbar">
- <Item
- widget="dxButton"
- options={this.buttonOptions}
- location="before" />
- </Toolbar>
- <Drawer
- minSize={37}
- height={250}
- revealMode="expand"
- openedStateMode="overlap"
- component={NavigationList}
- opened={this.state.isOpened} >
- <div id="view">
- <Router history={history}>
- <div>
- <Route exact path="/" component={Inbox} />
- <Route exact path="/inbox" component={Inbox} />
- <Route exact path="/sent-mail" component={SentMail} />
- <Route exact path="/spam" component={Spam} />
- <Route exact path="/trash" component={Trash} />
- </div>
- </Router>
- </div>
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
- import React from "react";
- import List from "devextreme-react/list.js";
- import history from "./history";
- const navigation = [
- { id: 1, text: "Inbox", icon: "message", filePath: "inbox" },
- { id: 2, text: "Sent Mail", icon: "check", filePath: "sent-mail" },
- { id: 3, text: "Trash", icon: "trash", filePath: "trash" },
- { id: 4, text: "Spam", icon: "mention", filePath: "spam" }
- ];
- class NavigationList extends React.PureComponent {
- loadView(e) {
- history.push(e.addedItems[0].filePath);
- }
- render() {
- return (
- <React.Fragment>
- <List
- items={navigation}
- width={200}
- selectionMode="single"
- onSelectionChanged={this.loadView} />
- </React.Fragment>
- );
- }
- }
- export default NavigationList;
- import React, { Component } from "react";
- import DxComponent from "./components/DxComponent";
- class App extends Component {
- render() {
- return (
- <div className="App">
- <DxComponent />
- </div>
- );
- }
- }
- export default App;
- import { createBrowserHistory } from "history"
- export default createBrowserHistory()
- .dx-drawer-panel-content, .dx-overlay-content {
- background-color: lightgray;
- }
- #toolbar {
- background-color: rgba(191, 191, 191, .15);
- padding: 5px 10px;
- }
- .dx-toolbar-button .dx-button {
- background-color: rgba(191, 191, 191, -0.15);
- border: none;
- }
- .dx-toolbar-button > .dx-toolbar-item-content {
- margin-left: -7px;
- }
- .dx-list-item-icon {
- margin-right: 10px;
- }
- #view {
- margin-left: 10px;
- margin-top: 10px;
- }
- import React from "react";
- class Inbox extends React.Component {
- render() {
- return (
- <div>Inbox</div>
- );
- }
- }
- export default Inbox;
- import React from "react";
- class SentMail extends React.Component {
- render() {
- return (
- <div>Sent Mail</div>
- );
- }
- }
- export default SentMail;
- import React from "react";
- class Spam extends React.Component {
- render() {
- return (
- <div>Spam</div>
- );
- }
- }
- export default Spam;
- import React from "react";
- class Trash extends React.Component {
- render() {
- return (
- <div>Trash</div>
- );
- }
- }
- export default Trash;
Create the Drawer
Wrap the view in the Drawer and specify a template for the Drawer's content. Inside the template, set the Drawer's width. You can use the nested widget's width option for this (see Implement Navigation), but in this tutorial, we use the width
CSS property. The Drawer's height adjusts to the view's height (specified via the height option).
In addition, you can specify the minSize option to make the Drawer partially visible in the closed state.
- import React from "react";
- import "devextreme/dist/css/dx.common.css";
- import "devextreme/dist/css/dx.light.css";
- import "./DxComponent.css";
- import { Drawer } from "devextreme-react/drawer";
- class DxComponent extends React.Component {
- constructor(props) {
- super(props);
- }
- render() {
- return (
- <React.Fragment>
- <Drawer
- minSize={37}
- height={250}
- render={ () => <div style="width: 150px">Drawer content</div> } >
- <div>View content</div>
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
- .dx-drawer-panel-content, .dx-overlay-content {
- background-color: lightgray;
- }
- #view {
- margin-left: 10px;
- margin-top: 10px;
- }
- import React, { Component } from "react";
- import DxComponent from "./components/DxComponent";
- class App extends Component {
- render() {
- return (
- <div className="App">
- <DxComponent />
- </div>
- );
- }
- }
- export default App;
If you run the code, you should see a partially visible Drawer and a view that displays View content.
Open and Close the Drawer
Depending on the library or framework you use, call the toggle() method or bind a variable to the opened option.
In the following code, a toolbar button outside the Drawer opens and closes it:
- // ...
- import { Drawer } from "devextreme-react/drawer";
- import { Toolbar, Item } from "devextreme-react/toolbar";
- class DxComponent extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- isOpened: false
- };
- this.buttonOptions = {
- icon: "menu",
- onClick: () => {
- this.setState({ isOpened: !this.state.isOpened })
- }
- };
- }
- render() {
- return (
- <React.Fragment>
- <Toolbar id="toolbar">
- <Item
- widget="dxButton"
- options={this.buttonOptions}
- location="before" />
- </Toolbar>
- <Drawer ...
- opened={this.state.isOpened} >
- <div>View content</div>
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
- /* ... */
- #toolbar {
- background-color: rgba(191, 191, 191, .15);
- padding: 5px 10px;
- }
- .dx-toolbar-button .dx-button {
- background-color: rgba(191, 191, 191, -0.15);
- border: none;
- }
- .dx-toolbar-button > .dx-toolbar-item-content {
- margin-left: -7px;
- }
Implement Navigation
The Drawer is designed to contain navigation items. If they should nest other items, use the TreeView widget to implement navigation. Otherwise, use the List.
These widgets provide the onSelectionChanged function in which we can implement the navigation logic. However, this function is executed only if you enable selection. In the TreeView, set the selectionMode to "single" and assign true to selectByClick; in the List, set the selectionMode to "single".
In this tutorial, we use the List:
- // ...
- import NavigationList from "./NavigationList.js";
- import { Router, Route } from "react-router-dom";
- import Inbox from "./views/Inbox.js";
- import Trash from "./views/Trash.js";
- import SentMail from "./views/SentMail.js";
- import Spam from "./views/Spam.js";
- import history from "./history";
- class DxComponent extends React.Component {
- render() {
- return (
- <React.Fragment>
- <Drawer ...
- component={NavigationList} >
- <div id="view">
- <Router history={history}>
- <div>
- <Route exact path="/" component={Inbox} />
- <Route exact path="/inbox" component={Inbox} />
- <Route exact path="/sent-mail" component={SentMail} />
- <Route exact path="/spam" component={Spam} />
- <Route exact path="/trash" component={Trash} />
- </div>
- </Router>
- </div>
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
- import React from "react";
- import List from "devextreme-react/list.js";
- import history from "./history";
- const navigation = [
- { id: 1, text: "Inbox", icon: "message", filePath: "inbox" },
- { id: 2, text: "Sent Mail", icon: "check", filePath: "sent-mail" },
- { id: 3, text: "Trash", icon: "trash", filePath: "trash" },
- { id: 4, text: "Spam", icon: "mention", filePath: "spam" }
- ];
- class NavigationList extends React.PureComponent {
- loadView(e) {
- history.push(e.addedItems[0].filePath);
- }
- render() {
- return (
- <React.Fragment>
- <List
- items={navigation}
- width={200}
- selectionMode="single"
- onSelectionChanged={this.loadView} />
- </React.Fragment>
- );
- }
- }
- export default NavigationList;
- import { createBrowserHistory } from "history";
- export default createBrowserHistory()
- /* ... */
- .dx-list-item-icon {
- margin-right: 10px;
- }
- import React from "react";
- class Inbox extends React.Component {
- render() {
- return (
- <div>Inbox</div>
- );
- }
- }
- export default Inbox;
- import React from "react";
- class SentMail extends React.Component {
- render() {
- return (
- <div>Sent Mail</div>
- );
- }
- }
- export default SentMail;
- import React from "react";
- class Spam extends React.Component {
- render() {
- return (
- <div>Spam</div>
- );
- }
- }
- export default Spam;
- import React from "react";
- class Trash extends React.Component {
- render() {
- return (
- <div>Trash</div>
- );
- }
- }
- export default Trash;
Run the code, open the Drawer, and click its items to change the views.
Configure the Reveal Behavior
When you open the Drawer, it can slide in or expand from the closed position. Use the revealMode option to specify this behavior.
- // ...
- class DxComponent extends React.Component {
- // ...
- render() {
- return (
- <React.Fragment>
- <Drawer ...
- revealMode="expand" >
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
Run the code and open the Drawer. You should see that the widget gets wider, but its content stays in place, creating an impression that the Drawer expands.
Configure Interaction with the View
When the Drawer opens, it can overlap, shrink, or partially displace the view, depending on the openedStateMode option:
- // ...
- class DxComponent extends React.Component {
- // ...
- render() {
- return (
- <React.Fragment>
- <Drawer ...
- openedStateMode="overlap" >
- </Drawer>
- </React.Fragment>
- );
- }
- }
- export default DxComponent;
Run the code, open the Drawer and you should see that it overlaps the view's text.
Change the Position
You can use the position option to anchor the Drawer to any side of the view. In this tutorial, the Drawer is in its default position (left).
You have configured basic Drawer features. For more information about this widget, explore the following resources:
If you have technical questions, please create a support ticket in the DevExpress Support Center.