# Staggered Menu

> Side menu whose color layers slide in one after another, then the links rise into place with a staggered tilt while the toggle rolls from Menu to Close.

Click **Menu** to open: colored layers sweep in from the side one after another, the panel follows, and each link rises into place with a small tilt and its number fades in. Click **Close**, press Escape, pick a link or click outside to slide everything back.

<demo-staggered-menu>



</demo-staggered-menu>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/staggered-menu.json"
```

## Usage

```vue
<script setup lang="ts">
  import { StaggeredMenu } from '~/components/ui/staggered-menu';
  import type { MenuItem, SocialItem } from '~/components/ui/staggered-menu';

  const items: MenuItem[] = [
    { label: 'Home', ariaLabel: 'Go to Home section', link: '#home' },
    { label: 'About', ariaLabel: 'Go to About section', link: '#about' },
    {
      label: 'Projects',
      ariaLabel: 'Go to Projects section',
      link: '#projects',
    },
    { label: 'Contact', ariaLabel: 'Go to Contact section', link: '#contact' },
  ];

  const socialItems: SocialItem[] = [
    { label: 'GitHub', link: 'https://github.com/your-handle' },
    { label: 'Twitter', link: 'https://twitter.com/your-handle' },
  ];
</script>

<template>
  <div class="relative h-screen bg-zinc-900">
    <StaggeredMenu
      position="right"
      :items="items"
      :social-items="socialItems"
      :colors="['#B497CF', '#5227FF']"
      logo-url="/logo.svg"
      menu-button-color="#fff"
      open-menu-button-color="#18181b"
      accent-color="#5227FF"
      @menu-open="console.log('open')"
      @menu-close="console.log('close')"
    />
  </div>
</template>
```

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        position
      </code>
    </td>
    
    <td>
      <code>
        'left' | 'right'
      </code>
    </td>
    
    <td>
      <code>
        'right'
      </code>
    </td>
    
    <td>
      Side the panel slides in from
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        colors
      </code>
    </td>
    
    <td>
      <code>
        string[]
      </code>
    </td>
    
    <td>
      <code>
        ['#B497CF', '#5227FF']
      </code>
    </td>
    
    <td>
      Colors of the layers that sweep in before the panel (up to 4; with 3 or more the middle one is dropped)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        items
      </code>
    </td>
    
    <td>
      <code>
        MenuItem[]
      </code>
    </td>
    
    <td>
      <code>
        []
      </code>
    </td>
    
    <td>
      Links in the panel (<code>
        label
      </code>
      
      , <code>
        link
      </code>
      
      , <code>
        ariaLabel?
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        social-items
      </code>
    </td>
    
    <td>
      <code>
        SocialItem[]
      </code>
    </td>
    
    <td>
      <code>
        []
      </code>
    </td>
    
    <td>
      Social links at the bottom of the panel (<code>
        label
      </code>
      
      , <code>
        link
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        display-socials
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Show the social links
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        display-item-numbering
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Show 01, 02… next to each link
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        logo-url
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Logo image in the header. Inverted while open below 1024px
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        menu-button-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#fff'
      </code>
    </td>
    
    <td>
      Toggle color while closed
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        open-menu-button-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#fff'
      </code>
    </td>
    
    <td>
      Toggle color while open
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        accent-color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#5227FF'
      </code>
    </td>
    
    <td>
      Hover color for links, numbers and the socials title
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        change-menu-color-on-open
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Fade the toggle to <code>
        open-menu-button-color
      </code>
      
       when opening
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        is-fixed
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Pin the menu to the viewport instead of its container
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        close-on-click-away
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Close when clicking outside the panel
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the wrapper
    </td>
  </tr>
</tbody>
</table>

## Events

<table>
<thead>
  <tr>
    <th>
      Event
    </th>
    
    <th>
      Payload
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        menu-open
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fired when the menu opens
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        menu-close
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Fired when the menu closes
    </td>
  </tr>
</tbody>
</table>

## Slots

<table>
<thead>
  <tr>
    <th>
      Slot
    </th>
    
    <th>
      Props
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        logo
      </code>
    </td>
    
    <td>
      <code>
        { open: boolean }
      </code>
    </td>
    
    <td>
      Custom header logo. Replaces the <code>
        logo-url
      </code>
      
       image
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The toggle is a real button with `aria-expanded`, `aria-controls` and an "Open menu" / "Close menu" label.
- While closed the panel is `inert` and `aria-hidden`, so its links are skipped by keyboard and screen readers.
- Escape closes the menu and returns focus to the toggle. Links and the toggle show visible focus rings.
- `prefers-reduced-motion: reduce` makes every transition instant.
- Ported from [React Bits](https://reactbits.dev/components/staggered-menu) by David Haz.
