mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-28 01:20:07 +00:00
Merge "Point out the limited width control"
This commit is contained in:
commit
1f95d60531
|
@ -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