Skip to content

Side navigation

Side navigation lists places down the left edge of the screen and marks the one you are in. It holds the blocks of a long page, or the workspaces and modules of WerkOS.

Page and product

On a long page, the list beside the content shows the page title and its blocks. It follows you down the page and marks the block you are reading.

A page at 1440 px, with its third block marked

In WerkOS, the rail on the far left switches workspaces. Expand it and the modules panel opens beside it, with the modules of that workspace in folders.

Projects chosen in the rail, Global Projects in the panel

When to use it

Use the page list on a page with three or more blocks. A shorter page, or an overview that is itself a list of links, does without it.

Keep side navigation to two levels. A deeper hierarchy, such as the documents of one candidate, belongs inside the page, with a breadcrumb above it. Leave actions and filters out of the list, so it stays a map.

Name each row with the word people use for the place. Module names are proper names and keep their capitals, such as Global Projects. Everything else is in sentence case. A module a person has no access to is left out.

Anatomy

Rows sit on the same pitch in both uses. Only the rows of WerkOS carry an icon, one per module.

Page list width
Two of twelve columns
--leftnav-w
Row
36 px, text inset 16 px
--space-4
Sticky offset
24 px under the header
--space-6
Rail
84 px wide, 24 px radius
--radius-3xl
Rail tile
36 px icon box, 17 px glyph, 10 px label. A 32 px box on a short window
Modules panel
232 px wide, pushes the content aside
Folder title
Bold, full ink, after a 14 px chevron
Module row
36 px, 18 px glyph, 10 px gap, 8 px radius
--radius-lg

Showing where you are

On a page, the current row gets a thin outline, which follows you as you scroll without a heavy fill jumping from row to row.

In WerkOS, the module you are in gets a soft blue fill, full ink and a heavier glyph. A module that is coming sits faded with the word Soon.

On a page. Point at a row, or tab to it.
  • Global ProjectsIdle
  • Global ProjectsHover
  • Global ProjectsCurrent
  • Global ProjectsFocus
  • Global ProjectsSoonComing soon
In WerkOS
Idle
Muted ink
--text-muted
Hover on a page
Fill, full ink
--surface-control
Hover in WerkOS
Soft fill, the ink stays
--glass-fill-hover
Current on a page
1 px outline, full radius, full ink
--text
Current in WerkOS
Soft blue fill, full ink, glyph stroke 2
--nav-fill-active
Coming soon
The whole row at 60 percent, the word Soon
Focus
2 px ring
--focus-ring

Behavior

The page list marks the block whose heading last passed under the header. At the bottom of the page the last block is marked, even when it is too short to reach the top.

Choosing a row scrolls to its block and moves focus to its heading. The list scrolls on its own when it is taller than the window, and keeps the current row in view.

The first tile, Expand or Collapse, opens and closes the modules panel, which pushes the content aside. The panel and its folders remember their state. Long labels wrap on a page and end in an ellipsis in the panel.

Keyboard and screen readers

Each list is a navigation landmark with its own name: On this page, Main navigation for the rail, and Modules. The current link carries aria-current. A closed modules panel is inert, so Tab does not walk into links you cannot see.

Tab
Moves from link to link
Enter
Follows the link
Enter or Space on a folder
Opens or closes the folder

Permitted and not permitted

Permitted

  • A current item at each level

    The rail and the panel both show where you are.

  • The word Soon after a module that is coming

    It keeps its place, and it is not a link.

Not permitted

  • A third level of nesting

    People lose track of where they are. Move the depth into the page.

  • Color alone for the current item

    People who cannot tell hues apart lose their place.

  • A pill around the word Soon

    The faded row already says it.

NextTabs

Side navigation

A list of places on the left edge that marks the current one: the blocks of a long page, or the WerkOS rail and modules panel.

  • Kind: component
  • Page: https://design.werklist.com/components/side-navigation
  • Version: 2.1.2

