FairGarden Design

Nav Drawer

Primary navigation below --ds-nav-inline-n-above: a menu Button that opens a modal Dialog sheet in the header's own scope. It is the single owner of the mobile drawer; put it in the Navigation Bar's drawer slot, which removes it from the inline threshold.

import {
  NavDrawer,
  NavDrawerGroup,
  NavDrawerLink,
  NavDrawerFooter,
} from '@fairgarden-private/design/components/NavDrawer'

The menu Button shows the menu icon and "Menu", which swap to × and "Close" while the drawer is open. Below 360 px the label drops to the icon, and it stays the accessible name. The sheet is full screen below --md-n-above. From there it is a 480 px side sheet docked to the end edge, with a --ds-stroke-3 inner edge, and the page beside it is left unpainted and inert. No backdrop or tint is painted. The sheet re-declares the header's preset, so a page-ground header gives a page-ground sheet and a night header a night one, never a white overlay.

The drawer

The drawer

The sheet repeats the header's bar, with the close control where the menu Button was. Each NavDrawerGroup is an independent Collapsible, so several may be open. Its row is set in the display serif and carries LTA's expand/collapse glyph: arrows point out in --role-muted when collapsed and in, in --primary12, when expanded. The glyph swaps and never rotates. Child links sit on a hairline indent guide. A NavDrawerLink at the top level is a direct link styled as a row. The group holding the current page opens by default, and the current link takes the --ds-stroke-3 start-edge bar and weight 700. The list scrolls in a Scroll Area between the fixed bar and the NavDrawerFooter, which holds the action pill, the utility links and the locale Select. Pass sections (the shared navigation data from @fairgarden-private/design/utils/navigation) to build the rows from the object that also feeds the Navigation Menu and the footer sitemap: each section with links becomes a group, opening with its landing page, and a section with only an href a direct link. Focus moves to the first row, stays trapped, and returns to the menu Button on close. If the window widens past the inline threshold while the drawer is open, it closes and focus moves to the matching bar item.

NavDrawerBasic.tsx
'use client'

import * as React from 'react'
import { Button } from '@fairgarden-private/design/components/Button'
import {
  NavDrawer,
  NavDrawerFooter,
  NavDrawerGroup,
  NavDrawerLink,
} from '@fairgarden-private/design/components/NavDrawer'
import { Select } from '@fairgarden-private/design/components/Select'
import styles from './drawer.module.css'

const languages = [
  { value: 'en', label: 'English' },
  { value: 'es', label: 'Español' },
]

/**
 * The drawer on its own (in a header it sits in the Navigation Bar's
 * `drawer` slot). The page is in What We Do › Our Programs, so that group
 * opens with its row and link marked current.
 */
export function NavDrawerBasic() {
  return (
    <div className={styles.row}>
      <NavDrawer
        logo={<span className={styles.wordmark}>FairGarden</span>}
        logoLabel="FairGarden home"
        currentPath="/what-we-do/our-programs"
        footer={
          <NavDrawerFooter
            action={
              <Button variant="solid" size="lg" nativeButton={false} render={<a href="/donate" />}>
                Donate
              </Button>
            }
            locale={<Select items={languages} defaultValue="en" aria-label="Language" />}
          >
            <NavDrawerLink href="/about">About</NavDrawerLink>
            <NavDrawerLink href="/contact">Contact</NavDrawerLink>
            <NavDrawerLink href="/accessibility">Accessibility settings</NavDrawerLink>
          </NavDrawerFooter>
        }
      >
        <NavDrawerGroup label="Why Land Matters">
          <NavDrawerLink href="/why-land-matters">Why land matters</NavDrawerLink>
          <NavDrawerLink href="/why-land-matters/land-conservation">Land conservation</NavDrawerLink>
          <NavDrawerLink href="/why-land-matters/priorities">Conservation priorities</NavDrawerLink>
        </NavDrawerGroup>
        <NavDrawerGroup label="What We Do">
          <NavDrawerLink href="/what-we-do">What we do</NavDrawerLink>
          <NavDrawerLink href="/what-we-do/our-programs">Our programs</NavDrawerLink>
          <NavDrawerLink href="/what-we-do/impact">Our collective impact</NavDrawerLink>
        </NavDrawerGroup>
        <NavDrawerGroup label="Take Action">
          <NavDrawerLink href="/take-action/get-involved">Get involved</NavDrawerLink>
          <NavDrawerLink href="/take-action/conserve">Conserve your land</NavDrawerLink>
          <NavDrawerLink href="/take-action/give">Give</NavDrawerLink>
        </NavDrawerGroup>
        <NavDrawerLink href="/find-a-land-trust">Find a Land Trust</NavDrawerLink>
        <NavDrawerLink href="/news">News</NavDrawerLink>
      </NavDrawer>
    </div>
  )
}

