Build the sticky header skeleton
The sticky header is currently disabled unconditionally and nothing is wired up, with placeholders for data and functionality which will be added in future. Bug: T289716 Change-Id: I16223ce849267e718aad22b8a24b2327332ac8b7
This commit is contained in:
parent
a068d6125d
commit
8657171471
|
@ -5,7 +5,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceModule": "skins.vector.styles",
|
"resourceModule": "skins.vector.styles",
|
||||||
"maxSize": "9.62 kB"
|
"maxSize": "9.7 kB"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceModule": "skins.vector.legacy.js",
|
"resourceModule": "skins.vector.legacy.js",
|
||||||
|
|
|
@ -381,14 +381,6 @@ class Hooks {
|
||||||
$bodyAttrs['class'] .= ' skin-vector-search-vue';
|
$bodyAttrs['class'] .= ' skin-vector-search-vue';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
VectorServices::getFeatureManager()->isFeatureEnabled(
|
|
||||||
Constants::FEATURE_STICKY_HEADER
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
$bodyAttrs['class'] .= ' skin-vector-sticky-header';
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = $sk->getConfig();
|
$config = $sk->getConfig();
|
||||||
// Should we disable the max-width styling?
|
// Should we disable the max-width styling?
|
||||||
if ( !self::isSkinVersionLegacy() && $sk->getTitle() && self::shouldDisableMaxWidth(
|
if ( !self::isSkinVersionLegacy() && $sk->getTitle() && self::shouldDisableMaxWidth(
|
||||||
|
|
|
@ -44,6 +44,10 @@ class SkinVector extends SkinMustache {
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private const MENU_TYPE_DROPDOWN = 2;
|
private const MENU_TYPE_DROPDOWN = 2;
|
||||||
private const MENU_TYPE_PORTAL = 3;
|
private const MENU_TYPE_PORTAL = 3;
|
||||||
|
private const NO_ICON = [
|
||||||
|
'icon' => 'none',
|
||||||
|
'class' => 'sticky-header-icon'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* T243281: Code used to track clicks to opt-out link.
|
* T243281: Code used to track clicks to opt-out link.
|
||||||
|
@ -296,6 +300,24 @@ class SkinVector extends SkinMustache {
|
||||||
Hooks::onSkinTemplateNavigation( $skin, $content_navigation );
|
Hooks::onSkinTemplateNavigation( $skin, $content_navigation );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate data needed to generate the sticky header.
|
||||||
|
* Lack of i18n is intentional and will be done as part of follow up work.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getStickyHeaderData() {
|
||||||
|
return [
|
||||||
|
'title' => 'Audre Lorde',
|
||||||
|
'heading' => 'Introduction',
|
||||||
|
'primary-action' => 'Primary action',
|
||||||
|
'data-icon-start' => self::NO_ICON,
|
||||||
|
'data-icon-end' => self::NO_ICON,
|
||||||
|
'data-icons' => [
|
||||||
|
self::NO_ICON, self::NO_ICON, self::NO_ICON, self::NO_ICON
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
@ -338,7 +360,9 @@ class SkinVector extends SkinMustache {
|
||||||
|
|
||||||
'sidebar-visible' => $this->isSidebarVisible(),
|
'sidebar-visible' => $this->isSidebarVisible(),
|
||||||
|
|
||||||
'is-language-in-header' => $this->isLanguagesInHeader(),
|
'data-vector-sticky-header' => VectorServices::getFeatureManager()->isFeatureEnabled(
|
||||||
|
Constants::FEATURE_STICKY_HEADER
|
||||||
|
) ? $this->getStickyHeaderData() : false,
|
||||||
] );
|
] );
|
||||||
|
|
||||||
if ( $skin->getUser()->isRegistered() ) {
|
if ( $skin->getUser()->isRegistered() ) {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-{{icon}} {{class}}"></div>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<header id="vector-sticky-header"
|
||||||
|
class="vector-sticky-header {{#is-visible}}vector-sticky-header-visible{{/is-visible}}">
|
||||||
|
<div class="vector-sticky-header-start">
|
||||||
|
<div class="vector-sticky-header-icon-start">
|
||||||
|
{{#data-icon-start}}
|
||||||
|
{{>Icon}}
|
||||||
|
{{/data-icon-start}}
|
||||||
|
</div>
|
||||||
|
<div class="vector-sticky-header-context-bar">
|
||||||
|
<div class="vector-sticky-header-context-bar-primary">{{title}}</div>
|
||||||
|
<div class="vector-sticky-header-context-bar-secondary">{{heading}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="vector-sticky-header-end">
|
||||||
|
<div class="vector-sticky-header-icons">
|
||||||
|
{{#data-icons}}
|
||||||
|
{{>Icon}}
|
||||||
|
{{/data-icons}}
|
||||||
|
</div>
|
||||||
|
<div class="mw-ui-button">
|
||||||
|
{{primary-action}}
|
||||||
|
</div>
|
||||||
|
<div class="vector-sticky-header-icon-end">
|
||||||
|
{{#data-icon-end}}
|
||||||
|
{{>Icon}}
|
||||||
|
{{/data-icon-end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
|
@ -42,7 +42,6 @@
|
||||||
{{#sidebar-visible}}checked{{/sidebar-visible}}>
|
{{#sidebar-visible}}checked{{/sidebar-visible}}>
|
||||||
|
|
||||||
{{>Header}}
|
{{>Header}}
|
||||||
|
|
||||||
<div class="mw-workspace-container">
|
<div class="mw-workspace-container">
|
||||||
{{>Navigation}}
|
{{>Navigation}}
|
||||||
<div class="mw-content-container">
|
<div class="mw-content-container">
|
||||||
|
@ -98,3 +97,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div> {{! END mw-page-container-inner }}
|
</div> {{! END mw-page-container-inner }}
|
||||||
</div> {{! END mw-page-container }}
|
</div> {{! END mw-page-container }}
|
||||||
|
{{#data-vector-sticky-header}}
|
||||||
|
{{>StickyHeader}}
|
||||||
|
{{/data-vector-sticky-header}}
|
||||||
|
|
|
@ -152,3 +152,9 @@
|
||||||
|
|
||||||
// Transitions
|
// Transitions
|
||||||
@transition-duration-base: 100ms;
|
@transition-duration-base: 100ms;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Layout
|
||||||
|
//
|
||||||
|
@max-width-page-container: unit( 1650px / @font-size-browser, em ); // 103.125em @ 16
|
||||||
|
@padding-horizontal-page-container: unit( 30px / @font-size-browser, em ); // 1.875em @ 16
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
var collapsibleTabs = require( '../skins.vector.legacy.js/collapsibleTabs.js' ),
|
var collapsibleTabs = require( '../skins.vector.legacy.js/collapsibleTabs.js' ),
|
||||||
vector = require( '../skins.vector.legacy.js/vector.js' ),
|
vector = require( '../skins.vector.legacy.js/vector.js' ),
|
||||||
|
stickyHeader = require( './stickyHeader.js' ),
|
||||||
languageButton = require( './languageButton.js' ),
|
languageButton = require( './languageButton.js' ),
|
||||||
initSearchLoader = require( './searchLoader.js' ).initSearchLoader,
|
initSearchLoader = require( './searchLoader.js' ).initSearchLoader,
|
||||||
dropdownMenus = require( './dropdownMenus.js' ),
|
dropdownMenus = require( './dropdownMenus.js' ),
|
||||||
|
@ -72,6 +73,7 @@ function main( window ) {
|
||||||
initSearchLoader( document );
|
initSearchLoader( document );
|
||||||
searchToggle();
|
searchToggle();
|
||||||
languageButton();
|
languageButton();
|
||||||
|
stickyHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
main( window );
|
main( window );
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
module.exports = function () {
|
||||||
|
var header = document.getElementById( 'vector-sticky-header' );
|
||||||
|
if ( !header ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: Use IntersectionObserver
|
||||||
|
header.classList.add( 'vector-sticky-header-visible' );
|
||||||
|
};
|
|
@ -0,0 +1,73 @@
|
||||||
|
@import '../../common/variables.less';
|
||||||
|
@import 'mediawiki.mixins.less';
|
||||||
|
|
||||||
|
.vector-sticky-header {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: @z-index-header;
|
||||||
|
transform: translateY( -100% );
|
||||||
|
transition: transform 250ms linear;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
max-width: @max-width-page-container + @padding-horizontal-page-container + @padding-horizontal-page-container;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: @background-color-base;
|
||||||
|
background-color: #fffffff7;
|
||||||
|
border-bottom: 1px solid @colorGray14;
|
||||||
|
// FIXME: Should this adapt to different thresholds? Ask Alex!
|
||||||
|
padding: 6px 8px 6px 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
@media ( min-width: @width-breakpoint-desktop ) {
|
||||||
|
padding: 6px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-visible {
|
||||||
|
transform: translateY( 0% );
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Layout
|
||||||
|
//
|
||||||
|
&-start {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-end {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Components
|
||||||
|
//
|
||||||
|
&-icons,
|
||||||
|
&-context-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 0 15px;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-context-bar {
|
||||||
|
border-left: 1px solid #c8c8c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-context-bar-primary {
|
||||||
|
padding-right: 15px;
|
||||||
|
font-size: unit( 22 / @font-size-browser, em );
|
||||||
|
}
|
||||||
|
|
||||||
|
&-context-bar-secondary {
|
||||||
|
&:before {
|
||||||
|
padding-right: 15px;
|
||||||
|
content: '|';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,9 +65,7 @@
|
||||||
|
|
||||||
// Page container
|
// Page container
|
||||||
|
|
||||||
@max-width-page-container: unit( 1650px / @font-size-browser, em ); // 103.125em @ 16
|
|
||||||
@min-width-page-container--padded: @max-width-page-container + ( 2 * @padding-horizontal-page-container ); // 106.875em
|
@min-width-page-container--padded: @max-width-page-container + ( 2 * @padding-horizontal-page-container ); // 106.875em
|
||||||
@padding-horizontal-page-container: unit( 30px / @font-size-browser, em ); // 1.875em @ 16
|
|
||||||
|
|
||||||
// Content containers
|
// Content containers
|
||||||
|
|
||||||
|
@ -147,12 +145,6 @@ body {
|
||||||
// allow z-index to apply so search results overlay article
|
// allow z-index to apply so search results overlay article
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: @z-index-header;
|
z-index: @z-index-header;
|
||||||
|
|
||||||
.skin-vector-sticky-header & {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
background: @background-color-base;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Searchbox */
|
/* Searchbox */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
@import './components/Sidebar.less';
|
@import './components/Sidebar.less';
|
||||||
@import './components/LanguageButton.less';
|
@import './components/LanguageButton.less';
|
||||||
@import './components/UserLinks.less';
|
@import './components/UserLinks.less';
|
||||||
|
@import './components/StickyHeader.less';
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all {
|
@media all {
|
||||||
|
|
|
@ -192,6 +192,7 @@
|
||||||
"name": "resources/skins.vector.js/config.json",
|
"name": "resources/skins.vector.js/config.json",
|
||||||
"callback": "Vector\\Hooks::getVectorResourceLoaderConfig"
|
"callback": "Vector\\Hooks::getVectorResourceLoaderConfig"
|
||||||
},
|
},
|
||||||
|
"resources/skins.vector.js/stickyHeader.js",
|
||||||
"resources/skins.vector.js/dropdownMenus.js",
|
"resources/skins.vector.js/dropdownMenus.js",
|
||||||
"resources/skins.vector.js/sidebar.js",
|
"resources/skins.vector.js/sidebar.js",
|
||||||
"resources/skins.vector.legacy.js/collapsibleTabs.js",
|
"resources/skins.vector.legacy.js/collapsibleTabs.js",
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import template from '!!raw-loader!../includes/templates/StickyHeader.mustache';
|
||||||
|
import Icon from '!!raw-loader!../includes/templates/Icon.mustache';
|
||||||
|
|
||||||
|
const NO_ICON = {
|
||||||
|
icon: 'none',
|
||||||
|
class: 'sticky-header-icon'
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
title: 'Audre Lorde',
|
||||||
|
heading: 'Introduction',
|
||||||
|
'primary-action': 'Primary action',
|
||||||
|
'is-visible': true,
|
||||||
|
'data-icon-start': NO_ICON,
|
||||||
|
'data-icon-end': NO_ICON,
|
||||||
|
'data-icons': [
|
||||||
|
NO_ICON, NO_ICON, NO_ICON, NO_ICON
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export const STICKY_HEADER_TEMPLATE_PARTIALS = {
|
||||||
|
Icon
|
||||||
|
};
|
||||||
|
|
||||||
|
export { template, data };
|
|
@ -0,0 +1,13 @@
|
||||||
|
import mustache from 'mustache';
|
||||||
|
import '../resources/skins.vector.styles/components/StickyHeader.less';
|
||||||
|
|
||||||
|
import { template, data,
|
||||||
|
STICKY_HEADER_TEMPLATE_PARTIALS } from './StickyHeader.stories.data';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'StickyHeader'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const stickyHeader = () => mustache.render(
|
||||||
|
template, data, STICKY_HEADER_TEMPLATE_PARTIALS
|
||||||
|
);
|
Loading…
Reference in New Issue