# NavigationDrawer

> A slide-out menu, or a fixed sidebar on Expanded and wider screens.

## Structure

This is a slide-out menu. Nest `<details>` / `<summary>` for nested sections — the documentation sidebar uses that. On Compact and Medium windows this same drawer slides over the page.

An overlay sidenav is a modal `<dialog>`. The framework wraps your `<ul class="navigation-drawer">`; `Escape` and a tap on the backdrop close it. A `navigation-drawer-fixed` drawer stays open from Expanded as CSS — no resize listener, no overlay.

The sidenav HTML must **not** sit inside the app bar’s `<nav>`. Put a `navigation-drawer-trigger` anywhere and set `data-target` to the navigation drawer’s `id`. `AutoInit()` starts every `.navigation-drawer` except those marked `no-autoinit`.

Toggle NavigationDrawer

-   [](#user)[John Doe](#name) [jdoe@example.com](#email)
    
-   First Link With Icon
-   Second Link

-   Subheader
-   Third Link
-   Close

```
<nav aria-label="Main">
  <ul id="slide-out" class="navigation-drawer">
    <li>
      <div class="user-view">
        <div class="background">
          <img src="images/office.jpg" alt="">
        </div>
        <a href="#user" aria-label="Profile"><img class="circle" src="images/portrait.jpg" alt=""></a>
        <a href="#name"><span class="name">John Doe</span></a>
        <a href="#email"><span class="email">jdoe@example.com</span></a>
      </div>
    </li>
    <li><a href="#!"><span class="material-symbols" aria-hidden="true">cloud</span>First Link With Icon</a></li>
    <li><a href="#!">Second Link</a></li>
    <li><div class="divider"></div></li>
    <li><span class="subheader">Subheader</span></li>
    <li><a href="#!">Third Link</a></li>
  </ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
```

## Initialization

The IIFE bundle exposes `Expressive.NavigationDrawer`. Call `init` yourself when you need options other than the defaults, or let `Expressive.AutoInit()` start every `.navigation-drawer`.

```
document.addEventListener('DOMContentLoaded', function() {
  const elems = document.querySelectorAll('.navigation-drawer');
  const instances = Expressive.NavigationDrawer.init(elems, {
    // specify options here
  });
});
```

## Options

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `edge` | String | `'left'` | Side of the screen. `'left'` or `'right'`. The constructor adds `right-aligned` when the edge is right. |
| `draggable` | Boolean | `true` | Allow swipe gestures to open and close. Drag is disabled while the navigation drawer is fixed on Expanded and wider windows. |
| `dragTargetWidth` | String | `'10px'` | Width of the screen-edge strip where a drag can start. |
| `onOpenStart` | Function | `null` | Called when the navigation drawer starts opening. |
| `onOpenEnd` | Function | `null` | Called when the navigation drawer finishes opening. |
| `onCloseStart` | Function | `null` | Called when the navigation drawer starts closing. |
| `onCloseEnd` | Function | `null` | Called when the navigation drawer finishes closing. |

## Methods

> All methods are called on the plugin instance. You can get the instance like this:

```
const instance = Expressive.NavigationDrawer.getInstance(elem);
```

### .open();

Opens the navigation drawer.

```
instance.open();
```

### .close();

Closes the navigation drawer.

```
instance.close();
```

### .destroy();

Destroy the plugin instance, unwrap the dialog host, and remove the drag target and event handlers.

```
instance.destroy();
```

## Properties

| Name | Type | Description |
| --- | --- | --- |
| `el` | Element | The DOM element the plugin was initialized with. |
| `options` | Object | The options the instance was initialized with. |
| `isOpen` | Boolean | Whether the overlay drawer is open. Stays false while a fixed sidenav is docked on Expanded and wider windows. |
| `isFixed` | Boolean | Whether the element has `navigation-drawer-fixed`. |
| `isDragged` | Boolean | Whether the navigation drawer is being dragged. |

## Close Trigger

Add `navigation-drawer-close` to an element inside the navigation drawer. A click on that element closes an overlay sidenav. That is useful in a single-page app where the page does not reload. It does nothing while the navigation drawer is fixed on Expanded and wider windows.

```
<nav aria-label="Main">
  <ul id="slide-out" class="navigation-drawer">
    <li><button type="button" class="navigation-drawer-close">Clicking this will close NavigationDrawer</button></li>
  </ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
```

## Variations

### Right edge

Pass `edge: 'right'`. Mark the element `no-autoinit` if you initialize it yourself, otherwise AutoInit would start it on the left.

Toggle Right NavigationDrawer

-   First Sidebar Link
-   Second Sidebar Link
-   Close

```
Expressive.NavigationDrawer.init(document.querySelector('#slide-out-right'), {
  edge: 'right'
});
```

### Nested sections

Nest `<details>` for a section that opens in place. Same `name` on several details is an accordion. The documentation sidebar uses this for Foundations, Structure, Components, and Forms.

-   Inbox
-   Foundations
    
    -   Color
    -   Typography
    
-   Structure
    
    -   App bar
    -   NavigationDrawer
    

```
<nav aria-label="Main">
  <ul id="slide-out" class="navigation-drawer">
    <li><a href="#!">First Sidebar Link</a></li>
    <li>
      <details name="docs-nav">
        <summary>
          <span class="material-symbols" aria-hidden="true">palette</span>
          Foundations
        </summary>
        <ul>
          <li><a href="#!">Color</a></li>
          <li><a href="#!">Typography</a></li>
        </ul>
      </details>
    </li>
  </ul>
</nav>
```

### Fixed HTML Structure

Add `navigation-drawer-fixed` so the navigation drawer stays open from Expanded (840px and up) and slides away on smaller ones. That dock is CSS, not a JavaScript `open()`. The documentation sidebar on the left is this pattern.

```
<nav aria-label="Main">
  <ul id="slide-out" class="navigation-drawer navigation-drawer-fixed">
    <li><a href="#!">First Sidebar Link</a></li>
    <li><a href="#!">Second Sidebar Link</a></li>
  </ul>
</nav>
<button type="button" data-target="slide-out" class="button text circle navigation-drawer-trigger" aria-label="Menu"><span class="material-symbols" aria-hidden="true">menu</span></button>
```

Offset the rest of the page by the navigation drawer width. The width token is `--md-comp-nav-drawer-width` (alias of `--md-comp-nav-drawer-width`, 300px). Put the padding on `header`, `main`, and `footer`.

```
@media (width >= 840px) {
  header, main, footer {
    padding-left: var(--md-comp-nav-drawer-width);
  }
}
```
