Use 'toc' skin option and render with new TableOfContents mustache template
Bug: T297611 Change-Id: I8332f7b9c9574d8dece4f7111b299b95533cf386
This commit is contained in:
parent
593cf2c2a3
commit
8a957c0163
|
@ -5,7 +5,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceModule": "skins.vector.styles",
|
"resourceModule": "skins.vector.styles",
|
||||||
"maxSize": "10.1 kB"
|
"maxSize": "10.3 kB"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceModule": "skins.vector.legacy.js",
|
"resourceModule": "skins.vector.legacy.js",
|
||||||
|
|
|
@ -136,6 +136,7 @@ class SkinVector extends SkinMustache {
|
||||||
private const SEARCH_SHOW_THUMBNAIL_CLASS = 'vector-search-box-show-thumbnail';
|
private const SEARCH_SHOW_THUMBNAIL_CLASS = 'vector-search-box-show-thumbnail';
|
||||||
private const SEARCH_AUTO_EXPAND_WIDTH_CLASS = 'vector-search-box-auto-expand-width';
|
private const SEARCH_AUTO_EXPAND_WIDTH_CLASS = 'vector-search-box-auto-expand-width';
|
||||||
private const STICKY_HEADER_ENABLED_CLASS = 'vector-sticky-header-enabled';
|
private const STICKY_HEADER_ENABLED_CLASS = 'vector-sticky-header-enabled';
|
||||||
|
private const TABLE_OF_CONTENTS_ENABLED_CLASS = 'vector-toc-enabled';
|
||||||
private const CLASS_QUIET_BUTTON = 'mw-ui-button mw-ui-quiet';
|
private const CLASS_QUIET_BUTTON = 'mw-ui-button mw-ui-quiet';
|
||||||
private const CLASS_PROGRESSIVE = 'mw-ui-progressive';
|
private const CLASS_PROGRESSIVE = 'mw-ui-progressive';
|
||||||
private const CLASS_ICON_BUTTON = 'mw-ui-icon mw-ui-icon-element';
|
private const CLASS_ICON_BUTTON = 'mw-ui-icon mw-ui-icon-element';
|
||||||
|
@ -485,6 +486,10 @@ class SkinVector extends SkinMustache {
|
||||||
$original['class'] = implode( ' ', [ $original['class'] ?? '', self::STICKY_HEADER_ENABLED_CLASS ] );
|
$original['class'] = implode( ' ', [ $original['class'] ?? '', self::STICKY_HEADER_ENABLED_CLASS ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( VectorServices::getFeatureManager()->isFeatureEnabled( Constants::FEATURE_TABLE_OF_CONTENTS ) ) {
|
||||||
|
$original['class'] = implode( ' ', [ $original['class'] ?? '', self::TABLE_OF_CONTENTS_ENABLED_CLASS ] );
|
||||||
|
}
|
||||||
|
|
||||||
return $original;
|
return $original;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,12 +562,17 @@ class SkinVector extends SkinMustache {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the Table of Contents should be visible.
|
* Determines if the Table of Contents should be visible.
|
||||||
|
* TOC is visible on main namespaces except for the Main Page
|
||||||
|
* when the feature flag is on.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function isTableOfContentsVisibleInSidebar(): bool {
|
private function isTableOfContentsVisibleInSidebar(): bool {
|
||||||
$featureManager = VectorServices::getFeatureManager();
|
$featureManager = VectorServices::getFeatureManager();
|
||||||
return $featureManager->isFeatureEnabled( Constants::FEATURE_TABLE_OF_CONTENTS );
|
$title = $this->getTitle();
|
||||||
|
$isMainNS = $title ? $title->inNamespaces( 0 ) : false;
|
||||||
|
$isMainPage = $title ? $title->isMainPage() : false;
|
||||||
|
return $featureManager->isFeatureEnabled( Constants::FEATURE_TABLE_OF_CONTENTS ) && $isMainNS && !$isMainPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
<div id="mw-panel-toc" class="mw-sidebar">
|
<nav id="mw-panel-toc" class="sidebar-toc" role="navigation" aria-labelledby="sidebar-toc-header">
|
||||||
<!-- sticky TOC goes here -->
|
<div class="sidebar-toc-header">
|
||||||
</div>
|
<h2 class="sidebar-toc-title" aria-hidden="true">Contents</h2>
|
||||||
|
</div>
|
||||||
|
<ul id="table-of-contents">
|
||||||
|
{{#array-sections}}
|
||||||
|
<li class="sidebar-toc-level-{{toclevel}}">
|
||||||
|
<a href="#{{anchor}}">
|
||||||
|
<div class="sidebar-toc-text">
|
||||||
|
<span class="sidebar-toc-numb">{{number}}</span> {{line}}</div>
|
||||||
|
</a>
|
||||||
|
{{#has-subsections}}<ul>{{/has-subsections}}
|
||||||
|
{{#is-last-item}}</li></ul>{{/is-last-item}}
|
||||||
|
{{/array-sections}}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
}}
|
}}
|
||||||
<div class="mw-page-container">
|
<div class="mw-page-container">
|
||||||
<a class="mw-jump-link" href="#content">{{msg-vector-jumptocontent}}</a>
|
<a class="mw-jump-link" href="#content">{{msg-vector-jumptocontent}}</a>
|
||||||
<div class="mw-page-container-inner">
|
<div class="mw-page-container-inner {{#is-vector-table-of-contents-visible}} vector-toc-visible{{/is-vector-table-of-contents-visible}}">
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -44,10 +44,11 @@
|
||||||
|
|
||||||
{{>Header}}
|
{{>Header}}
|
||||||
|
|
||||||
{{#is-vector-table-of-contents-visible}}{{>TableOfContents}}{{/is-vector-table-of-contents-visible}}
|
|
||||||
|
|
||||||
<div class="mw-workspace-container">
|
<div class="mw-workspace-container">
|
||||||
{{>Navigation}}
|
{{>Navigation}}
|
||||||
|
{{#is-vector-table-of-contents-visible}}
|
||||||
|
{{>TableOfContents}}
|
||||||
|
{{/is-vector-table-of-contents-visible}}
|
||||||
<div class="mw-content-container">
|
<div class="mw-content-container">
|
||||||
{{! `role` is unnecessary but kept to support selectors in any gadgets or user styles. }}
|
{{! `role` is unnecessary but kept to support selectors in any gadgets or user styles. }}
|
||||||
<main id="content" class="mw-body" role="main">
|
<main id="content" class="mw-body" role="main">
|
||||||
|
|
|
@ -100,3 +100,10 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update article page's content container when table of contents is enabled
|
||||||
|
.vector-toc-enabled #mw-panel {
|
||||||
|
width: @margin-toc-start-content;
|
||||||
|
background-color: @background-color-base;
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
@import '../../common/variables.less';
|
||||||
|
|
||||||
|
@subcategory-indent: 8px;
|
||||||
|
|
||||||
|
.sidebar-toc {
|
||||||
|
width: 200px;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 12px;
|
||||||
|
float: left;
|
||||||
|
position: sticky;
|
||||||
|
top: calc( @height-sticky-header + 1.5em );
|
||||||
|
background-color: @background-color-base;
|
||||||
|
border: @border-base;
|
||||||
|
border-radius: @border-radius-base;
|
||||||
|
|
||||||
|
.sidebar-toc-header {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toc-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: @font-size-heading-3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toc-numb {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toc-text {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
line-height: 18px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: @subcategory-indent;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @color-base;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sidebar-toc-level-1 {
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
> a {
|
||||||
|
color: @color-link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide TOC when sidebar is open
|
||||||
|
.mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .sidebar-toc {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -39,6 +39,8 @@
|
||||||
// content container for aesthetic reasons. The sidebar is already displaced
|
// content container for aesthetic reasons. The sidebar is already displaced
|
||||||
// -30px so we simply add 30px of space to the width of the sidebar.
|
// -30px so we simply add 30px of space to the width of the sidebar.
|
||||||
@margin-start-content: @width-grid-column-one + unit( 8px / @font-size-browser, em ); // 11.5em @ 16
|
@margin-start-content: @width-grid-column-one + unit( 8px / @font-size-browser, em ); // 11.5em @ 16
|
||||||
|
// Ensure there's enough space between the TOC and content container
|
||||||
|
@margin-toc-start-content: 16em;
|
||||||
|
|
||||||
// Tabs
|
// Tabs
|
||||||
|
|
||||||
|
@ -231,6 +233,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mw-content-container {
|
.mw-content-container {
|
||||||
|
display: flow-root;
|
||||||
max-width: @max-width-content-container;
|
max-width: @max-width-content-container;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
@ -283,6 +286,13 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increase margin when TOC is enabled
|
||||||
|
.vector-toc-enabled .mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container {
|
||||||
|
.skin-vector-disable-max-width & {
|
||||||
|
margin-left: @margin-toc-start-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media ( max-width: @max-width-margin-start-content ) {
|
@media ( max-width: @max-width-margin-start-content ) {
|
||||||
// Adjusts the content and mw-article-toolbar-container.
|
// Adjusts the content and mw-article-toolbar-container.
|
||||||
.mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container,
|
.mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container,
|
||||||
|
@ -290,6 +300,12 @@ body {
|
||||||
margin-left: @margin-start-content;
|
margin-left: @margin-start-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increase margin when TOC is enabled
|
||||||
|
.vector-toc-enabled .mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container,
|
||||||
|
.vector-toc-enabled .mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-article-toolbar-container {
|
||||||
|
margin-left: @margin-toc-start-content;
|
||||||
|
}
|
||||||
|
|
||||||
// Specificity needed to disable the default animations at lower resolutions.
|
// Specificity needed to disable the default animations at lower resolutions.
|
||||||
.vector-animations-ready .mw-sidebar {
|
.vector-animations-ready .mw-sidebar {
|
||||||
// Remove sidebar transition at smaller widths.
|
// Remove sidebar transition at smaller widths.
|
||||||
|
@ -297,6 +313,21 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update article page's content container when
|
||||||
|
// TOC is visible and when TOC is enabled and the sidebar is open
|
||||||
|
.vector-toc-visible .mw-workspace-container .mw-content-container,
|
||||||
|
.vector-toc-visible .mw-workspace-container .mw-article-toolbar-container,
|
||||||
|
.vector-toc-enabled .mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container,
|
||||||
|
.vector-toc-enabled .mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-article-toolbar-container {
|
||||||
|
// Use !important to override checkbox status dependent styles applied above
|
||||||
|
margin-left: @margin-toc-start-content !important; /* stylelint-disable-line declaration-no-important */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent center align when TOC is visible
|
||||||
|
.vector-toc-visible .mw-workspace-container {
|
||||||
|
margin-left: initial;
|
||||||
|
}
|
||||||
|
|
||||||
@media ( min-width: ( @max-width-workspace-container + ( 2 * @padding-horizontal-page-container ) ) ) {
|
@media ( min-width: ( @max-width-workspace-container + ( 2 * @padding-horizontal-page-container ) ) ) {
|
||||||
#mw-panel {
|
#mw-panel {
|
||||||
background: @background-color-page-container;
|
background: @background-color-page-container;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
@import './components/UserLinks.less';
|
@import './components/UserLinks.less';
|
||||||
@import './components/Header.less';
|
@import './components/Header.less';
|
||||||
@import './components/StickyHeader.less';
|
@import './components/StickyHeader.less';
|
||||||
|
@import './components/TableOfContents.less';
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all {
|
@media all {
|
||||||
|
|
Loading…
Reference in New Issue