When to use it

  • Page list: pages with three or more blocks.
  • Rail: switching WerkOS workspaces from 1024 px.
  • Modules panel: the modules of the current workspace, grouped in folders.

When not to use it

  • Pages with fewer than three blocks and overview pages.
  • More than two levels of hierarchy.
  • Actions, filters or editing inside the list.
  • Screens under 1024 px: WerkOS uses mobile navigation there, and a website page shows no page list.

Anatomy

  • Page list: columns 1 and 2 of the twelve column grid from 1024 px, with no fill, border or radius (--leftnav-w)
  • Page list title: the page title, 24 px on 32 px, weight 700, with 16 px under it. Plain text, not a heading and not a link (--text)
  • Page list row: 36 px, padding 8 px by 16 px, 56 px when the label wraps to two lines (--type-nav, --space-4)
  • Page list position: sticks 24 px under the header and scrolls on its own when taller than the window (--space-6)
  • Rail: a floating glass panel 84 px wide, radius 24 px, 8 px in from the edges of the window. Its head holds the 22 px mark stroked in a blue gradient, 56 px high, 48 px on a short window (--radius-3xl, --glass-fill, --glass-highlight, --glass-ring, --glass-shadow-panel)
  • Rail tile: 36 px icon box, radius 12 px, 17 px glyph, 10 px label at weight 500, tiles 12 px apart. On a window under 960 px high: 32 px box, 16 px glyph, 10 px apart (--radius-xl)
  • Profile tile: the last tile is the person's picture, 22 px, 20 px on a short window, with a 1 px ring (--border-rule)
  • Modules panel: 232 px, radius 24 px, docked 6 px from the rail, pushes the content aside. Its head is 56 px, with the workspace glyph at 17 px in muted ink and the workspace name in bold (--glass-fill-panel, --glass-fill, --radius-3xl)
  • Folder toggle: 14 px chevron in muted ink, turned 90 degrees when open. Title in bold, full ink. Padding 4 px by 6 px, radius 8 px (--text, --text-muted, --radius-lg)
  • Module row: 36 px, padding 8 px, gap 10 px, radius 8 px, 18 px glyph, label 14 px at weight 500, rows 2 px apart (--radius-lg, --type-nav)
  • Upcoming module: the whole row at 60 percent, not a link, with the word Soon after the label and no pill (--text-muted, --type-caption)

Variants

  • Page list: Blocks of one page, with scroll spy.
  • Rail: WerkOS workspaces and shared pages.
  • Modules panel: Modules of the current workspace.

States

  • Idle: Muted ink, glyph stroke 1.75 (--text-muted)
  • Hover, page list: Fill at full radius, full ink (--surface-control, --text)
  • Hover, rail and panel: Soft glass fill. A panel row keeps its muted ink, a rail label turns full ink (--glass-fill-hover)
  • Current, page list: 1 px outline in full ink at full radius, full ink, aria-current location (--text, --radius-full)
  • Current, rail and panel: Soft blue fill, full ink, glyph stroke 2, aria-current page. In the rail the fill glides to the new tile (--nav-fill-active, --text)
  • Focus: 2 px ring, drawn inside the tile in the rail (--focus-ring)
  • Panel closed: No width, out of the tab order and hidden from screen readers. Opens in 150 ms (--duration-fast, --ease-soft)
  • Forced colors: The current WerkOS row also gets a 1 px outline, since fills are removed

Keyboard

  • Tab: Next link
  • Enter: Follows the link. On the page list, scrolls to the block and focuses its heading
  • Enter or Space on a folder: Toggles the folder

Accessibility

  • Landmarks: nav named On this page, nav named Main navigation for the rail, nav named Modules.
  • Current link: aria-current location on the page list, page in the rail and the panel.
  • Folder toggles are buttons with aria-expanded.
  • A closed modules panel is inert and hidden from screen readers.
  • After a jump, focus lands on the block heading, and the heading stops clear of the sticky header.
  • Idle ink meets 4.5 to 1 on the page color in both themes.
  • Upcoming rows carry aria-disabled true.

