DataTalksClub / DataTalksClub/website

Prevent nested links in documentation curriculum cards

Open
#263 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accessibility bug content frontend P1 testing
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Parent accessibility baseline: #65

Product outcome

Curriculum cards render valid, unambiguous native-link semantics while preserving every source-authored destination. A linked curriculum item whose details contain another link becomes one visually unchanged neutral card with separate, clearly named link targets: the item title opens the item destination and each details link keeps its own destination. Items with only one destination retain the accepted whole-card interaction; items without a destination remain static.

This is a bounded accessibility and HTML-validity correction to the documentation presentation introduced by face8e4808d65afbf0374d1ced7a88079950d663. It does not alter curriculum data or redesign the documentation system.

Normative authority

Confirmed current regression

At current main/face8e4, content.docs_presentation.docs_curriculum() extracts the title destination from source-rendered Markdown, while templates/review/docs_detail.html wraps both the title and details_html in that destination anchor. Exactly two current projected items therefore contain an anchor in an anchor:

Public page Item-title destination Details destination
/docs/courses/data-engineering-zoomcamp/curriculum/Final Project https://github.com/DataTalksClub/data-engineering-zoomcamp/tree/main/projects /docs/courses/data-engineering-zoomcamp/project/Project page
/docs/courses/llm-zoomcamp/curriculum/Capstone Project https://github.com/DataTalksClub/llm-zoomcamp/blob/main/project.md /docs/courses/llm-zoomcamp/project/Project page

The source data and both destinations are correct. The presentation composition is the defect.

Scope and interaction contract

Structural classification
  • Derive whether a curriculum item's already-sanitized rendered details contain one or more anchors as a presentation property. The rule is structural and generic: do not match course slug, item title, link label, or URL.
  • When an item has a title destination and no details links, preserve the accepted whole-card native anchor, accessible name, pointer target, focus treatment, reduced-motion behavior, and destination.
  • When an item has no title destination, preserve the accepted static card.
  • When an item has both a title destination and one or more details links, render a neutral card container, not an anchor and not an element with role="link" or tabindex. Render the visible item title as the native primary anchor to the title destination, and render the source-authored details HTML normally so its native anchors remain siblings/descendants of the neutral container rather than descendants of another anchor.
Names, destinations, and activation
  • The primary anchors have concise names from the source item titles: Final Project and Capstone Project. The local details anchors retain the visible name Project page. No link's accessible name may absorb the other link's description or destination.
  • Keyboard order within each split card is primary title link first, followed by details links in source order. Each is reached once with Tab, activated with Enter, and receives the shared visible, unobscured focus treatment. There is no duplicate tab stop, keyboard trap, scripted click forwarding, or card-level pseudo-link.
  • Pointer activation of the primary title link resolves to the exact external repository destination. Pointer activation of Project page resolves to the exact local documentation destination. Clicking non-link card background does nothing; no overlay or stretched-link hit area may cover or steal a details link.
  • Actual interactive targets retain the applicable shared target-size/spacing, contrast, forced-colors, and reduced-motion behavior. A neutral card must not present hover/focus animation that falsely promises whole-card activation.
Visual and content continuity
  • Preserve the existing content-page shell, docs header/local navigation, curriculum ordering, marker, card border/background/radius/spacing, typography, responsive layout, light/dark themes, and all source-authored copy.
  • Preserve all current item counts and ordering on every projected curriculum page. Preserve exact docs routes, headings/anchors, canonical metadata, source projection, source-authored URLs, sanitization, and fallback-to-complete-prose behavior.
  • The split-link treatment must work for a generic future curriculum item with any title destination and one or more safe details anchors; it is not limited to the two current Project page cases.

