-
-
Notifications
You must be signed in to change notification settings - Fork 25
ENH: Implement sticky RHS table of contents with scroll highlighting #350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add sticky_contents config option (defaults to False) - Use position: fixed for reliable sticky behavior - Add scrollspy.js module for tracking scroll position - Highlight active section in TOC as user scrolls - Support scrollable TOC for long content lists Fixes #133 Usage: html_theme_options: sticky_contents: true
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #350 +/- ##
=======================================
Coverage ? 45.21%
=======================================
Files ? 2
Lines ? 387
Branches ? 0
=======================================
Hits ? 175
Misses ? 212
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
🎭 Visual Regression Test ResultsDetails
Skipped testsmobile-chrome › theme.spec.ts › Theme Features › f-string interpolation styling |
- Shows floating button at bottom right when page is scrolled down - Only appears when sticky_contents is enabled - Uses modern Sass color.adjust() function - Animated appearance with fade and slide transition - Button hidden until user scrolls past 300px threshold
- Subsections are hidden by default in sticky TOC mode - When a section becomes active, its parent sections expand - When scrolling away, subsections collapse back - Smooth animated transitions for expand/collapse - Only affects sticky mode - non-sticky TOC unchanged
- Subsections now stay expanded while scrolling through content - Parent section stays expanded when any child is active - Also expands parent's children when parent heading is active - Only collapses when scrolling to a different top-level section
- Track which top-level TOC section each item belongs to - When active item changes, keep its entire top-level section expanded - Expand ALL nested items within the active top-level section - Subsections only collapse when scrolling to a different top-level section - Uses :has() selector for finding items with children
- Fix parent traversal to correctly find top-level TOC item - Replace :has() selector with :scope > ul for broader browser support - Ensure all nested items with children get expanded class
- New theme option: contents_autoexpand (default: false)
- When false: TOC shows all sections normally (no collapse/expand)
- When true: Subsections auto-collapse/expand based on scroll position
- Allows sticky TOC to ship while auto-expand is refined
- Uses data-autoexpand attribute to pass config to JavaScript
Usage in _config.yml:
html_theme_options:
sticky_contents: true
contents_autoexpand: true # optional, defaults to false
- Expand all ancestors of the active item (so it's visible in collapsed tree) - Expand the active item itself if it has children (show its subsections) - Removed complex top-level tracking - simpler ancestor traversal - When on 4.2, shows 4.2.1, 4.2.2 etc - When on 4.2.1, keeps 4.2 expanded so 4.2.1 is visible
- Start from parent ul of active item, not the item itself - Walk up ul->li->ul->li chain correctly - Ensures parent sections get expanded class when in subsection
- Theme config values come as strings ('True'/'False') not booleans
- Updated conditionals to check for both boolean and string values
- Fixes autoexpand not being enabled despite default True in theme.conf
- Remove debug console.log statements from scrollspy.js - Add CSS for contents_autoexpand=false mode (hides subsections) - Add documentation for sticky_contents and contents_autoexpand options - Add test_sticky_toc unit test for HTML output verification - Re-enable visual regression tests in CI workflow
- Change overflow-y from 'auto' to 'hidden' for cleaner appearance - Content that exceeds viewport height will be clipped at bottom - Also adds Core Rules section to copilot-instructions.md
|
@jstac @DrDrij I have implemented the This implementation is enabled through an option for the theme. Here is a video of the new implementation which keeps the RHS contents visible while you scroll the page, and continuously provides context as you scroll through sections and subsections in the document. It also has a new demo-stick-contents-autoexpand.movInterested in thoughts / comments / suggestions. |
|
Here is demo of demo-autoexapand-false.mov |
- When contents_autoexpand is false, highlight the top-level parent section instead of the hidden subsection as user scrolls through content - Move back-to-top button outside .inner container to prevent clipping from overflow-y: hidden
Functionality look perfect @mmcky. Nothing to add. Just a thought, since you're introducing anchor points, why not make these accessible for users to share links to specific context..
|
|
Thanks @DrDrij. Nice idea, would you add that to Contents or next to the titles themselves (when reading the doc) do you think? |


Summary
This PR implements a sticky right-hand side table of contents (TOC) that remains fixed while scrolling and highlights the currently active section.
Fixes
Implementation
New Features
sticky_contents: truein_config.ymlTechnical Approach
position: fixedinstead ofposition: stickyfor reliable behavior regardless of parent container positioningrequestAnimationFramefor throttled scroll handling (smooth performance)scrollspy.jsmoduleFiles Changed
src/quantecon_book_theme/assets/scripts/scrollspy.js(NEW) - Scroll spy functionalitysrc/quantecon_book_theme/assets/scripts/index.js- Import and initialize scrollspysrc/quantecon_book_theme/assets/styles/_page.scss- Sticky positioning and active highlight stylessrc/quantecon_book_theme/theme/quantecon_book_theme/layout.html- Conditional sticky classsrc/quantecon_book_theme/theme/quantecon_book_theme/theme.conf- Newsticky_contentsoptionUsage
Add to your Jupyter Book
_config.yml:Testing
sticky_contents: truein lecture-python-programming.myst