Add custom limited width popup

Bug: T333601
Change-Id: I663d6a391aeeb05c27f2f2b8829c22325b528b39
This commit is contained in:
bwang 2023-04-12 15:36:55 -05:00 committed by Jdlrobson
parent 7c02deca9b
commit 4f76994970
7 changed files with 165 additions and 37 deletions

View file

@ -9,7 +9,7 @@
},
{
"resourceModule": "skins.vector.js",
"maxSize": "14.3 kB"
"maxSize": "14.8 kB"
},
{
"resourceModule": "skins.vector.legacy.js",

View file

@ -460,7 +460,12 @@ class SkinVector22 extends SkinMustache {
'has-buttons-in-content-top' => $this->isLanguagesInContentAt( 'top' ) || $hasAddTopicButton,
'is-language-in-content-bottom' => $this->isLanguagesInContentAt( 'bottom' ),
// Cast empty string to null
'html-subtitle' => $parentData['html-subtitle'] === '' ? null : $parentData['html-subtitle']
'html-subtitle' => $parentData['html-subtitle'] === '' ? null : $parentData['html-subtitle'],
// FIXME: Replace with VectorComponentButton
'data-vector-settings-button' => [
'label' => $this->msg( 'vector-limited-width-toggle' ),
'class' => 'mw-ui-icon mw-ui-icon-element vector-limited-width-toggle',
],
] );
}
}

View file

@ -83,3 +83,6 @@
{{>StickyHeader}}
</div>
{{/data-vector-sticky-header}}
<div class='vector-settings'>
{{#data-vector-settings-button}}{{>Button}}{{/data-vector-settings-button}}
</div>

View file

@ -29,10 +29,10 @@ module.exports = {
// An object that configures minimum threshold enforcement for coverage results
coverageThreshold: {
global: {
branches: 32,
functions: 40,
lines: 39,
statements: 39
branches: 31,
functions: 39,
lines: 38,
statements: 38
}
},

View file

@ -14,26 +14,45 @@ function setDataAttribute( toggleBtn ) {
toggleBtn.dataset.eventName = features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ?
'limited-width-toggle-off' : 'limited-width-toggle-on';
}
/**
* Gets appropriate popup text based off the limited width feature flag
*
* @return {string}
*/
function getPopupText() {
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
return mw.msg( label );
}
/**
* adds a toggle button
*/
function init() {
const toggle = document.createElement( 'button' );
toggle.setAttribute( 'title', mw.msg( 'vector-limited-width-toggle' ) );
toggle.setAttribute( 'aria-hidden', 'true' );
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' );
let settings = /** @type {HTMLElement} */ ( document.querySelector( '.vector-settings' ) );
let toggle = /** @type {HTMLElement} */ ( document.querySelector( '.vector-limited-width-toggle' ) );
if ( !( toggle && settings ) ) {
// FIXME: Replace this block with a return statement after caching implications are resolved
toggle = document.createElement( 'button' );
toggle.setAttribute( 'title', mw.msg( 'vector-limited-width-toggle' ) );
toggle.setAttribute( 'aria-hidden', 'true' );
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' );
settings = document.createElement( 'div' );
settings.setAttribute( 'class', 'vector-settings' );
settings.appendChild( toggle );
document.body.appendChild( settings );
}
setDataAttribute( 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.
@ -47,6 +66,7 @@ function init() {
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.
@ -56,12 +76,7 @@ function init() {
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 );
popupNotification.add( settings, getPopupText(), id, [], timeout, dismiss );
};
/**
@ -70,7 +85,10 @@ function init() {
* See T334366.
*/
const showPageLoadPopups = () => {
showPopup( TOGGLE_ID, false );
if ( !config.VectorLimitedWidthIndicator ) {
return;
}
addLimitedWidthPopup( settings, getPopupText(), dismiss );
};
toggle.addEventListener( 'click', function () {
@ -80,9 +98,6 @@ function init() {
if ( !features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ) {
showPopup( TOGGLE_ID );
}
if ( !features.isEnabled( LIMITED_WIDTH_FEATURE_NAME ) ) {
dismiss();
}
} );
if ( userMayNotKnowTheyAreInExpandedMode ) {
@ -91,5 +106,36 @@ function init() {
}
}
}
/**
* @param {HTMLElement} container
* @param {string} message
* @param {Function} [onDismiss]
*/
function addLimitedWidthPopup( container, message, onDismiss = () => {} ) {
const popupTemplateString = `
<div class="vector-limited-width-popup">
<div class="vector-limited-width-popup-head">
<button class="vector-limited-width-popup-close-button mw-ui-button mw-ui-quiet mw-ui-icon-element">
<span class="mw-ui-icon mw-ui-icon-wikimedia-close"></span>
<span>Close</span>
</button>
</div>
<div class="vector-limited-width-popup-body">
<p>${message}</p>
</div>
<div class="vector-limited-width-popup-anchor"></div>
</div>
`;
const popupFrag = document.createRange().createContextualFragment( popupTemplateString );
container.appendChild( popupFrag );
const closeButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-limited-width-popup-close-button' ) );
closeButton.addEventListener( 'click', () => {
const popup = /** @type {HTMLElement} */ ( document.querySelector( '.vector-limited-width-popup' ) );
if ( popup && popup.parentElement ) {
popup.parentElement.removeChild( popup );
}
onDismiss();
}, { once: true } );
}
module.exports = init;

View file

@ -1,11 +1,4 @@
/**
* Limited width toggle - a button which lets users change the layout from
* a fixed-width content column to a layout where the content takes up the
* full window width.
*/
// By default, toggle should be hidden unless the breakpoint below is reached.
.vector-limited-width-toggle {
.client-nojs .vector-settings {
display: none;
}
@ -15,11 +8,24 @@
right: 8px;
}
/**
* Limited width toggle - a button which lets users change the layout from
* a fixed-width content column to a layout where the content takes up the
* full window width.
*/
// By default, toggle should be hidden unless the breakpoint below is reached.
.vector-limited-width-toggle,
.vector-limited-width-popup {
display: none;
}
// 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 {
.vector-limited-width-toggle,
.vector-limited-width-popup {
display: block;
}
@ -32,3 +38,70 @@
background-image: url( images/fullscreen.svg );
}
}
// Custom popup notification that shows on page load
.vector-limited-width-popup {
position: absolute;
z-index: 1;
filter: drop-shadow( 0 2px 1px rgba( 0, 0, 0, 0.3 ) );
background-color: #fff;
border: 1px solid #a2a9b1;
border-radius: 2px;
margin-bottom: 9px;
left: -290.733px;
bottom: 31px;
&-head {
margin-bottom: 9px;
}
&-close-button {
position: absolute;
right: 0;
}
&-body {
margin: 5px 12px;
line-height: 1.42857143em;
width: 296px;
height: auto;
max-width: 298px;
max-height: 593px;
p {
margin: 0.4em 0 0.5em 0;
}
}
&-anchor {
bottom: -9px;
display: block;
position: absolute;
background-repeat: no-repeat;
left: 306.367px;
&::before,
&::after {
content: '';
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
}
&::before {
top: -10px;
left: -9px;
border-top-color: #a2a9b1;
border-width: 10px;
}
&::after {
top: -10px;
left: -8px;
border-top-color: #fff;
border-width: 9px;
}
}
}

View file

@ -331,7 +331,8 @@
"imageGallery",
"userGroup",
"expand",
"listBullet"
"listBullet",
"close"
]
},
"skins.vector.js": {