Acceptance criteria

  • Parsing the server response and inspecting the repaired browser DOM find zero nested anchors and zero interactive descendants inside a whole-card anchor on every current projected curriculum page.
  • The Data Engineering Final Project card exposes exactly one primary Final Project link to https://github.com/DataTalksClub/data-engineering-zoomcamp/tree/main/projects and one Project page link to /docs/courses/data-engineering-zoomcamp/project/; both are contained by one neutral visual card and neither contains the other.
  • The LLM Capstone Project card exposes exactly one primary Capstone Project link to https://github.com/DataTalksClub/llm-zoomcamp/blob/main/project.md and one Project page link to /docs/courses/llm-zoomcamp/project/; both are contained by one neutral visual card and neither contains the other.
  • A generic presentation unit test proves the split-card branch for a linked item with one or multiple details anchors without relying on course/title/link-label/URL text. It also proves the existing whole-card branch for a title-only destination and static branch for no title destination.
  • Keyboard and pointer browser checks prove link order, unique tab stops, exact names/destinations, Enter activation, visible focus, non-link background behavior, and non-overlapping hit targets for both affected pages. The tests perform no live request to an external repository.
  • Desktop 1440×900 and mobile 390×844 renderings of both affected pages have no document-level horizontal overflow, lost/truncated content, covered link, or broken card geometry. The split controls remain usable at 200% zoom/320 CSS-pixel reflow, with reduced motion and forced colors.
  • The focused WCAG A/AA scan and explicit semantics checks pass for both affected pages. Existing docs hierarchy, source anchors, canonical/alias behavior, JavaScript-off read access, other curriculum cards, non-curriculum prose, and light/dark behavior do not regress.
  • The independently recomputed versioned verification plan has no required skip. Focused Django/presentation tests, applicable docs/accessibility Playwright checks, make test-playwright (template-change backstop), full Django/compatibility checks, lint/format/type/migration/portability/terminology checks, and git diff --check pass through uv-backed commands.
  • An independent tester captures and opens original screenshots below .tmp/screenshots/issue-263/: both affected routes at desktop and mobile, plus representative visible keyboard focus on the primary and Project page links and representative dark-theme evidence. Every image shows the expected page, correct destinations/controls, readable layout, and no error/debug/private data.

Required verification scenarios

  1. Render the current Data Engineering and LLM curriculum pages. Inspect server HTML and repaired DOM structure, accessible link names, exact hrefs, focus order, focus indication, pointer hit testing, local Project page navigation, non-link card background, viewport overflow, reduced motion, forced colors, and axe results.
  2. Render representative unaffected cases: a linked ML curriculum module with no details link remains one whole-card destination, an existing static curriculum item remains non-interactive, and a non-curriculum docs page remains ordinary prose.
  3. Exercise a synthetic generic item whose title has one destination and whose details contain multiple anchors. It splits into one neutral container and independent native links in source order, with no string/path special case and no dropped/sanitization-bypassing content.
  4. At desktop/mobile and 200%/320px, inspect both affected pages in the accepted shell and at least one dark-theme state. Verify card geometry/copy remains coherent and actual controls, not the neutral background, carry hover/focus affordance.

Non-goals

  • No rewrite of curriculum facts, titles, descriptions, module ordering, source projection JSON, or source-authored URLs.
  • No removal, redirection, relabelling, or replacement of either repository or local project-documentation destination.
  • No redesign of documentation navigation, typography, page shells, card tokens, unrelated curriculum/prose pages, or global interaction primitives.
  • No JavaScript card emulation, click forwarding, overlay/stretched anchor across sibling controls, ARIA role substitution for native anchors, or external network dependency in tests.
  • No course-management, cohort, registration, learner, Studio, admin API, content-import, SEO-route, or deployment behavior change.
  • No claim to complete #65's outstanding real screen-reader/HUMAN matrix or WCAG conformance.

Dependencies and sequencing

There is no product or architecture dependency. Start from then-current clean main. #261 owns the current P0 exact-main quality-gate recovery but supplies no interface required here and has no allowed-file overlap with this bounded fix; coordinate sequencing so #263's final verification is run on a green then-current base. If another docs/template change lands first, rebase and recompute the plan before tester handoff.

Delivery

Status after grooming: GROOMED / engineer-ready P1. Follow the full issue lifecycle: engineer implements and freezes an uncommitted candidate; an independent tester recomputes the plan, runs the selected gates, and inspects screenshots; PM accepts the exact candidate; only then may the engineer commit with Closes #263, followed by local no-ff merge/push and on-call observation. No pull request.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with content.docs_presentation.docs_curriculum() and templates/review/docs_detail.html, then read _docs/PROCESS.md and the linked accessibility and verification specifications. Add focused Django/presentation coverage for split, whole-card, and static cases, followed by Playwright checks on the two named curriculum routes. Done means no nested anchors, exact independent destinations and names, preserved unaffected cards, and passing responsive/accessibility verification.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, playwright, python
Domain
accessibility, documentation, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.