Content

  • Row labels: the name people use for the place. Module names are proper names and keep their capitals: Global Projects, Job Board. Everything else is in sentence case.
  • Folder titles: one short noun each, such as People or Organizations.
  • Upcoming modules: the word Soon, as text.

Tokens

  • --leftnav-w
  • --type-nav
  • --type-caption
  • --space-4
  • --text
  • --text-muted
  • --surface-control
  • --radius-full
  • --radius-lg
  • --radius-xl
  • --radius-3xl
  • --nav-fill-active
  • --glass-fill-hover
  • --glass-fill-panel
  • --glass-fill
  • --glass-shadow-panel
  • --glass-highlight
  • --glass-ring
  • --border-rule
  • --focus-ring
  • --space-6
  • --duration-fast
  • --ease-soft

JSON

{
  "title": "Side navigation",
  "path": "/components/side-navigation",
  "url": "https://design.werklist.com/components/side-navigation",
  "text": "https://design.werklist.com/agent/components/side-navigation",
  "summary": "A list of places down the left edge that shows where you are: the blocks of a long page, or the workspaces and modules of WerkOS.",
  "version": "2.1.2",
  "kind": "component",
  "name": "Side navigation",
  "purpose": "A list of places on the left edge that marks the current one: the blocks of a long page, or the WerkOS rail and modules panel.",
  "use": [
    "Page list: pages with three or more blocks.",
    "Rail: switching WerkOS workspaces from 1024 px.",
    "Modules panel: the modules of the current workspace, grouped in folders."
  ],
  "avoid": [
    "Pages with fewer than three blocks and overview pages.",
    "More than two levels of hierarchy.",
    "Actions, filters or editing inside the list.",
    "Screens under 1024 px: WerkOS uses mobile navigation there, and a website page shows no page list."
  ],
  "anatomy": [
    {
      "part": "Page list",
      "measure": "columns 1 and 2 of the twelve column grid from 1024 px, with no fill, border or radius",
      "token": "--leftnav-w"
    },
    {
      "part": "Page list title",
      "measure": "the page title, 24 px on 32 px, weight 700, with 16 px under it. Plain text, not a heading and not a link",
      "token": "--text"
    },
    {
      "part": "Page list row",
      "measure": "36 px, padding 8 px by 16 px, 56 px when the label wraps to two lines",
      "token": "--type-nav, --space-4"
    },
    {
      "part": "Page list position",
      "measure": "sticks 24 px under the header and scrolls on its own when taller than the window",
      "token": "--space-6"
    },
    {
      "part": "Rail",
      "measure": "a floating glass panel 84 px wide, radius 24 px, 8 px in from the edges of the window. Its head holds the 22 px mark stroked in a blue gradient, 56 px high, 48 px on a short window",
      "token": "--radius-3xl, --glass-fill, --glass-highlight, --glass-ring, --glass-shadow-panel"
    },
    {
      "part": "Rail tile",
      "measure": "36 px icon box, radius 12 px, 17 px glyph, 10 px label at weight 500, tiles 12 px apart. On a window under 960 px high: 32 px box, 16 px glyph, 10 px apart",
      "token": "--radius-xl"
    },
    {
      "part": "Profile tile",
      "measure": "the last tile is the person's picture, 22 px, 20 px on a short window, with a 1 px ring",
      "token": "--border-rule"
    },
    {
      "part": "Modules panel",
      "measure": "232 px, radius 24 px, docked 6 px from the rail, pushes the content aside. Its head is 56 px, with the workspace glyph at 17 px in muted ink and the workspace name in bold",
      "token": "--glass-fill-panel, --glass-fill, --radius-3xl"
    },
    {
      "part": "Folder toggle",
      "measure": "14 px chevron in muted ink, turned 90 degrees when open. Title in bold, full ink. Padding 4 px by 6 px, radius 8 px",
      "token": "--text, --text-muted, --radius-lg"
    },
    {
      "part": "Module row",
      "measure": "36 px, padding 8 px, gap 10 px, radius 8 px, 18 px glyph, label 14 px at weight 500, rows 2 px apart",
      "token": "--radius-lg, --type-nav"
    },
    {
      "part": "Upcoming module",
      "measure": "the whole row at 60 percent, not a link, with the word Soon after the label and no pill",
      "token": "--text-muted, --type-caption"
    }
  ],
  "variants": [
    {
      "name": "Page list",
      "use": "Blocks of one page, with scroll spy."
    },
    {
      "name": "Rail",
      "use": "WerkOS workspaces and shared pages."
    },
    {
      "name": "Modules panel",
      "use": "Modules of the current workspace."
    }
  ],
  "states": [
    {
      "name": "Idle",
      "change": "Muted ink, glyph stroke 1.75",
      "tokens": [
        "--text-muted"
      ]
    },
    {
      "name": "Hover, page list",
      "change": "Fill at full radius, full ink",
      "tokens": [
        "--surface-control",
        "--text"
      ]
    },
    {
      "name": "Hover, rail and panel",
      "change": "Soft glass fill. A panel row keeps its muted ink, a rail label turns full ink",
      "tokens": [
        "--glass-fill-hover"
      ]
    },
    {
      "name": "Current, page list",
      "change": "1 px outline in full ink at full radius, full ink, aria-current location",
      "tokens": [
        "--text",
        "--radius-full"
      ]
    },
    {
      "name": "Current, rail and panel",
      "change": "Soft blue fill, full ink, glyph stroke 2, aria-current page. In the rail the fill glides to the new tile",
      "tokens": [
        "--nav-fill-active",
        "--text"
      ]
    },
    {
      "name": "Focus",
      "change": "2 px ring, drawn inside the tile in the rail",
      "tokens": [
        "--focus-ring"
      ]
    },
    {
      "name": "Panel closed",
      "change": "No width, out of the tab order and hidden from screen readers. Opens in 150 ms",
      "tokens": [
        "--duration-fast",
        "--ease-soft"
      ]
    },
    {
      "name": "Forced colors",
      "change": "The current WerkOS row also gets a 1 px outline, since fills are removed"
    }
  ],
  "keys": [
    {
      "key": "Tab",
      "action": "Next link"
    },
    {
      "key": "Enter",
      "action": "Follows the link. On the page list, scrolls to the block and focuses its heading"
    },
    {
      "key": "Enter or Space on a folder",
      "action": "Toggles the folder"
    }
  ],
  "accessibility": [
    "Landmarks: nav named On this page, nav named Main navigation for the rail, nav named Modules.",
    "Current link: aria-current location on the page list, page in the rail and the panel.",
    "Folder toggles are buttons with aria-expanded.",
    "A closed modules panel is inert and hidden from screen readers.",
    "After a jump, focus lands on the block heading, and the heading stops clear of the sticky header.",
    "Idle ink meets 4.5 to 1 on the page color in both themes.",
    "Upcoming rows carry aria-disabled true."
  ],
  "content": [
    "Row labels: the name people use for the place. Module names are proper names and keep their capitals: Global Projects, Job Board. Everything else is in sentence case.",
    "Folder titles: one short noun each, such as People or Organizations.",
    "Upcoming modules: the word Soon, as text."
  ],
  "tokens": [
    "--leftnav-w",
    "--type-nav",
    "--type-caption",
    "--space-4",
    "--text",
    "--text-muted",
    "--surface-control",
    "--radius-full",
    "--radius-lg",
    "--radius-xl",
    "--radius-3xl",
    "--nav-fill-active",
    "--glass-fill-hover",
    "--glass-fill-panel",
    "--glass-fill",
    "--glass-shadow-panel",
    "--glass-highlight",
    "--glass-ring",
    "--border-rule",
    "--focus-ring",
    "--space-6",
    "--duration-fast",
    "--ease-soft"
  ]
}

Raw file: https://design.werklist.com/agent/components/side-navigation