Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions pytorch_sphinx_theme2/static/js/collapsible-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Collapsible "Subclassed by" list behavior.
* Finds paragraphs starting with "Subclassed by" that have more than 5 items,
* collapses them to a single line, and adds a "See All" / "Hide" toggle button.
*
* Breathe/Doxygen renders "Subclassed by" in a <p> tag. The subclass names may
* be <a> links (when targets exist) or plain text (when they don't). We count
* both to determine whether to collapse.
*/
document.addEventListener('DOMContentLoaded', function() {
var paragraphs = document.querySelectorAll('p');

paragraphs.forEach(function(p) {
var text = p.textContent.trim();
if (!text.startsWith('Subclassed by')) return;

// Count items: use <a> links if present, otherwise count comma-separated entries
var links = p.querySelectorAll('a');
var itemCount = links.length;
if (itemCount <= 5) {
// Links may not exist (plain text subclass names). Count comma-separated items.
var afterLabel = text.replace(/^Subclassed by\s*/, '');
var commaCount = afterLabel.split(',').filter(function(s) { return s.trim().length > 0; }).length;
if (commaCount > itemCount) {
itemCount = commaCount;
}
}

if (itemCount > 5) {
p.classList.add('subclassed-by-list', 'collapsed');

var toggle = document.createElement('button');
toggle.className = 'subclassed-by-toggle';
toggle.textContent = 'See All (' + itemCount + ')';
toggle.type = 'button';

toggle.addEventListener('click', function(e) {
e.preventDefault();

if (p.classList.contains('collapsed')) {
p.classList.remove('collapsed');
p.classList.add('expanded');
toggle.textContent = 'Hide';
} else {
p.classList.remove('expanded');
p.classList.add('collapsed');
toggle.textContent = 'See All (' + itemCount + ')';
}
});

p.appendChild(toggle);
}
});
});
60 changes: 60 additions & 0 deletions pytorch_sphinx_theme2/static/scss/_collapsible_list.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Collapsible "Subclassed by" list styles.
* When a paragraph has more than 5 links, it collapses to a single line
* with a "See All" button to expand the full list.
* Main use case is C++ docs
*/

/* Container for the subclassed-by list */
.subclassed-by-list {
position: relative;

/* Initially collapsed state - show only 1 line */
&.collapsed {
max-height: 1.6em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding-right: 140px; /* Space for the button */
}

/* Expanded state */
&.expanded {
max-height: none;
overflow: visible;
white-space: normal;
padding-right: 0;
padding-bottom: 2em; /* Space for the button at the bottom */

.subclassed-by-toggle {
position: absolute;
top: auto;
bottom: 0;
right: 0;
}
}
}

/* The "See All" / "Hide" toggle button */
.subclassed-by-toggle {
position: absolute;
top: 0;
right: 0;
background-color: #f0f0f0;
border: 1px solid #ccc;
border-radius: 4px;
padding: 2px 10px;
color: #333;
cursor: pointer;
font-size: 0.85em;
text-decoration: none;
font-family: inherit;
font-weight: 500;
transition: background-color 0.2s, border-color 0.2s;

&:hover {
background-color: #e0e0e0;
border-color: #999;
text-decoration: none;
}
}
1 change: 1 addition & 0 deletions pytorch_sphinx_theme2/static/scss/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@use 'search';
@use 'tippy';
@use 'navbar_dropdown';
@use 'collapsible_list';

// Import FontAwesome
@use "@fortawesome/fontawesome-free/scss/fontawesome";
Expand Down
15 changes: 14 additions & 1 deletion pytorch_sphinx_theme2/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,24 @@
link.parentElement.classList.remove('active');
});

// Add active class to the matching link
// Add active class to the matching link and all its ancestor TOC items
const matchingLink = tocNav.querySelector(`a[href="#${CSS.escape(targetId)}"]`);
if (matchingLink) {
matchingLink.classList.add('active');
matchingLink.parentElement.classList.add('active');

// Walk up the DOM to activate parent TOC entries (e.g. h2 parent of h3)
let ancestor = matchingLink.parentElement.parentElement;
while (ancestor && ancestor !== tocNav) {
if (ancestor.classList.contains('toc-entry')) {
ancestor.classList.add('active');
const parentLink = ancestor.querySelector(':scope > a.nav-link');
if (parentLink) {
parentLink.classList.add('active');
}
}
ancestor = ancestor.parentElement;
}
}

// Use setTimeout to reset the guard after the current call stack
Expand Down
Loading