Skip to content

SPA: Help page + glossary refresh — grouped, searchable, deep-linkable definitions; guide reordered around the tasks people come for #657

Closed

Description

@mforce

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 .eyebrow caps labels (SPA: retire tracked all-caps labels outside the nav group dividers #652).

Proposal

Glossary

  1. <dl> with a stable id per term (glossary-egg-lot), term in --ink 600, definition ≤ 60ch at 1.6 line-height, a hairline between entries not a table grid. Deep-linkable: /help#glossary-egg-lot.
  2. 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.
  3. Filter-as-you-type box over term + definition (client-side, 51 entries — trivial). aria-live count of matches.
  4. 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; TOC ids in HelpPage.tsx unchanged (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

  1. mforce commented on Sep 2, 2026

    @mforce
    OwnerAuthor

    Shipped in the #650 PR (owner decision 2026-09-02: fold #657 into that branch). What landed, against the proposal above:

    • Glossary → <dl> per group, alphabetical in the active language, every entry a stable anchor (/help#glossary-egg-lot); data in web/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.
    • Search box over guide sections and glossary terms; a live status line ("Matches for “fifo”: 0 in the guide, 2 in the glossary." / "Nothing matches …") and a Clear control.
    • 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.
    • "Fixing mistakes" moved to directly after "The daily loop"; rail grouped (Start here · Every day · Selling · Supplies · Farm & people · The app), same order as the sections, pinned by test.
    • Definitions capped at 60ch; the two caps eyebrows on this page are sentence-case kickers now (SPA: retire tracked all-caps labels outside the nav group dividers #652 does the rest of the app).
    • Parity guard: every entry names the specs/product/GLOSSARY.md term it is the subset of, and helpGlossary.test.ts fails 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.
    • Deep link follows hash changes and router navigations, not only the first load.

    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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions