mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-27 17:10:19 +00:00
Point out the limited width control
The limited control will be pointed to on page load
When wgVectorPageLoadIndicator is set to true (defaults
to false)
Clicking the button should show the indicator.
Additional change:
* Update config.json to reflect new state
(Follow up to 28ada2dc
)
Bug: T333601
Change-Id: I188ed7226b9a1530e54b1aaa80caa0830bf73633
This commit is contained in:
parent
a0c7b58ec6
commit
2622472983
|
@ -50,6 +50,8 @@
|
|||
"vector-site-nav-label": "Site",
|
||||
"vector-main-menu-label": "Main menu",
|
||||
"vector-limited-width-toggle": "Toggle limited content width",
|
||||
"vector-limited-width-toggle-on-popup": "You have switched your layout to full width. To go back to limited width, press this button.",
|
||||
"vector-limited-width-toggle-off-popup": "You can toggle between a limited width and full width by clicking this button.",
|
||||
"vector-page-tools-label": "Tools",
|
||||
"vector-page-tools-general-label": "General",
|
||||
"vector-page-tools-actions-label": "Actions",
|
||||
|
|
|
@ -66,6 +66,8 @@
|
|||
"vector-site-nav-label": "Accessible label for site (main menu) nav landmark",
|
||||
"vector-main-menu-label": "Main menu label",
|
||||
"vector-limited-width-toggle": "Toggle for control to limit content width.",
|
||||
"vector-limited-width-toggle-on-popup": "Hint that points out the limited width toggle control.",
|
||||
"vector-limited-width-toggle-off-popup": "Hint that points out the limited width toggle control.",
|
||||
"vector-page-tools-label": "Label for the page tools pinnable dropdown\n{{identical|Tools}}",
|
||||
"vector-page-tools-general-label": "Label for the page tools 'General' menu\n{{identical|General}}",
|
||||
"vector-page-tools-actions-label": "Label for the page tools 'Actions' menu\n{{identical|Action}}",
|
||||
|
|
|
@ -29,10 +29,10 @@ module.exports = {
|
|||
// An object that configures minimum threshold enforcement for coverage results
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 33,
|
||||
functions: 41,
|
||||
lines: 40,
|
||||
statements: 40
|
||||
branches: 32,
|
||||
functions: 40,
|
||||
lines: 39,
|
||||
statements: 39
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"@doc": "This file describes the shape of the AB config. It exists to support jest",
|
||||
"wgVectorWebABTestEnrollment": {}
|
||||
"@doc": "This file describes the shape of the AB config. It exists to support jest and TypeScript.",
|
||||
"VectorLimitedWidthIndicator": true,
|
||||
"VectorSearchApiUrl": ""
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
const features = require( './features.js' );
|
||||
const popupNotification = require( './popupNotification.js' );
|
||||
const config = require( './config.json' );
|
||||
const LIMITED_WIDTH_FEATURE_NAME = 'limited-width';
|
||||
const AWARE_COOKIE_NAME = `${LIMITED_WIDTH_FEATURE_NAME}-aware`;
|
||||
const TOGGLE_ID = 'toggleWidth';
|
||||
|
||||
/**
|
||||
* Sets data attribute for click tracking purposes.
|
||||
|
@ -20,12 +24,72 @@ function init() {
|
|||
toggle.textContent = mw.msg( 'vector-limited-width-toggle' );
|
||||
toggle.classList.add( 'mw-ui-icon', 'mw-ui-icon-element', 'mw-ui-button', 'vector-limited-width-toggle' );
|
||||
setDataAttribute( toggle );
|
||||
document.body.appendChild( toggle );
|
||||
const toggleMenu = document.createElement( 'div' );
|
||||
toggleMenu.setAttribute( 'class', 'vector-settings' );
|
||||
toggleMenu.appendChild( toggle );
|
||||
document.body.appendChild( toggleMenu );
|
||||
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/39
|
||||
const userMayNotKnowTheyAreInExpandedMode = !mw.cookie.get( AWARE_COOKIE_NAME );
|
||||
const dismiss = () => {
|
||||
mw.cookie.set( AWARE_COOKIE_NAME, '1' );
|
||||
};
|
||||
|
||||
/**
|
||||
* check user has not disabled cookies by
|
||||
* reading the cookie and unsetting the cookie.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
const areCookiesEnabled = () => {
|
||||
dismiss();
|
||||
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/39
|
||||
const savedSuccessfully = mw.cookie.get( AWARE_COOKIE_NAME ) === '1';
|
||||
mw.cookie.set( AWARE_COOKIE_NAME, null );
|
||||
return savedSuccessfully;
|
||||
};
|
||||
/**
|
||||
* @param {string} id this allows us to group notifications making sure only one is visible
|
||||
* at any given time. All existing popups associated with ID will be removed.
|
||||
* @param {number|false} timeout
|
||||
*/
|
||||
const showPopup = ( id, timeout = 4000 ) => {
|
||||
if ( !config.VectorLimitedWidthIndicator ) {
|
||||
return;
|
||||
}
|
||||
const label = features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ?
|
||||
'vector-limited-width-toggle-off-popup' : 'vector-limited-width-toggle-on-popup';
|
||||
// possible messages:
|
||||
// * vector-limited-width-toggle-off-popup
|
||||
// * vector-limited-width-toggle-on-popup
|
||||
popupNotification.add( toggleMenu, mw.msg( label ), id, [], timeout, dismiss );
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: This currently loads OOUI on page load. It should be swapped out
|
||||
* for a more performance friendly version before being deployed.
|
||||
* See T334366.
|
||||
*/
|
||||
const showPageLoadPopups = () => {
|
||||
showPopup( TOGGLE_ID, false );
|
||||
};
|
||||
|
||||
toggle.addEventListener( 'click', function () {
|
||||
features.toggle( LIMITED_WIDTH_FEATURE_NAME );
|
||||
setDataAttribute( toggle );
|
||||
window.dispatchEvent( new Event( 'resize' ) );
|
||||
if ( !features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ) {
|
||||
showPopup( TOGGLE_ID );
|
||||
}
|
||||
if ( !features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ) {
|
||||
dismiss();
|
||||
}
|
||||
} );
|
||||
|
||||
if ( userMayNotKnowTheyAreInExpandedMode ) {
|
||||
if ( areCookiesEnabled() ) {
|
||||
showPageLoadPopups();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = init;
|
||||
|
|
|
@ -9,15 +9,18 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.vector-settings {
|
||||
position: fixed;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
// Note on certain pages the control will have no effect e.g. Special:RecentChanges
|
||||
// Defining this at 1400px is a product decision so do not change it
|
||||
// (more context at https://phabricator.wikimedia.org/T326887#8540889)
|
||||
@media ( min-width: 1400px ) {
|
||||
.vector-limited-width-toggle {
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
//NOTE: enabled/disabled class on body.
|
||||
|
|
|
@ -70,7 +70,7 @@ function togglePinnableClasses( header ) {
|
|||
/**
|
||||
* Create the indicators for the pinnable element
|
||||
*
|
||||
* @param {string|undefined} pinnableElementId
|
||||
* @param {string} pinnableElementId
|
||||
*/
|
||||
function addPinnableElementIndicator( pinnableElementId ) {
|
||||
const dropdownSelector = document.querySelector( `#${pinnableElementId}-dropdown` );
|
||||
|
@ -80,7 +80,7 @@ function addPinnableElementIndicator( pinnableElementId ) {
|
|||
// * vector-page-tools-unpinned-popup
|
||||
// * vector-main-menu-unpinned-popup
|
||||
const message = mw.msg( `${pinnableElementId}-unpinned-popup` );
|
||||
popupNotification.add( container, message );
|
||||
popupNotification.add( container, message, pinnableElementId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,34 @@
|
|||
// Store active notifications to only show one at a time, for use inside clearHints and showHint
|
||||
const /** @type {Record<string,OoUiPopupWidget>} */ activeNotification = {};
|
||||
|
||||
/**
|
||||
* Adds and show a popup to the user to point them to the new location of the element
|
||||
*
|
||||
* @param {Element} container
|
||||
* @param {HTMLElement} container
|
||||
* @param {string} message
|
||||
* @param {string} id
|
||||
* @param {string[]} [classes]
|
||||
* @param {number} [timeout]
|
||||
* @param {boolean} [autoClose]
|
||||
* @param {number|false} [timeout]
|
||||
* @param {Function} [onDismiss]
|
||||
* @return {JQuery.Promise<OoUiPopupWidget|undefined>}
|
||||
*/
|
||||
function add( container, message, classes = [], timeout = 4000, autoClose = true ) {
|
||||
function add( container, message, id, classes = [], timeout = 4000, onDismiss = () => {} ) {
|
||||
/**
|
||||
* @type {any}
|
||||
* @type {OoUiPopupWidget}
|
||||
*/
|
||||
let popupWidget;
|
||||
// clear existing hints.
|
||||
if ( id && activeNotification[ id ] ) {
|
||||
remove( activeNotification[ id ] );
|
||||
delete activeNotification[ id ];
|
||||
}
|
||||
// load oojs-ui if it's not already loaded
|
||||
mw.loader.using( 'oojs-ui-core' ).then( () => {
|
||||
return mw.loader.using( 'oojs-ui-core' ).then( () => {
|
||||
popupWidget = new OO.ui.PopupWidget( {
|
||||
$content: $( '<p>' ).text( message ),
|
||||
autoClose,
|
||||
padded: true,
|
||||
autoClose: timeout !== false,
|
||||
head: timeout === false,
|
||||
anchor: true,
|
||||
align: 'center',
|
||||
position: 'below',
|
||||
|
@ -25,24 +36,43 @@ function add( container, message, classes = [], timeout = 4000, autoClose = true
|
|||
container
|
||||
} );
|
||||
popupWidget.$element.appendTo( container );
|
||||
if ( popupWidget && id ) {
|
||||
activeNotification[ id ] = popupWidget;
|
||||
}
|
||||
popupWidget.on( 'closing', () => {
|
||||
onDismiss();
|
||||
} );
|
||||
show( popupWidget, timeout );
|
||||
return popupWidget;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the popup widget
|
||||
*
|
||||
* @param {any} popupWidget popupWidget from oojs-ui
|
||||
* @param {OoUiPopupWidget} popupWidget popupWidget from oojs-ui
|
||||
* cannot use type because it's not loaded yet
|
||||
* @param {number} [timeout]
|
||||
*/
|
||||
function remove( popupWidget ) {
|
||||
popupWidget.toggle( false );
|
||||
popupWidget.$element.remove();
|
||||
}
|
||||
/**
|
||||
* Toggle the popup widget
|
||||
*
|
||||
* @param {OoUiPopupWidget} popupWidget popupWidget from oojs-ui
|
||||
* cannot use type because it's not loaded yet
|
||||
* @param {number|false} [timeout] use false if user must dismiss it themselves.
|
||||
*/
|
||||
function show( popupWidget, timeout = 4000 ) {
|
||||
popupWidget.toggle( true );
|
||||
// @ts-ignore https://github.com/wikimedia/typescript-types/pull/40
|
||||
popupWidget.toggleClipping( true );
|
||||
// hide the popup after timeout ms
|
||||
if ( timeout === false ) {
|
||||
return;
|
||||
}
|
||||
setTimeout( () => {
|
||||
popupWidget.toggle( false );
|
||||
popupWidget.$element.remove();
|
||||
remove( popupWidget );
|
||||
}, timeout );
|
||||
}
|
||||
|
||||
|
@ -59,5 +89,6 @@ function removeAll( selector = '.vector-popup-notification' ) {
|
|||
|
||||
module.exports = {
|
||||
add,
|
||||
remove,
|
||||
removeAll
|
||||
};
|
||||
|
|
|
@ -209,9 +209,11 @@ const setupTableOfContents = ( tocElement, bodyContent, initSectionObserverFn )
|
|||
.contains( STICKY_HEADER_VISIBLE_CLASS );
|
||||
const containerSelector = !isStickyHeaderVisible ?
|
||||
'.vector-page-titlebar .vector-toc-landmark' : '#vector-sticky-header .vector-toc-landmark';
|
||||
const container = document.querySelector( containerSelector );
|
||||
const container = /** @type {HTMLElement} */(
|
||||
document.querySelector( containerSelector )
|
||||
);
|
||||
if ( container ) {
|
||||
popupNotification.add( container, mw.message( 'vector-toc-unpinned-popup' ).text() );
|
||||
popupNotification.add( container, mw.message( 'vector-toc-unpinned-popup' ).text(), TOC_ID );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -359,7 +359,7 @@
|
|||
},
|
||||
{
|
||||
"name": "resources/skins.vector.js/config.json",
|
||||
"config": [ "VectorSearchApiUrl" ]
|
||||
"config": [ "VectorSearchApiUrl", "VectorLimitedWidthIndicator" ]
|
||||
},
|
||||
{
|
||||
"name": "resources/skins.vector.js/tableOfContentsConfig.json",
|
||||
|
@ -396,6 +396,8 @@
|
|||
"mediawiki.util"
|
||||
],
|
||||
"messages": [
|
||||
"vector-limited-width-toggle-on-popup",
|
||||
"vector-limited-width-toggle-off-popup",
|
||||
"vector-search-loader",
|
||||
"vector-limited-width-toggle",
|
||||
"vector-toc-beginning",
|
||||
|
@ -485,6 +487,10 @@
|
|||
}
|
||||
},
|
||||
"config": {
|
||||
"VectorLimitedWidthIndicator": {
|
||||
"value": false,
|
||||
"description": "Temporary configuration flag that determines whether Vector skins can load indicators for limited width."
|
||||
},
|
||||
"VectorShareUserScripts": {
|
||||
"value": true,
|
||||
"description": "Temporary configuration flag that determines whether Vector skins should share user scripts and styles."
|
||||
|
|
Loading…
Reference in a new issue