Create new sticky toc container

Bug: T313060
Change-Id: Ia263c606dce5a6060b6b29fbaedc49cef3e17a5c
This commit is contained in:
bwang 2022-08-24 13:53:37 -05:00 committed by Jdlrobson
parent 990c7f72b9
commit 9c6f6709c6
5 changed files with 57 additions and 15 deletions

View file

@ -1,3 +1,6 @@
<div class="mw-table-of-contents-container mw-sticky-header-element">
{{#data-toc}}{{>TableOfContents}}{{/data-toc}}
<div class="mw-table-of-contents-container">
{{! T313060 Additional container div needed to prevent the sticky element from being siblings with the footer }}
<div class="vector-sticky-toc-container mw-sticky-header-element">
{{#data-toc}}{{>TableOfContents}}{{/data-toc}}
</div>
</div>

View file

@ -60,8 +60,11 @@ function moveToc( position ) {
return;
}
// FIXME: Remove after Ia263c606dce5a6060b6b29fbaedc49cef3e17a5c has been in prod for 5 days
const isCachedHtml = document.querySelector( '.mw-table-of-contents-container.mw-sticky-header-element' );
let newTocContainer;
const sidebarTocContainerClass = 'mw-table-of-contents-container';
const sidebarTocContainerClass = isCachedHtml ? 'mw-table-of-contents-container' : 'vector-sticky-toc-container';
const stickyHeaderTocContainerClass = 'vector-menu-content';
// Avoid moving TOC if unnecessary
if ( !currTocContainer.classList.contains( sidebarTocContainerClass ) && position === 'sidebar' ) {
@ -69,6 +72,7 @@ function moveToc( position ) {
} else if ( !currTocContainer.classList.contains( stickyHeaderTocContainerClass ) && position === 'stickyheader' ) {
newTocContainer = document.querySelector( `.vector-sticky-header-toc .${stickyHeaderTocContainerClass}` );
}
if ( newTocContainer ) {
newTocContainer.insertAdjacentElement( 'beforeend', toc );
}

View file

@ -10,11 +10,19 @@
@toc-subsection-toggle-icon-size: 1.834em;
.mw-table-of-contents-container {
// Needed for Grid-based layout
align-self: start;
height: 100%;
}
// FIXME: Remove selector after Ia263c606dce5a6060b6b29fbaedc49cef3e17a5c has been in prod for 5 days
.mw-table-of-contents-container.mw-sticky-header-element {
// stylelint-disable-next-line plugin/no-unsupported-browser-features
position: sticky;
top: 0;
// Needed for Grid-based layout
align-self: start;
height: unset;
// Needed to align TOC with bottom of title
// 1.5em from .mw-table-of-contents-container + 1.5em from .sidebar-toc = 3em
@ -25,10 +33,32 @@
}
}
.vector-sticky-toc-container {
// stylelint-disable-next-line plugin/no-unsupported-browser-features
position: sticky;
top: 0;
@media ( min-width: @min-width-desktop ) {
.vector-toc-not-collapsed & {
// Default spacing separating the sidebar TOC from the main menu or viewport.
// Need to use padding in order for the spacing to apply when sticky
padding-top: 1.5em;
}
.vector-toc-not-collapsed @{selector-main-menu-closed} ~ .mw-table-of-contents-container & {
// Needed to align TOC with bottom of title, 1.5em padding + 1.5em margin = 3em
margin-top: 1.5em;
}
}
}
// FIXME: Remove selector after Ia263c606dce5a6060b6b29fbaedc49cef3e17a5c has been in prod for 5 days
.mw-table-of-contents-container > .sidebar-toc {
margin-top: 1.5em;
}
.sidebar-toc {
max-height: 75vh;
// Default spacing separating the sidebar TOC from the main menu or viewport.
margin-top: 1.5em;
padding: @sidebar-toc-vertical-padding @sidebar-toc-right-padding @sidebar-toc-vertical-padding @sidebar-toc-left-padding;
box-sizing: border-box;
overflow: auto;

View file

@ -64,7 +64,9 @@
display: block;
}
.mw-table-of-contents-container {
// FIXME: Remove this selector after Ia263c606dce5a6060b6b29fbaedc49cef3e17a5c has been in prod for 5 days
.mw-table-of-contents-container.mw-sticky-header-element,
.vector-sticky-toc-container {
position: relative;
}

View file

@ -1,5 +1,6 @@
const mustache = require( 'mustache' );
const fs = require( 'fs' );
const tocContainerTemplate = fs.readFileSync( 'includes/templates/TableOfContentsContainer.mustache', 'utf8' );
const stickyHeaderTemplate = fs.readFileSync( 'includes/templates/StickyHeader.mustache', 'utf8' );
const buttonTemplate = fs.readFileSync( 'includes/templates/Button.mustache', 'utf8' );
const menuTemplate = fs.readFileSync( 'includes/templates/Menu.mustache', 'utf8' );
@ -116,17 +117,19 @@ describe( 'sticky header', () => {
} );
describe( 'moveToc', () => {
const sidebarTocContainerClass = 'mw-table-of-contents-container';
const stickyHeaderTocContainerClass = 'vector-menu-content';
const sidebarTocContainerClass = 'vector-sticky-toc-container';
const stickyTocContainerClass = 'vector-menu-content';
const tocId = 'mw-panel-toc';
function setupToc() {
const sidebarTocContainer = document.createElement( 'div' );
sidebarTocContainer.classList.add( sidebarTocContainerClass );
const toc = document.createElement( 'div' );
toc.setAttribute( 'id', tocId );
sidebarTocContainer.appendChild( toc );
document.body.appendChild( sidebarTocContainer );
const sidebarTocContainerHTML = mustache.render( tocContainerTemplate, {
'data-toc': [ '' ]
}, {
TableOfContents: '<div id="mw-panel-toc" class="sidebar-toc"></div>'
} );
var sidebarTocContainerTemplate = document.createElement( 'template' );
sidebarTocContainerTemplate.innerHTML = sidebarTocContainerHTML;
document.body.appendChild( sidebarTocContainerTemplate.content );
}
test( 'moves toc to stickyheader and sidebar', () => {
@ -136,7 +139,7 @@ describe( 'sticky header', () => {
( toc.parentNode ).classList.contains( sidebarTocContainerClass ) ).toBeTruthy();
sticky.moveToc( 'stickyheader' );
expect( /** @type {Element} */
( toc.parentNode ).classList.contains( stickyHeaderTocContainerClass ) ).toBeTruthy();
( toc.parentNode ).classList.contains( stickyTocContainerClass ) ).toBeTruthy();
sticky.moveToc( 'sidebar' );
expect( /** @type {Element} */
( toc.parentNode ).classList.contains( sidebarTocContainerClass ) ).toBeTruthy();