feat(#3589): add breadcrumb navigation to docs website#3590
feat(#3589): add breadcrumb navigation to docs website#3590
Conversation
0032c96 to
49cad8c
Compare
✅ Deploy Preview for goa-design-2 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
49cad8c to
ce5b943
Compare
| const crumbCount = Math.max(1, segments.length - 1); | ||
| for (let i = 0; i < crumbCount; i++) { | ||
| path += '/' + segments[i]; | ||
| crumbs.push({ label: segmentToLabel(segments[i]), url: path }); |
There was a problem hiding this comment.
This is usually great, but there are situations where a generated portion of the URL doesn't actually generate a workable page. Take the URL http://localhost:4203/foundations/style-guide/colour for example, takes you to Colour, and generates this as the breadcrumb:
The problem is, "Style guide" in that breadcrumb creates a link to /foundations/style-guide, which isn't an actual page.
I think we need some checking in here to verify that a created link is actually valid.
There was a problem hiding this comment.
I added a check that collects all valid page routes at build time. If an intermediate segment doesn't have a page, it shows as plain text instead of a link. So on the colour page you'd see "Style guide" as text and "Foundations" as a link.
| </li> | ||
| )} | ||
| <li class="sr-only" aria-current="page"> | ||
| {segmentToLabel(segments[segments.length - 1])} |
There was a problem hiding this comment.
This is likely pretty minor, but maybe an issue (I'm not sure). What the screen reader reads here doesn't line up with the header of the page in all situations:
- App Header - reads App Header - title reads Header
- Radio Group - reads Radio Group - title reads Radio
- File Upload Input - reads File Upload Input - title reads File uploader
- Linear Progress - reads Linear Progress - title reads Linear Progress Indicator
There was a problem hiding this comment.
Yeah, the sr-only text comes from the URL slug, so it won't always match the h1 exactly. I think it's close enough for now since it's only for screen readers and the context is still clear. We could add a prop to pass the real title if it becomes an issue.
Add Breadcrumbs component that derives navigation trail from URL path. Integrated into DocumentationPageLayout, TokensLayout, ExamplesPageLayout, and component page templates (inside each page's centering container to handle different max-widths). Replaces category badge on component pages and "Back to all examples" link on example pages. Component pages show their category in the breadcrumb trail with a link to the All Components page filtered by that category. ComponentsGrid now reads ?category= URL params to support this. Keyboard-only focus styles, visually-hidden current page for screen readers (aria-current="page").
ce5b943 to
74ed858
Compare
Summary
Closes #3589
Approach
Built as an Astro component first for our docs site as a proof of concept. We can learn from this before designing a shared Svelte breadcrumb component for the UI component library.
File-by-file walkthrough
Breadcrumbs.astro (new, 142 lines)
The core component. Derives the breadcrumb trail from the URL path automatically. Each segment gets a label from a lookup map (or falls back to formatting the slug). Always shows at least the section name. Has an optional
parentGroupprop for when the logical hierarchy isn't in the URL (only used by component pages for the category). Current page is visually hidden but available to screen readers viaaria-current="page". Uses design tokens for all styling, focus-visible for keyboard-only focus rings.ComponentsGrid.tsx (+16 lines)
Adds URL param reading on mount so
?category=inputs-and-actionspre-filters the grid. This is what makes the breadcrumb category link work. Same pattern ExamplesGrid already uses.DocumentationPageLayout.astro (+10 lines)
Adds breadcrumbs inside the content card.
breadcrumb-rowhas a 960px max-width to match the content grid centering.examples/index.astro (+2 lines) — Adds breadcrumbs to the All
Examples page.
TokensLayout.astro (+9 lines)
Same as above, 1408px max-width.
components/[slug].astro (+5/-4 lines)
Passes the component's category as
parentGroupwith a link to/components?category=.... Removes the old category badge that was above the title (breadcrumbs replace that context).components/index.astro (+2 lines)
Adds breadcrumbs to the All Components page.
examples/[slug].astro (-10 lines)
Adds breadcrumbs inside the page template (not the layout) so they align with the narrower content width. Removes the "Back to all examples" link and its CSS since breadcrumbs handle that navigation now.
Test plan