Vertical Navigation

The <nys-verticalnav> component renders a side navigation menu on desktop and collapses into a <nys-accordion> on tablet and mobile. It is commonly used on sites and applications with many links that may not fit in a horizontal navigation.

Copy Code
<nys-verticalnav heading="Freshwater Fishing" headingLevel="h2">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/services">Services</a></li>
    <li>
      <h3>Freshwater Fishing Regulations</h3>
      <ul>
        <li><a href="">Places to Fish</a></li>
        <li><a href="">Learn to Fish</a></li>
        <li><a href="">Ice Fishing</a></li>
      </ul>
    </li>
  </ul>
</nys-verticalnav>

Can't use NYS Design System web components in your project? Try using the CSS Variables instead.


Accessibility

The <nys-verticalnav> component includes the following accessibility-focused features:

  • The nav region is labeled via aria-labelledby (pointing to the header) or aria-label when the header is hidden.
  • On mobile, the nav becomes an accordion, keeping all links reachable with the same keyboard interactions as nys-accordion.
  • A link with aria-current="page" automatically gets active styling, and any containing nys-verticalnavgroup auto-expands so the active link is visible on load.
  • nys-verticalnavgroup triggers are real <button> elements with aria-expanded reflecting open/closed state.

Note: <a> elements have no native disabled attribute, so <nys-verticalnavgroup disabled> only disables the group's own toggle button — it doesn't affect the links inside. To mark an individual link as disabled, add aria-disabled="true" to that <a> directly:

Additional accessibility test and build content is coming soon, in a new format.


Options

Header slot

Replace the default heading with custom markup using the header slot.

Freshwater Fishing

2026 Season Open

