aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsn <jsherman@wikimedia.org>2022-12-02 15:03:12 -0600
committerjsn <jsherman@wikimedia.org>2022-12-12 09:43:53 -0600
commitac3128360deb0ad0ee55bbe67008f9d6e1b38094 (patch)
treed885623a8c6b0c0b59ad6af51ea78958102b074c
parent949c83b98b922aac2daa5e5e924cf2e863e256b4 (diff)
downloadmediawikicore-ac3128360deb0ad0ee55bbe67008f9d6e1b38094.tar.gz
mediawikicore-ac3128360deb0ad0ee55bbe67008f9d6e1b38094.zip
Optimize mobile prefs modals
Bug: T324227 Change-Id: I9f399f5517602b15a34c9e1af5dca213c2678785
-rw-r--r--includes/specials/forms/PreferencesFormOOUI.php22
-rw-r--r--resources/src/mediawiki.special.preferences.ooui/mobile.js122
-rw-r--r--resources/src/mediawiki.special.preferences.styles.ooui.less108
3 files changed, 151 insertions, 101 deletions
diff --git a/includes/specials/forms/PreferencesFormOOUI.php b/includes/specials/forms/PreferencesFormOOUI.php
index 48bbe2ecb067..bc70394d0d5d 100644
--- a/includes/specials/forms/PreferencesFormOOUI.php
+++ b/includes/specials/forms/PreferencesFormOOUI.php
@@ -247,7 +247,7 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
'expanded' => false,
'content' => [],
'framed' => false,
- 'classes' => [ 'mw-mobile-preferences-option' ]
+ 'classes' => [ 'mw-mobile-prefsection' ]
] );
$iconHeaderDiv = ( new OOUI\Tag( 'div' ) )
@@ -277,20 +277,24 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
$contentDiv = ( new OOUI\Tag( 'div' ) )->addClasses( [ 'mw-prefs-hidden' ] );
$contentDiv->addClasses( [ 'mw-prefs-content-page' ] );
$contentDiv->setAttributes( [
- 'id' => 'mw-prefs-option-' . $key . '-content'
+ 'id' => 'mw-mobile-prefs-' . $key . '-content'
+ ] );
+ $contentHeader = ( new OOUI\Tag( 'div' ) )->setAttributes( [
+ 'id' => 'mw-mobile-prefs-' . $key . '-head'
] );
- $contentHeader = ( new OOUI\Tag( 'div' ) )->addClasses( [ 'mw-prefs-content-header' ] );
$contentHeaderBackButton = new OOUI\IconWidget( [
- 'icon' => 'previous',
+ 'icon' => 'close',
'label' => $this->msg( "prefs-back-label" ),
'title' => $this->msg( "prefs-back-title" ),
- 'classes' => [ 'mw-prefs-header-icon' ],
+ 'classes' => [ 'mw-prefs-header-icon', 'mw-ui-icon' ],
] );
$contentHeaderBackButton->setAttributes( [
- 'id' => 'mw-prefs-option-' . $key . '-back-button',
+ 'id' => 'mw-mobile-prefs-' . $key . '-back-button',
+ ] );
+ $contentHeaderTitle = ( new OOUI\Tag( 'h5' ) )->setAttributes( [
+ 'id' => 'mw-mobile-prefs-' . $key . '-title',
] );
- $contentHeaderTitle = ( new OOUI\Tag( 'h5' ) )
- ->appendContent( $label )->addClasses( [ 'mw-prefs-header-title' ] );
+ $contentHeaderTitle->appendContent( $label )->addClasses( [ 'mw-prefs-header-title' ] );
$formContent = new OOUI\Widget( [
'content' => new OOUI\HtmlSnippet( $content )
] );
@@ -301,7 +305,7 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
$contentDiv->appendContent( $hiddenForm );
$prefPanel->appendContent( $contentDiv );
$prefPanel->setAttributes( [
- 'id' => 'mw-prefs-option-' . $key,
+ 'id' => 'mw-mobile-prefs-' . $key,
] );
$prefPanel->setInfusable( true );
$prefPanels[] = $prefPanel;
diff --git a/resources/src/mediawiki.special.preferences.ooui/mobile.js b/resources/src/mediawiki.special.preferences.ooui/mobile.js
index 1dc1b213675c..c9fcb8a87571 100644
--- a/resources/src/mediawiki.special.preferences.ooui/mobile.js
+++ b/resources/src/mediawiki.special.preferences.ooui/mobile.js
@@ -2,12 +2,14 @@
* JavaScript for Special:Preferences: mobileLayout.
*/
( function () {
+ // Define a window manager to control the dialogs
+ var dialogFactory = new OO.Factory();
+ var windowManager = new OO.ui.WindowManager( { factory: dialogFactory } );
/*
- * Adds a ToggleSwitchWidget to control each checkboxWidget
- * Hides each checkboxWidget
+ * Add a ToggleSwitchWidget to control each checkboxWidget
+ * Hide each checkboxWidget
*/
- function insertToggles() {
- var checkboxes = document.querySelectorAll( 'span.oo-ui-checkboxInputWidget' );
+ function insertToggles( checkboxes ) {
Array.prototype.forEach.call( checkboxes, function ( checkboxWidget ) {
var checkboxInput = checkboxWidget.querySelector( 'input' );
var toggleSwitchWidget = new OO.ui.ToggleSwitchWidget( {
@@ -22,63 +24,67 @@
checkboxWidget.classList.add( 'hidden' );
} );
}
- $( function () {
- insertToggles();
- var options, windowManager, preferencesForm, prefOptionsContainer, prefContent, prefFormWrapper;
- options = OO.ui.infuse( document.querySelector( '.mw-mobile-preferences-container' ) );
- windowManager = new OO.ui.WindowManager();
- preferencesForm = document.querySelector( '#mw-prefs-form' );
- prefOptionsContainer = document.querySelector( '#mw-prefs-container' );
- prefFormWrapper = document.querySelector( '.mw-htmlform-ooui-wrapper' );
-
- function showContent( element ) {
- prefContent = document.querySelector( '#' + element.elementId + '-content' );
- prefContent.classList.remove( 'mw-prefs-hidden' );
- prefOptionsContainer.classList.add( 'mw-prefs-hidden' );
- prefOptionsContainer.removeAttribute( 'style' );
- preferencesForm.insertBefore( prefContent, preferencesForm.firstChild );
-
- function PrefDialog( config ) {
- PrefDialog.super.call( this, config );
- }
-
- OO.inheritClass( PrefDialog, OO.ui.Dialog );
- PrefDialog.static.name = element.elementId;
- PrefDialog.static.escapable = false;
- PrefDialog.prototype.initialize = function () {
- PrefDialog.super.prototype.initialize.call( this );
- this.content = new OO.ui.PanelLayout( { padded: true, expanded: true } );
- this.$body.append( preferencesForm );
- };
-
- PrefDialog.prototype.getBodyHeight = function () {
- return this.content.$element.outerHeight( true );
- };
-
- var prefDialog = new PrefDialog( { size: 'full' } );
-
- $( document.body ).append( windowManager.$element );
- windowManager.addWindows( [ prefDialog ] );
- windowManager.openWindow( prefDialog );
-
- if ( prefDialog.isOpening() ) {
- document.querySelector( '#mw-mf-viewport' ).classList.add( 'hidden' );
- }
+ /*
+ * Configure and register a dialog for a pref section
+ */
+ function sectionDialog( sectionId, sectionHead, sectionBody ) {
+ function PrefDialog() {
+ var conf = { classes: [ 'overlay-content', 'mw-mobile-pref-window' ] };
+ PrefDialog.super.call( this, conf );
}
+ OO.inheritClass( PrefDialog, OO.ui.Dialog );
+ PrefDialog.static.name = sectionId;
+ PrefDialog.static.escapable = true;
+ PrefDialog.static.size = 'larger';
+ PrefDialog.prototype.initialize = function () {
+ insertToggles( sectionBody.querySelectorAll( 'span.oo-ui-checkboxInputWidget' ) );
+ this.name = sectionId;
+ PrefDialog.super.prototype.initialize.call( this );
+ this.$head.append( sectionHead );
+ this.$head[ 0 ].classList.add( 'mw-mobile-pref-dialog-head' );
+ this.$body.append( sectionBody );
+ this.content = new OO.ui.PanelLayout( { padded: true, expanded: true } );
+ this.$body[ 0 ].classList.add( 'mw-mobile-pref-dialog-body' );
+ };
- options.items.forEach( function ( element ) {
- document.querySelector( '#' + element.elementId ).addEventListener( 'click', function () {
- showContent( element );
+ dialogFactory.register( PrefDialog );
+ }
+ // DOM-dependant code
+ $( function () {
+ /*
+ * Initialize Dialogs for all pref sections
+ */
+ function initDialogs() {
+ // Query the document once, then query that returned element afterwards.
+ var preferencesForm = document.querySelector( '#mw-prefs-form' );
+ var prefButtons = preferencesForm.querySelector( 'div.mw-prefs-buttons' );
+ var sections = preferencesForm.querySelectorAll( '.mw-mobile-prefsection' );
+ // Move the form buttons (such as save) into the dialog after opening.
+ windowManager.on( 'opening', function ( win, opened ) {
+ if ( opened ) {
+ win.$foot[ 0 ].appendChild( prefButtons );
+ }
} );
-
- var backButtonId = '#' + element.elementId + '-back-button';
- document.querySelector( backButtonId ).addEventListener( 'click', function () {
- prefContent.classList.add( 'mw-prefs-hidden' );
- prefOptionsContainer.classList.remove( 'mw-prefs-hidden' );
- prefFormWrapper.insertBefore( preferencesForm, prefFormWrapper.firstChild );
- document.querySelector( '#mw-mf-viewport' ).classList.remove( 'hidden' );
- windowManager.currentWindow.close();
+ // Move the form buttons (such as save) back to the main form while closing.
+ windowManager.on( 'closing', function () {
+ preferencesForm.querySelector( '#preferences' ).appendChild( prefButtons );
} );
- } );
+ // Add the window manager to the form
+ $( preferencesForm ).append( windowManager.$element );
+ // add event listeners and register a dialog for each section
+ Array.prototype.forEach.call( sections, function ( section ) {
+ var sectionContent = preferencesForm.querySelector( '#' + section.id + '-content' );
+ var sectionBody = sectionContent.querySelector( 'div > div.oo-ui-widget' );
+ var sectionHead = sectionContent.querySelector( '#' + section.id + '-head' );
+ sectionHead.querySelector( '#' + section.id + '-back-button' ).addEventListener( 'click', function () {
+ windowManager.closeWindow( section.id );
+ } );
+ preferencesForm.querySelector( '#' + section.id ).addEventListener( 'click', function () {
+ windowManager.openWindow( section.id );
+ } );
+ sectionDialog( section.id, sectionHead, sectionBody );
+ } );
+ }
+ initDialogs();
} );
}() );
diff --git a/resources/src/mediawiki.special.preferences.styles.ooui.less b/resources/src/mediawiki.special.preferences.styles.ooui.less
index 803cfd220c60..d0508c12eb88 100644
--- a/resources/src/mediawiki.special.preferences.styles.ooui.less
+++ b/resources/src/mediawiki.special.preferences.styles.ooui.less
@@ -26,28 +26,14 @@
.mw-email-authenticated .oo-ui-labelWidget { }
*/
-/*
- * Use `position: sticky` on supported browsers, degrades gracefully in
- * all others, therefore no `@supports` feature query to reduce code complexity.
- */
.mw-prefs-buttons {
background-color: #fff;
- .position-sticky();
- bottom: 0;
- margin-top: -1px;
border-top: 1px solid #c8ccd1;
padding: 1em 0;
// Add top box shadow on top only to emphasize content is scrollable underneath `sticky`.
box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.25 );
}
-// Support Edge: The `position: sticky` rule above causes the buttons to
-// disappear in RTL languages on Microsoft Edge. This magically fixes the issue. See T220706.
-#preferences {
- /* stylelint-disable-next-line plugin/no-unsupported-browser-features */
- filter: brightness( 1 );
-}
-
/* This is needed because add extra buttons in a weird way */
.mw-prefs-buttons .mw-htmlform-submit-buttons {
margin: 0;
@@ -191,17 +177,17 @@
These are used when users navigate to Special:Preferences
with params ?useskin=vector&useformat=mobile
*/
-.mw-mobile-preferences-option {
+.mw-mobile-prefsection {
cursor: pointer;
padding-top: 0.3125em;
border-bottom: 0.0625em solid @colorGray12;
}
-.mw-mobile-preferences-option:hover {
+.mw-mobile-prefsection:hover {
background-color: @colorGray15;
}
-.mw-mobile-preferences-option:last-child {
+.mw-mobile-prefsection:last-child {
border-bottom: none; // stylelint-disable-line declaration-property-value-disallowed-list
}
@@ -232,36 +218,88 @@ with params ?useskin=vector&useformat=mobile
display: flex;
}
-.mw-prefs-content-header + div {
- margin-top: 50px;
+/* Override default inline styles for 'larger' dialog */
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-active.mw-mobile-pref-window {
+ padding-top: 0;
}
-.mw-prefs-content-header {
+/* Overriding default inline styles for 'larger' dialog */
+.mw-mobile-pref-window > .oo-ui-window-frame {
+ width: auto !important; /* stylelint-disable-line declaration-no-important */
+ height: 100% !important; /* stylelint-disable-line declaration-no-important */
+ max-height: 100% !important; /* stylelint-disable-line declaration-no-important */
+}
+
+.oo-ui-window-head.mw-mobile-pref-dialog-head {
width: 100%;
- height: 3.125em;
- display: block;
+ height: 3em;
+ display: flex;
+ align-items: center;
border-bottom: 1px solid @colorGray12;
box-shadow: 0 0.25em 0.125em -0.1875em rgba( 0, 0, 0, 0.25 );
position: fixed;
background: #fff;
- z-index: 100;
- margin-top: -52px;
- padding-top: 16px;
}
-.mw-prefs-content-page div.oo-ui-widget.oo-ui-widget-enabled {
- margin-left: 10px;
+.oo-ui-window-head.mw-mobile-pref-dialog-head > div > h5.mw-prefs-header-title {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.25em;
+}
+
+.oo-ui-window-body.mw-mobile-pref-dialog-body {
margin-right: 5px;
- padding-top: 16px;
+ margin-top: 49px;
+ padding-bottom: 66px;
}
-.oo-ui-window-body .mw-htmlform-submit-buttons {
- padding-left: 16px;
+.oo-ui-window-body.mw-mobile-pref-dialog-body > div.oo-ui-widget-enabled > div {
+ padding: 16px;
+}
+
+.oo-ui-window-body.mw-mobile-pref-dialog-body > div.oo-ui-widget-enabled > div:last-child {
+ margin-bottom: 16px;
+}
+
+/* T317110: sub-section title */
+.oo-ui-window-body.mw-mobile-pref-dialog-body > div.oo-ui-widget-enabled > div.mw-prefs-fieldset-wrapper > fieldset.oo-ui-fieldsetLayout.oo-ui-labelElement > legend.oo-ui-fieldsetLayout-header {
+ border-bottom: 1px #000 solid;
+ max-width: 100%;
+}
+
+/* T317110: sub-section and sub-sub-section titles */
+.oo-ui-window-body.mw-mobile-pref-dialog-body div.oo-ui-widget-enabled > div.mw-prefs-fieldset-wrapper > fieldset.oo-ui-fieldsetLayout.oo-ui-labelElement > legend.oo-ui-fieldsetLayout-header > span.oo-ui-labelElement-label {
+ font-size: 1em;
+ font-weight: bold;
+ line-height: 1.25em;
+ margin-bottom: 12px;
+}
+
+/* T317110: preference separation */
+.oo-ui-window-body.mw-mobile-pref-dialog-body div.oo-ui-widget-enabled > div.mw-prefs-fieldset-wrapper > fieldset.oo-ui-fieldsetLayout > div.oo-ui-fieldsetLayout-group > div.oo-ui-widget-enabled > div > div {
+ padding: 12px 0;
+ margin: 0;
+ border-bottom: 1px #eaecf0 solid;
+}
+
+/* T317110: preference label */
+.oo-ui-window-body.mw-mobile-pref-dialog-body .oo-ui-labelElement-label {
+ line-height: 1.25em;
}
-.oo-ui-window-body #preferences {
- position: sticky;
- bottom: 0;
+/* T317110: help text */
+.oo-ui-window-body.mw-mobile-pref-dialog-body div.oo-ui-fieldLayout-body label.oo-ui-inline-help.oo-ui-labelElement-label.oo-ui-labelElement.oo-ui-labelWidget {
+ font-size: 0.875em;
+ line-height: 1.25em;
+}
+
+/* T317110: non-interactive text */
+.oo-ui-window-body.mw-mobile-pref-dialog-body .oo-ui-labelElement-label.oo-ui-labelElement.oo-ui-labelWidget {
+ color: #72777d;
+}
+
+.oo-ui-window-foot > .mw-prefs-buttons {
+ padding-left: 16px;
}
.oo-ui-window-body .oo-ui-fieldLayout-messages {
@@ -271,7 +309,9 @@ with params ?useskin=vector&useformat=mobile
.oo-ui-iconWidget.mw-prefs-header-icon {
color: @colorGray2;
cursor: pointer;
- margin: 0.25em 0.5em;
+ width: 1.25em;
+ height: 1.25em;
+ margin: 0 16px 0 17px;
}
.mw-prefs-header-title {