feat(sidebar): carry a page's icon into the menu entry - #2102
Conversation
The sidebar renderer already reads a `pre` field for a leading icon and honors it at every level, but the page-hierarchy entry builder only ever set `title` and `link`. A site whose sidebar is derived from the page tree could therefore never show one, however its pages were authored, while a site driving the same sidebar from a data file could. Populates `pre` from the page's `icon` param, using the merge already used below for `pages`. The key is omitted when unset so the renderer's `with` guards stay false rather than seeing an empty string, which keeps existing output byte-identical for pages without an icon. Icons inherit the svg mode the sidebar's render sites already pass, so this does not touch the partialCached/symbols constraint documented at the top of assets/sidebar.html.
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Follow-up to the previous commit, which set `pre` unconditionally. That
silently changed every existing site: `icon` is authored for a page's
card, so sidebars gained icons nobody asked for, and only on the pages
that happen to set one. Hinode's own demo showed the failure — mod-docs
sets `icon` on a single page, so the sidebar rendered one lone icon
among thirty text rows.
Default is now off, and the depth is configurable because icons on the
top level alone is the common case:
navigation.sidebarIcons bool, site-wide (default false)
navigation.sidebarIconLevel int, deepest level (default 1)
Both cascade through per-page frontmatter and per-type `pages.<Type>`
defaults, resolved by a new `utilities/GetSidebarIcons.html` that
mirrors `utilities/GetIncludeTOC.html`.
Levels are counted as the sidebar renders them. `assets/sidebar.html`
drops the walk's root entry and promotes its children, so the root is
never a visible row — counting from the recursion root would have made
`sidebarIconLevel = 1` select an entry that is thrown away, which is
exactly what it did before this was measured.
Verified on a site with ~180 pages carrying `icon`, reading icon counts
out of the rendered sidebar:
default architecture 0 engineering 0
level 1 13 7
level 2 59 43
level 9 117 56
At level 1 the thirteen glyphs are distinct and match the thirteen
top-level sections exactly.
|
Pushed a follow-up that makes this opt-in — thanks for catching the demo. The deploy preview showed the problem clearly: Now off by default, with a configurable depth[navigation]
sidebarIcons = false # site-wide switch
sidebarIconLevel = 1 # deepest level that may show an iconA depth rather than a bool because icons on the top level only is the common case — that was the original request that started this. Both settings cascade through per-page frontmatter and per-type One thing worth flaggingLevels are counted as the sidebar renders them, not as the partial recurses. EvidenceIcon counts read out of the rendered sidebar on a site with ~180 pages carrying
At level 1 the thirteen glyphs are distinct and match the thirteen top-level sections exactly — so it is the top row, not an arbitrary subset. Every rendered icon remains a self-contained
Follow-onThe two settings need documenting on gethinode.com — I will raise that against |
|
🎉 This PR is included in version 3.13.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
The sidebar renderer already supports a leading icon, but only for data-file menus. A site whose sidebar is derived from the page tree can never show one.
The gap
assets/sidebar.htmlreads aprefield for a leading icon and honors it at every level —86,124,188,200,372,390,416,473,503.But
assets/helpers/sidebar-menu-entry.html:22, which builds entries for the page-hierarchy sidebar (assets/live-pages.html:244), only ever sets two keys:So
preis never populated on that path, and no amount of frontmatter can surface an icon. A site using adata/*.ymlmenu gets icons; a site using the page tree cannot.The change
Populate
prefrom the page'siconparam, using themergealready used a few lines below forpages:The key is omitted when unset, so the renderer's
withguards stay false rather than receiving an empty string. Output for pages without an icon is unchanged.Evidence
Built a consuming site with ~180 pages carrying
icon:frontmatter, before and after, via a module replacement:/architecture//engineering//reference/Every rendered icon is a self-contained
<svg><path>—<use href>count is 0 in all three.That last number is the one that matters here.
assets/sidebar.htmldocuments at length that icons in this partial must render in svg mode, because the partial ispartialCachedand symbols mode registers its<symbol>as a per-page side effect — the cached output would then carry<use href="#id">with nothing behind it. The comment also warns the failure is self-masking, since an icon shared with the page body still resolves. Populatingpreinherits the existing render sites'"mode" "svg", and the zero above confirms it rather than assuming it.pnpm testpasses.Context
Found while adding sidebar icons to two sites built on Hinode. One drives its docs sidebar from
data/docs.ymland needed only four lines of data; the other uses the page hierarchy and could not do it at all. This closes that asymmetry.