API Reference

The navigation drawer below --ds-nav-inline-n-above [D183]: the menu Button (the menu icon plus “Menu”; × plus “Close” while open) and a modal Dialog sheet in the header’s own scope, full screen below --md-n-above and a 480 px side sheet with a --ds-stroke-3 inner edge from it. The sheet repeats the header’s bar with the close control where the menu Button was, lists independent Collapsible groups and direct links in a Scroll Area, and keeps its footer fixed. Focus moves to the first row, is trapped, and returns to the menu Button; no backdrop is painted. If the viewport reaches the inline threshold while open, it closes and focus goes to the matching bar item. Put it in the Navigation Bar’s drawer slot.

PropTypeDescription
label
string | undefined

The menu Button’s label, authored in title case [D160]. Default “Menu”.

defaultOpen
boolean | undefined

Initial open state. Default false.

open
boolean | undefined

Controlled open state.

onOpenChange
((open: boolean) => void) | undefined

Called when the drawer opens or closes.

closeLabel
string | undefined

The close control’s label. Default “Close”.

currentPath
string | undefined

The current page’s URL path. Default: the Navigation Bar’s.

footer
React.ReactNode | undefined

The fixed footer zone: a NavDrawerFooter.

logo
React.ReactNode | undefined

The logo repeated in the drawer’s bar. Default: the Navigation Bar’s.

logoHref
string | undefined

The logo link. Default: the Navigation Bar’s, else “/".

logoLabel
string | undefined

The logo link’s accessible name. Default: the Navigation Bar’s.

navLabel
string | undefined

The drawer nav’s name. Default “Main”.

primary
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null
| undefined

Override the header scope’s primary. Never defaulted [D133].

secondary
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'ruby'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null
| undefined

Override the header scope’s secondary. Never defaulted.

sections
SitemapSection[] | undefined

The top-level rows from the shared navigation data (utils/navigation), the object that also feeds NavigationMenuSections and Footer’s sitemap [D187]. A section with links is a group (its landing page first, then its links); one with only an href is a direct link. They come before children.

triggerClassName
string | undefined

Class names for the menu Button, added after its own.

children
React.ReactNode | undefined

The top-level rows: NavDrawerGroups and direct NavDrawerLinks.

className
string | undefined

Class names for the sheet, added after its own.

One top-level group: an independent Collapsible whose trigger row shows LTA’s expand/collapse glyph [D109] (outward in --role-muted, inward in --primary12 when open; it swaps, never rotates), over its child links on an indent guide. A group holding the current page opens by default and its row takes the start-edge bar (aria-current="true").

PropTypeDescription
label
React.ReactNode | undefined

The group row’s label, in the display serif (type-itemhead).

children
React.ReactNode | undefined

The group’s NavDrawerLinks. Nest groups one level deep at most.

A drawer link. At the top level it is a direct link, styled as a group row without the glyph (the bare-text underline on hover); in a group, a type-body-ui child link on the indent guide; in the footer, a utility link. Child and footer links are list links, whose hover is color only [D181]. The current page takes aria-current="page", the --ds-stroke-3 start-edge bar and weight 700.

PropTypeDescription
active
boolean | undefined

Marks the link as the current page. Default: its path equals the drawer’s currentPath.

The drawer’s fixed footer zone, under a --border-size-2 --role-rule: the primary pill first (where the header’s action goes below 360 px), then the utility links at a --ds-size-hit pitch, then the locale Select. Put it in the drawer’s footer.

PropTypeDescription
action
React.ReactNode | undefined

The primary pill: a solid Button at size="lg", hugging its label.

locale
React.ReactNode | undefined

The locale Select (or a locale link).

children
React.ReactNode | undefined

Utility links (NavDrawerLinks): the utility bar’s links, repeated.

Additional types

NavDrawerFooterProps
NavDrawerGroupProps
NavDrawerLinkProps
NavDrawerProps
navigationDrawer

Specification: DESIGN-SYSTEM.md §11.6 (mobile navigation drawer) [D97, D183], with the Dialog of §10.14 and the disclosure glyph of §10.13 [D109].