Copy Code
<style>
  [slot="header"] {
    padding-left: var(--nys-space-100, 8px);
    padding-top: var(--nys-space-100, 8px);
  }
  [slot="header"] h2 {
    margin: 0;
    font-size: var(--nys-font-size-h4, 1.25rem);
    color: var(--nys-color-theme, #154973);
  }
  [slot="header"] p {
    font-size: var(--nys-font-size-xs, 0.75rem);
    color: var(--nys-color-success, #2e7d32);
    font-weight: 500;
    margin: 0;
  }
</style>
<nys-verticalnav heading="Freshwater Fishing" headingLevel="h2">
  <div slot="header">
    <h2>Freshwater Fishing</h2>
    <p>2026 Season Open</p>
  </div>
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/services">Services</a></li>
  </ul>
</nys-verticalnav>

Add extra content below the links, like a divider and contact info.

Regulations last updated: January 2026

Contact the DEC for fishing inquiries
Copy Code
<style>
  [slot="footer"] {
    display: flex;
    flex-direction: column;
    gap: var(--nys-space-100, 8px);
    padding: 0 var(--nys-space-100, 8px) var(--nys-space-100, 8px);
  }
  [slot="footer"] p {
    margin: 0;
    font-size: var(--nys-font-size-xs, 0.75rem);
    color: var(--nys-color-text-weak, #4a4d4f);
  }
  [slot="footer"] a {
    font-size: var(--nys-font-size-sm, 0.875rem);
    color: var(--nys-color-theme, #154973);
  }
</style>
<nys-verticalnav heading="Freshwater Fishing" headingLevel="h2">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/services">Services</a></li>
  </ul>
  <div slot="footer">
    <nys-divider></nys-divider>
    <p>Regulations last updated: January 2026</p>
    <a href="/contact-dec">Contact the DEC for fishing inquiries</a>
  </div>
</nys-verticalnav>

Collapsible groups

Use <nys-verticalnavgroup> for a set of links that expand and collapse. Add expanded to open it by default, or disabled to prevent interaction.

Copy Code
<nys-verticalnav heading="NYS Design System" headingLevel="h2">
  <ul>
    <li><a href="/">Foundations</a></li>
    <li>
      <nys-verticalnavgroup label="Accessibility">
        <ul>
          <li><a href="">WCAG Guidelines</a></li>
          <li><a href="">Screen Readers</a></li>
          <li><a href="">Color Contrast</a></li>
        </ul>
      </nys-verticalnavgroup>
    </li>
  </ul>
</nys-verticalnav>

Set aria-current="page" on a link to mark it active. If it's inside a nys-verticalnavgroup, the group auto-expands.

Copy Code
<nys-verticalnav heading="NYS Design System" headingLevel="h2">
  <ul>
    <li><a href="/">Foundations</a></li>
    <li>
      <nys-verticalnavgroup label="Accessibility">
        <ul>
          <li><a aria-current="page" href="">WCAG Guidelines</a></li>
          <li><a href="">Screen Readers</a></li>
        </ul>
      </nys-verticalnavgroup>
    </li>
  </ul>
</nys-verticalnav>

Disabled state

Add disabled to nys-verticalnavgroup to prevent the whole group from being toggled. For individual links outside a group, add aria-disabled="true" directly to the <a>. Links have no native disabled attribute, so this is the only way to mark one as unavailable.

Copy Code
<nys-verticalnav heading="NYS Design System" headingLevel="h2">
  <ul>
    <li><a href="/">Foundations</a></li>
    <li><a href="/components">Components</a></li>
    <li>
      <nys-verticalnavgroup disabled label="Accessibility">
        <ul>
          <li><a aria-disabled="true">WCAG Guidelines</a></li>
          <li><a href="">Screen Readers</a></li>
          <li><a href="">Color Contrast</a></li>
        </ul>
      </nys-verticalnavgroup>
    </li>
    <li>
      <h3>Resources</h3>
      <ul>
        <li><a aria-disabled="true">Design Tokens</a></li>
        <li><a href="">Utilities</a></li>
      </ul>
    </li>
  </ul>
</nys-verticalnav>

Hidden heading

A heading is required for the vertical navigation. If a visible heading is not needed on desktop, use hideHeading to visually hide it.

Note: The heading text is still used as the accessible label for the accordion on smaller screens and mobile devices (resize the screen to see this in action).

Copy Code
<nys-verticalnav heading="Section nav" hideHeading>
  <ul>
    <li><a href="/home">Home</a></li>
  </ul>
</nys-verticalnav>

Page layout

Use <nys-verticalnav> alongside a global header and footer to build a full page layout. On screens below 1024px, the nav collapses into an accordion automatically.

This example uses the NYSDS grid to lay out the nav and main content side by side, switching to a stacked layout at the nys-desktop breakpoint (1024px). This approach matches the width at which <nys-verticalnav> itself collapses into an accordion.

Note: The example below is for guidance only. Adjust the styles to fit your application's layout needs. <nys-verticalnav> doesn't add its own outer spacing, so wrap it (like .page-layout__nav below) and add padding yourself to match your site's layout.

Copy Code
<style>
  .page-layout__body {
    background-color: var(--nys-color-white, #ffffff);
  }
  .page-layout__nav {
    padding: var(--nys-space-300, 24px) var(--nys-space-50, 4px) var(--nys-space-300, 24px) 0;
  }
  .page-layout__main {
    padding: var(--nys-space-400, 32px);
  }
</style>
<div>
  <nys-unavheader></nys-unavheader>
  <nys-globalheader homepageLink="https://ny.gov" agencyName="Office of Information Technology Services">
    <ul>
      <li><a href="https://its.ny.gov/services">Services</a></li>
      <li><a href="https://its.ny.gov/get-help">Help Center</a></li>
    </ul>
  </nys-globalheader>
  <div class="page-layout__body">
    <div class="nys-grid-container nys-grid-gap-400">
      <div class="nys-grid-row">
        <div class="nys-desktop:nys-grid-col page-layout__nav">
          <nys-verticalnav heading="NYS Design System" headingLevel="h2">
            <ul>
              <li><a href="/">Foundations</a></li>
              <li><a href="/components">Components</a></li>
              <li>
                <nys-verticalnavgroup label="Accessibility">
                  <ul>
                    <li><a href="">WCAG Guidelines</a></li>
                    <li><a href="">Screen Readers</a></li>
                    <li><a href="">Color Contrast</a></li>
                  </ul>
                </nys-verticalnavgroup>
              </li>
              <li>
                <h3>Resources</h3>
                <ul>
                  <li><a href="">Design Tokens</a></li>
                  <li><a href="">Utilities</a></li>
                </ul>
              </li>
            </ul>
          </nys-verticalnav>
        </div>
        <main class="nys-desktop:nys-grid-col page-layout__main">
          <p>Place content here.</p>
        </main>
      </div>
    </div>
  </div>
  <nys-globalfooter agencyName="Agency Name" homepageLink="https://ny.gov">
    <ul>
      <li><a href="https://"> Privacy Policy </a></li>
      <li><a href="https://"> Terms of Service </a></li>
    </ul>
  </nys-globalfooter>
  <nys-unavfooter></nys-unavfooter>
</div>

Mobile controls

Call open(), close(), or toggle() on the mobile version of nys-verticalnav to control the mobile accordion programmatically.

Note: useful for a hamburger button or other trigger placed outside the nav itself. These methods only have a visible effect below the 1024px breakpoint, where the nav renders as an accordion; at desktop widths the nav is always visible.

Copy Code
<nys-verticalnav id="my-nav">
  <ul>
    <li><a href="/">Foundations</a></li>
    <li><a href="/components">Components</a></li>
    <li>
      <nys-verticalnavgroup label="Accessibility">
        <ul>
          <li><a href="">WCAG Guidelines</a></li>
          <li><a href="">Screen Readers</a></li>
          <li><a href="">Color Contrast</a></li>
        </ul>
      </nys-verticalnavgroup>
    </li>
    <li>
      <h3>Resources</h3>
      <ul>
        <li><a href="">Design Tokens</a></li>
        <li><a href="">Utilities</a></li>
      </ul>
    </li>
  </ul>
</nys-verticalnav>
<nys-button label="Toggle navigation (mobile view only)" onclick="document.querySelector('#my-nav').toggle()"></nys-button>

Usage

Do

  • Use for navigation where every item links to a different page.
  • Use for section-level navigation within a site.
  • Support up to two levels of navigation: top-level links and one level of nested links.
  • Set aria-current="page" on the active link so the component can apply active styles and expand the current group.
  • Avoid excessive use of icons, colors, or badges in navigation items.

Don't

  • Don't use for in-page navigation, such as scrolling to sections on the same page.
  • Don't use for linear task flows, such as multi-step forms or wizards.
  • Don't use for filtering, tab switching, or other in-page interactions.
  • Don't nest more than one level of sub-items.
  • Don't overload with excessive use of icons, colors, or badges in navigation items.

Properties

nys-verticalnav

Property Type Default Description
heading String "Page navigation" Heading text, and the accessible label when hideHeading is set.
headingLevel "h1" | "h2" | "h3" | "h4" | "h5" | "h6" "h2" Heading tag used for the auto-generated heading.
hideHeading Boolean false Hides the visible heading. heading is still used as the nav's accessible label.

nys-verticalnavgroup

Property Type Default Description
label String Text shown on the toggle button.
expanded Boolean false Opens the group by default.
disabled Boolean false Prevents the group from being toggled.
active Boolean false Set automatically when the group contains the active link. Not meant to be set manually.

Style Overrides

There are no existing CSS variables for this component. Explore existing options, or propose a new one with a Component Proposal.


Events

The <nys-verticalnav> component emits one custom Javascript event:

  1. nys-verticalnav-toggle – Fired when the mobile accordion is expanded or collapsed. This only applies on smaller screens, where the nav collapses into an accordion (see Page layout). On desktop the nav is always visible and this event does not fire.

Event details

The nys-verticalnav-toggle event includes a detail object with the following properties:

  • id (string): The id of the vertical nav.
  • expanded (boolean): Whether the nav is now expanded.

You can listen to these events using JavaScript:

Copy Code
// Select the vertical nav component
const verticalnav = document.querySelector('nys-verticalnav');
// Listen for the 'nys-verticalnav-toggle' event (mobile accordion only)
verticalnav.addEventListener('nys-verticalnav-toggle', (event) => {
  const { id, expanded } = event.detail;
  console.log(`Vertical nav with id="${id}" is now ${expanded ? "expanded" : "collapsed"}.`);
});

Suggest a New Component

Do you have an idea for a new NYS Design System web component? Look through the existing proposals in our GitHub discussions board to see if someone already proposed something similar. If not, feel free to submit one.