Skip to content

Conversation

@vivekvernekar26
Copy link

  • 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

- 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
@vercel
Copy link

vercel bot commented Oct 26, 2025

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

@vercel
Copy link

vercel bot commented Oct 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
learn-javascript Error Error Nov 22, 2025 1:00pm

Copy link
Contributor

Copilot AI left a 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.

Comment on lines +1 to +55
// 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
});
});
Copy link

Copilot AI Nov 22, 2025

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.

Suggested change
// 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 uses AI. Check for mistakes.

// Handle keyboard navigation
$tocHeader.on('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
Copy link

Copilot AI Nov 22, 2025

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) {
Suggested change
if (e.key === 'Enter' || e.key === ' ') {
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32) {

Copilot uses AI. Check for mistakes.

// Save state to localStorage
var collapsed = $tocNav.hasClass('toc-collapsed');
localStorage.setItem('intopic-toc-collapsed', collapsed);
Copy link

Copilot AI Nov 22, 2025

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);
});
Suggested change
localStorage.setItem('intopic-toc-collapsed', collapsed);
localStorage.setItem('intopic-toc-collapsed', collapsed);
// Update aria-expanded for accessibility
$(this).attr('aria-expanded', !collapsed);

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +32
2. **`node_modules/gitbook-plugin-toc-accordion`** - Symlink to local plugin

Copy link

Copilot AI Nov 22, 2025

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
$tocHeader.data('accordion-initialized', true);

// Load saved state from localStorage (default: open)
var isCollapsed = localStorage.getItem('intopic-toc-collapsed') === 'true';
Copy link

Copilot AI Nov 22, 2025

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.

Copilot uses AI. Check for mistakes.
position: relative;
transition: color 0.3s ease;
}

Copy link

Copilot AI Nov 22, 2025

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.

Suggested change
nav.intopic-toc h3:focus {
outline: 2px solid #4A90E2;
outline-offset: 2px;
}

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +41
/* 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;
}
Copy link

Copilot AI Nov 22, 2025

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.

Suggested change
/* 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 uses AI. Check for mistakes.
Comment on lines +39 to +40
transition: all 0.3s ease;
overflow: hidden;
Copy link

Copilot AI Nov 22, 2025

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.

Suggested change
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 */

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +39
display: none;
}

/* Smooth transition for content */
nav.intopic-toc .navbar-nav {
transition: all 0.3s ease;
Copy link

Copilot AI Nov 22, 2025

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;
}
Suggested change
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;

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +9
{
"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"
}
}
Copy link

Copilot AI Nov 22, 2025

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.

Copilot uses AI. Check for mistakes.
@sumn2u
Copy link
Owner

sumn2u commented Nov 22, 2025

@vivekvernekar26 Thanks for the PR, it seems the addition of the toc-accordion is causing problem in the build? Can you have a look into it when you have time?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants