-
Notifications
You must be signed in to change notification settings - Fork 183
feat: Add accordion functionality to 'In This Chapter' section #359
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
- Implemented custom gitbook-plugin-toc-accordion plugin - Added toggle functionality to show/hide TOC content - Accordion is open by default for better UX - Added visual arrow indicator that rotates on toggle - Persistent state using localStorage - Keyboard accessible (Enter/Space keys) - Smooth CSS transitions and hover effects - ARIA attributes for screen reader support Fixes issue: No option to hide 'In This Chapter' section Improves UX on pages with extensive content
|
@vivekvernekar26 is attempting to deploy a commit to the Suman Kunwar's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements accordion functionality for the "In This Chapter" section in a GitBook/HonKit documentation site. The feature allows users to collapse/expand the table of contents, with state persistence via localStorage, keyboard accessibility, and visual feedback through CSS animations.
Key Changes:
- Created a custom local GitBook plugin (
gitbook-plugin-toc-accordion) with accordion functionality - Added keyboard navigation support (Enter/Space keys) and ARIA attributes for accessibility
- Implemented persistent state management using localStorage with accordion open by default
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
gitbook-plugin-toc-accordion/package.json |
Plugin metadata defining the package name, version, and GitBook engine compatibility |
gitbook-plugin-toc-accordion/index.js |
Plugin entry point that registers CSS and JS assets |
gitbook-plugin-toc-accordion/assets/accordion.js |
JavaScript implementation for toggle functionality, keyboard handling, and localStorage persistence |
gitbook-plugin-toc-accordion/assets/accordion.css |
CSS styles for arrow indicator, hover effects, and collapse transitions |
gitbook-plugin-toc-accordion/README.md |
Plugin documentation covering features, installation, and usage |
book.json |
Added toc-accordion plugin to plugins list and configured custom website styles |
styles/website.css |
Duplicate of plugin CSS (should be removed to avoid redundancy) |
assets/accordion.js |
Duplicate of plugin JavaScript (should be removed to avoid double initialization) |
ACCORDION_FEATURE.md |
Comprehensive documentation of the feature implementation and testing instructions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Accordion functionality for "In This Chapter" section | ||
| require(['gitbook', 'jQuery'], function(gitbook, $) { | ||
| gitbook.events.bind('page.change', function() { | ||
| // Wait for the intopic-toc to be rendered | ||
| setTimeout(function() { | ||
| var $tocNav = $('nav.intopic-toc'); | ||
| var $tocHeader = $tocNav.find('h3'); | ||
|
|
||
| if ($tocHeader.length === 0) return; | ||
|
|
||
| // Check if accordion is already initialized | ||
| if ($tocHeader.data('accordion-initialized')) return; | ||
|
|
||
| // Mark as initialized | ||
| $tocHeader.data('accordion-initialized', true); | ||
|
|
||
| // Load saved state from localStorage (default: open) | ||
| var isCollapsed = localStorage.getItem('intopic-toc-collapsed') === 'true'; | ||
|
|
||
| if (isCollapsed) { | ||
| $tocNav.addClass('toc-collapsed'); | ||
| } | ||
|
|
||
| // Add click handler to toggle accordion | ||
| $tocHeader.on('click', function(e) { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
|
|
||
| $tocNav.toggleClass('toc-collapsed'); | ||
|
|
||
| // Save state to localStorage | ||
| var collapsed = $tocNav.hasClass('toc-collapsed'); | ||
| localStorage.setItem('intopic-toc-collapsed', collapsed); | ||
| }); | ||
|
|
||
| // Make header keyboard accessible | ||
| $tocHeader.attr('tabindex', '0'); | ||
| $tocHeader.attr('role', 'button'); | ||
| $tocHeader.attr('aria-expanded', !isCollapsed); | ||
| $tocHeader.attr('aria-label', 'Toggle table of contents'); | ||
|
|
||
| // Handle keyboard navigation | ||
| $tocHeader.on('keydown', function(e) { | ||
| if (e.key === 'Enter' || e.key === ' ') { | ||
| e.preventDefault(); | ||
| $(this).click(); | ||
|
|
||
| // Update aria-expanded | ||
| var expanded = !$tocNav.hasClass('toc-collapsed'); | ||
| $(this).attr('aria-expanded', expanded); | ||
| } | ||
| }); | ||
| }, 500); // Wait for plugin to render | ||
| }); | ||
| }); |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This JavaScript file is an exact duplicate of gitbook-plugin-toc-accordion/assets/accordion.js. The plugin already provides this script through its index.js configuration, so this duplicate will cause the accordion initialization logic to run twice.
Recommendation: Remove this file entirely and rely on the plugin's JavaScript. The duplicate initialization could lead to unexpected behavior and double event handlers being attached.
| // Accordion functionality for "In This Chapter" section | |
| require(['gitbook', 'jQuery'], function(gitbook, $) { | |
| gitbook.events.bind('page.change', function() { | |
| // Wait for the intopic-toc to be rendered | |
| setTimeout(function() { | |
| var $tocNav = $('nav.intopic-toc'); | |
| var $tocHeader = $tocNav.find('h3'); | |
| if ($tocHeader.length === 0) return; | |
| // Check if accordion is already initialized | |
| if ($tocHeader.data('accordion-initialized')) return; | |
| // Mark as initialized | |
| $tocHeader.data('accordion-initialized', true); | |
| // Load saved state from localStorage (default: open) | |
| var isCollapsed = localStorage.getItem('intopic-toc-collapsed') === 'true'; | |
| if (isCollapsed) { | |
| $tocNav.addClass('toc-collapsed'); | |
| } | |
| // Add click handler to toggle accordion | |
| $tocHeader.on('click', function(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| $tocNav.toggleClass('toc-collapsed'); | |
| // Save state to localStorage | |
| var collapsed = $tocNav.hasClass('toc-collapsed'); | |
| localStorage.setItem('intopic-toc-collapsed', collapsed); | |
| }); | |
| // Make header keyboard accessible | |
| $tocHeader.attr('tabindex', '0'); | |
| $tocHeader.attr('role', 'button'); | |
| $tocHeader.attr('aria-expanded', !isCollapsed); | |
| $tocHeader.attr('aria-label', 'Toggle table of contents'); | |
| // Handle keyboard navigation | |
| $tocHeader.on('keydown', function(e) { | |
| if (e.key === 'Enter' || e.key === ' ') { | |
| e.preventDefault(); | |
| $(this).click(); | |
| // Update aria-expanded | |
| var expanded = !$tocNav.hasClass('toc-collapsed'); | |
| $(this).attr('aria-expanded', expanded); | |
| } | |
| }); | |
| }, 500); // Wait for plugin to render | |
| }); | |
| }); |
|
|
||
| // Handle keyboard navigation | ||
| $tocHeader.on('keydown', function(e) { | ||
| if (e.key === 'Enter' || e.key === ' ') { |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The keyboard event handler uses the .key property which is not supported in older browsers. For better compatibility, especially with Internet Explorer, you should also check for e.keyCode or use a more compatible approach.
Recommendation:
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32) {| if (e.key === 'Enter' || e.key === ' ') { | |
| if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32) { |
|
|
||
| // Save state to localStorage | ||
| var collapsed = $tocNav.hasClass('toc-collapsed'); | ||
| localStorage.setItem('intopic-toc-collapsed', collapsed); |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aria-expanded attribute is only set during initialization but not updated when the user clicks the heading (only updated on keyboard interaction). This creates an inconsistency for screen reader users.
Recommendation: Update the aria-expanded attribute in the click handler as well:
$tocHeader.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
$tocNav.toggleClass('toc-collapsed');
// Save state to localStorage
var collapsed = $tocNav.hasClass('toc-collapsed');
localStorage.setItem('intopic-toc-collapsed', collapsed);
// Update aria-expanded for accessibility
$(this).attr('aria-expanded', !collapsed);
});| localStorage.setItem('intopic-toc-collapsed', collapsed); | |
| localStorage.setItem('intopic-toc-collapsed', collapsed); | |
| // Update aria-expanded for accessibility | |
| $(this).attr('aria-expanded', !collapsed); |
| 2. **`node_modules/gitbook-plugin-toc-accordion`** - Symlink to local plugin | ||
|
|
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation mentions node_modules/gitbook-plugin-toc-accordion as a modified file, but this directory is typically git-ignored and should not be part of the repository. The symlink setup (if needed) should be documented in the installation/setup instructions instead.
Recommendation: Remove this entry from the "Files Modified" section or clarify that this is a setup step, not a file modification tracked in git.
| 2. **`node_modules/gitbook-plugin-toc-accordion`** - Symlink to local plugin | |
| ## Setup | |
| To use the local `gitbook-plugin-toc-accordion` plugin during development, create a symlink in `node_modules`: | |
| ```sh | |
| ln -s ../gitbook-plugin-toc-accordion node_modules/gitbook-plugin-toc-accordion |
This step ensures HonKit loads the local plugin code. Do not commit node_modules or the symlink to version control.
| $tocHeader.data('accordion-initialized', true); | ||
|
|
||
| // Load saved state from localStorage (default: open) | ||
| var isCollapsed = localStorage.getItem('intopic-toc-collapsed') === 'true'; |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code doesn't handle the case where localStorage is unavailable (e.g., in private browsing mode or when disabled). This will throw an error and break the accordion functionality.
Recommendation: Add a try-catch block or check for localStorage availability:
// Load saved state from localStorage (default: open)
var isCollapsed = false;
try {
isCollapsed = localStorage.getItem('intopic-toc-collapsed') === 'true';
} catch (e) {
// localStorage not available, use default
}Similarly, wrap the localStorage.setItem call on line 33 in a try-catch.
| position: relative; | ||
| transition: color 0.3s ease; | ||
| } | ||
|
|
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The heading lacks a visible focus indicator for keyboard navigation, which is important for accessibility. Users navigating with keyboard won't have clear visual feedback when the heading is focused.
Recommendation: Add a focus style:
nav.intopic-toc h3:focus {
outline: 2px solid #4A90E2;
outline-offset: 2px;
}Or use your project's standard focus styling.
| nav.intopic-toc h3:focus { | |
| outline: 2px solid #4A90E2; | |
| outline-offset: 2px; | |
| } |
| /* Accordion functionality for "In This Chapter" section */ | ||
| nav.intopic-toc h3 { | ||
| cursor: pointer; | ||
| user-select: none; | ||
| position: relative; | ||
| transition: color 0.3s ease; | ||
| } | ||
|
|
||
| nav.intopic-toc h3:hover { | ||
| color: #6c767f; | ||
| } | ||
|
|
||
| /* Add arrow indicator */ | ||
| nav.intopic-toc h3::after { | ||
| content: ""; | ||
| display: inline-block; | ||
| width: 0; | ||
| height: 0; | ||
| margin-left: 8px; | ||
| vertical-align: middle; | ||
| border-left: 5px solid transparent; | ||
| border-right: 5px solid transparent; | ||
| border-top: 5px solid #9DAAB6; | ||
| transition: transform 0.3s ease; | ||
| } | ||
|
|
||
| /* Rotate arrow when collapsed */ | ||
| nav.intopic-toc.toc-collapsed h3::after { | ||
| transform: rotate(-90deg); | ||
| } | ||
|
|
||
| /* Hide content when collapsed */ | ||
| nav.intopic-toc.toc-collapsed .navbar-nav { | ||
| display: none; | ||
| } | ||
|
|
||
| /* Smooth transition for content */ | ||
| nav.intopic-toc .navbar-nav { | ||
| transition: all 0.3s ease; | ||
| overflow: hidden; | ||
| } |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This CSS file is an exact duplicate of gitbook-plugin-toc-accordion/assets/accordion.css. Since the plugin already provides the CSS through its index.js configuration, this file creates redundancy and could lead to maintainability issues.
Recommendation: Remove this file and rely solely on the plugin's CSS, or remove the CSS from the plugin if you prefer to manage all styles globally in styles/website.css.
| /* Accordion functionality for "In This Chapter" section */ | |
| nav.intopic-toc h3 { | |
| cursor: pointer; | |
| user-select: none; | |
| position: relative; | |
| transition: color 0.3s ease; | |
| } | |
| nav.intopic-toc h3:hover { | |
| color: #6c767f; | |
| } | |
| /* Add arrow indicator */ | |
| nav.intopic-toc h3::after { | |
| content: ""; | |
| display: inline-block; | |
| width: 0; | |
| height: 0; | |
| margin-left: 8px; | |
| vertical-align: middle; | |
| border-left: 5px solid transparent; | |
| border-right: 5px solid transparent; | |
| border-top: 5px solid #9DAAB6; | |
| transition: transform 0.3s ease; | |
| } | |
| /* Rotate arrow when collapsed */ | |
| nav.intopic-toc.toc-collapsed h3::after { | |
| transform: rotate(-90deg); | |
| } | |
| /* Hide content when collapsed */ | |
| nav.intopic-toc.toc-collapsed .navbar-nav { | |
| display: none; | |
| } | |
| /* Smooth transition for content */ | |
| nav.intopic-toc .navbar-nav { | |
| transition: all 0.3s ease; | |
| overflow: hidden; | |
| } |
| transition: all 0.3s ease; | ||
| overflow: hidden; |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using transition: all can cause performance issues as it transitions every property, including properties that don't need animation. This can trigger unnecessary repaints and reflows.
Recommendation: Be specific about which properties to transition:
nav.intopic-toc .navbar-nav {
transition: opacity 0.3s ease, max-height 0.3s ease;
overflow: hidden;
}Note: You may also need to add max-height with a reasonable value for the transition to work properly with display: none.
| transition: all 0.3s ease; | |
| overflow: hidden; | |
| transition: opacity 0.3s ease, max-height 0.3s ease; | |
| overflow: hidden; | |
| max-height: 1000px; /* Adjust as needed for your content */ |
| display: none; | ||
| } | ||
|
|
||
| /* Smooth transition for content */ | ||
| nav.intopic-toc .navbar-nav { | ||
| transition: all 0.3s ease; |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using display: none prevents CSS transitions from working. The element immediately disappears without any smooth animation. Combined with the transition: all 0.3s ease on .navbar-nav, this creates an inconsistent user experience where the collapse has no visual transition.
Recommendation: Use max-height, opacity, or transform with overflow: hidden for smooth animations:
/* Hide content when collapsed */
nav.intopic-toc.toc-collapsed .navbar-nav {
max-height: 0;
opacity: 0;
pointer-events: none;
}
/* Smooth transition for content */
nav.intopic-toc .navbar-nav {
max-height: 1000px; /* Adjust based on your content */
opacity: 1;
transition: max-height 0.3s ease, opacity 0.3s ease;
overflow: hidden;
}| display: none; | |
| } | |
| /* Smooth transition for content */ | |
| nav.intopic-toc .navbar-nav { | |
| transition: all 0.3s ease; | |
| max-height: 0; | |
| opacity: 0; | |
| pointer-events: none; | |
| } | |
| /* Smooth transition for content */ | |
| nav.intopic-toc .navbar-nav { | |
| max-height: 1000px; /* Adjust based on your content */ | |
| opacity: 1; | |
| transition: max-height 0.3s ease, opacity 0.3s ease; |
| { | ||
| "name": "gitbook-plugin-toc-accordion", | ||
| "version": "1.0.0", | ||
| "description": "Adds accordion functionality to In This Chapter section", | ||
| "main": "index.js", | ||
| "engines": { | ||
| "gitbook": ">=3.0.0" | ||
| } | ||
| } |
Copilot
AI
Nov 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The package.json is missing several important fields for a proper npm package. Consider adding:
"author": Package author information"license": License type (e.g., "MIT", "ISC")"repository": Link to the source code repository"keywords": For better discoverability if published
While this works for a local plugin, adding these fields follows npm best practices and makes the plugin more complete.
|
@vivekvernekar26 Thanks for the PR, it seems the addition of the |
Fixes issue: No option to hide 'In This Chapter' section Improves UX on pages with extensive content