Repository navigation
Description
Part of the SPA look-and-feel pass (design review 2026-09-02). Siblings: #650 #651 #652 #653 #654 #655 #656. Independent of them except #652 (caps labels), which touches the .eyebrow this page uses twice.
Problem
web/src/routes/HelpPage.tsx is one 676-line scroll: 27 sections, ~104 bullets, a sticky contents rail, and the glossary at the very bottom — 51 terms in one flat two-column table.data (<h3 id="glossary">, line ~553). The docs-sync rule (AGENTS.md, 2026-07-17) makes both grow with every PR, which is right, but the page has no structure that scales with it:
- Glossary order is shipping order, not alphabetical or by domain: Navigation, Page loading, Searchable picker, Operational day, Install to home screen, New version ready, Farm code, … then Daily entry, Egg lot, Grade. A reader looking up "Cull" scans 20 UI-chrome rows first.
- No search. No per-term anchor, so a screen cannot link "what does Restricted mean?" to its definition — the in-app glossary is not reachable from where the term appears.
- Table markup for a definition list:
th[scope=row]+td, hairline rows, no rhythm between term and definition, definitions run the full column width (~48rem, >80 characters a line). - "Fixing mistakes" — the section people actually come for — is the 24th of 27.
- Two
.eyebrowcaps labels (SPA: retire tracked all-caps labels outside the nav group dividers #652).
Proposal
Glossary
<dl>with a stableidper term (glossary-egg-lot), term in--ink600, definition ≤ 60ch at 1.6 line-height, a hairline between entries not a table grid. Deep-linkable:/help#glossary-egg-lot.- Group by domain, alphabetical inside the group: Getting around · Signing in · Flocks & daily entry · Eggs, grades & stock · Sales & money · Messages you may see. A small jump rail for the groups.
- Filter-as-you-type box over term + definition (client-side, 51 entries — trivial).
aria-livecount of matches. - Where a screen shows a glossary term as a badge or column header (
StatusBadge, Restricted, Sellable, Hen-day %), a quiet "?" link to the anchor. Start with the status badges and the Stock/Reports headers.
Guide (the rest of the page)
5. Move Fixing mistakes to directly after The daily loop. Reorder the rail to match.
6. Split the rail into the same domain groups as the glossary, so the two halves of the page share one map.
7. Search box (item 3) searches guide sections too — heading + bullet text.
8. .eyebrow → sentence-case section kicker or removed (#652).
Guard
9. A parity test that every term in the SPA glossary has a heading in specs/product/GLOSSARY.md and vice versa (or a documented exclusion list) — the docs-sync rule is enforced by review today, not by a test. Walk both lists, exclude deliberately (AGENTS.md "Writing a guard").
Acceptance
- Glossary is a
<dl>, grouped and alphabetised, every term deep-linkable;TOCids inHelpPage.tsxunchanged (they drive the scroll-spy and existing anchors). - Search filters glossary + guide; empty result says so and offers to clear.
- At least the status badges link to their glossary entry.
- Line length of definitions ≤ 60ch on desktop; rail collapses on mobile as today.
- Vitest: grouping/alphabetisation from the catalog, search filtering, anchor ids stable (frontend tests in the same PR). jsdom has no IntersectionObserver — keep the existing fallback.
- Parity guard between SPA glossary terms and
specs/product/GLOSSARY.md, with a mutation run showing it goes red when a term is removed from one side. - en / es / tl: group labels and search copy inline; existing term/definition keys untouched.
-
tools/simulation/ui/help specs still pass — read the callers (Daily entry: require grading to reconcile sellable eggs before submit #394).
Activity
mforce commentedon Sep 2, 2026
Shipped in the #650 PR (owner decision 2026-09-02: fold #657 into that branch). What landed, against the proposal above:
<dl>per group, alphabetical in the active language, every entry a stable anchor (/help#glossary-egg-lot); data inweb/src/routes/helpGlossary.ts. 7 groups, not 6: the proposed "Messages you may see" group was folded into the groups its messages belong to (a sign-in message sits under Signing in), and Feed/water/supplies got its own group because six terms needed one.GlossaryLink"?" on four headers to start: History → Status (Locked entry), Sales → Status (Confirm), Stock → Restricted (Withdrawal restriction) and the lot ledger's Type (Egg movement ledger). Status badges themselves did not get one — a link per row on 21 badge sites is noise; the header carries it once.specs/product/GLOSSARY.mdterm it is the subset of, andhelpGlossary.test.tsfails when that term disappears from the spec, when a catalog row has no entry, or when an entry has no row in en/es/tl. Mutation-checked (renamed spec, dropped entry, disabled hiding, unsorted groups, section moved back) — 5/5 red on the named test.Not done: the Stock/Reports column headers beyond the four above, and a GLOSSARY.md ↔ SPA reverse check (the spec glossary is deliberately the superset).
feat(web): give the Help page its own look — head band, glossary grid…
feat(web): typeset numbers as numbers and refresh the Help glossary (#…
test(web): raise the paging suites' per-test budget, not the run's (#750
chore(main): release 0.1.0 (#542)
chore(ci): skip the image and web jobs on documentation-only pull req…
test(web): verify Help renders /login?farm=<code> as text, not an HTM…
test(web): verify Help renders /login?farm=<code> as text, not an HTM…
fix(web): restore the grouped, alphabetised Help glossary (#657) (#924)