RCFilters: Make the interface not jump around while loading
authorRoan Kattouw <roan.kattouw@gmail.com>
Thu, 21 Sep 2017 00:11:22 +0000 (17:11 -0700)
committerCatrope <roan@wikimedia.org>
Thu, 21 Sep 2017 16:58:31 +0000 (16:58 +0000)
* Move the "show new changes" widget into the .rcfilters-head container
** It doesn't conceptually belong here, but this way the min-height
   trick can capture it
* Increase the min-height to account for "show new changes" and drift
* Set a different (higher) min-height on the watchlist
* Adjust the loading spinner position to account for "show new changes" having moved
* Don't apply a margin-top to the first table in WatchlistTopSectionWidget,
  only the second one
* Make .watchlistDetails float while loading
** This is because it starts outside rcfilters-head but is then moved into it.
   Floating it makes it not take any space, which makes the min-height math
   a lot easier (and tolerant to taller .watchlistDetails divs like on enwiki)
* Don't remove the margin and padding from the first h4, this causes jumpiness
** This does increase whitespace slightly, if we want to fix that we could
   set a negative margin-bottom on rcfilters-head instead
* Move the margin-left rules making space for the highlights into a mixin,
  and apply it before initialization instead of after

Bug: T176300
Change-Id: I353deab90cd944209d7540559c6b41decad20e7d

resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js

index dd4f9d4..80aff74 100644 (file)
@@ -2,7 +2,8 @@
 @import 'mw.rcfilters.mixins';
 
 @rcfilters-spinner-width: 70px;
-@rcfilters-head-min-height: 200px;
+@rcfilters-head-min-height: 250px;
+@rcfilters-wl-head-min-height: 320px;
 
 // Corrections for the standard special page
 .client-js {
                border: 0;
        }
 
+       // Reserve space for the UI while it loads
        .rcfilters-head {
                min-height: @rcfilters-head-min-height;
        }
+       // On the watchlist, reserve a bit more
+       .mw-special-Watchlist .rcfilters-head {
+               min-height: @rcfilters-wl-head-min-height;
+       }
+
        body:not( .mw-rcfilters-ui-initialized ) .rcfilters-head {
                opacity: 0.5;
                pointer-events: none;
                        // message of our own
                        display: none;
                }
+
+               // Reserve space for the highlight circles
+               ul,
+               table.mw-enhanced-rc {
+                       .result-circle-margin();
+               }
        }
 
        body.mw-rcfilters-ui-loading .mw-changeslist {
        body.mw-rcfilters-ui-loading .rcfilters-spinner {
                display: block;
                // When loading new results, display the spinner on top of the results area
-               margin-top: 4em;
+               margin-top: 2em;
        }
 
        #contentSub,
        form#mw-watchlist-resetbutton {
                display: none;
        }
+
+       // Make the watchlist-details message display while loading, but make it not take up any
+       // space. This makes the min-height trick work better.
+       .watchlistDetails {
+               float: left;
+       }
 }
 
 .mw-rcfilters-staticfilters-selected {
index 6c8ebac..6c44cc4 100644 (file)
        }
 }
 
+// A mixin for changes list containers. Applies enough margin-left to fit the 5 highlight circles.
+.result-circle-margin() {
+       margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )';
+}
+
 // A mixin just for changesListWrapperWidget page, to output the scope of the widget
 // so it is before the rest of the rule; we need the li& to be in
 // between the wrapper scope and the color-cX class, which doesn't
index 5ef60e0..555631b 100644 (file)
                background-color: #dee0e3;
        }
 
-       h4:first-of-type {
-               margin-top: 0;
-               padding-top: 0;
-       }
-
-       ul {
-               // Each li's margin-left should be the width of the highlights
-               // element + the margin
-               margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )';
-       }
-
        &-highlighted {
                ul {
                        list-style: none;
@@ -69,8 +58,6 @@
        // Correction for Enhanced RC
        // This is outside the scope of the 'highlights' wrapper
        table.mw-enhanced-rc {
-               margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )';
-
                td:last-child {
                        width: 100%;
                }
index 5e1e118..6fa3aa2 100644 (file)
@@ -16,7 +16,7 @@
                float: right;
        }
 
-       .mw-rcfilters-ui-table {
+       &-savedLinksTable {
                margin-top: 1em;
        }
 
index 279e5be..ea32e36 100644 (file)
@@ -48,7 +48,7 @@
                        // We handle our own display/hide of the empty results message
                        .removeClass( 'mw-changeslist-empty' );
 
-               this.setupNewChangesButtonContainer( this.$element );
+               this.setupNewChangesButtonContainer();
        };
 
        /* Initialization */
 
        /**
         * Setup the container for the 'new changes' button.
-        *
-        * @param {jQuery} $content
         */
-       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function ( $content ) {
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function () {
                this.showNewChangesLink = new OO.ui.ButtonWidget( {
                        framed: false,
                        label: mw.message( 'rcfilters-show-new-changes' ).text(),
                this.showNewChangesLink.connect( this, { click: 'onShowNewChangesClick' } );
                this.showNewChangesLink.toggle( false );
 
-               $content.before(
+               // HACK: Add the -newChanges div inside rcfilters-head, rather than right above us
+               // Visually it's the same place, but by putting it inside rcfilters-head we are
+               // able to use the min-height rule to prevent the page from jumping when this is added.
+               this.$element.parent().find( '.rcfilters-head' ).append(
                        $( '<div>' )
                                .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-newChanges' )
                                .append( this.showNewChangesLink.$element )
index 7d78565..b9d9bdf 100644 (file)
@@ -52,6 +52,7 @@
 
                $bottomTable = $( '<div>' )
                        .addClass( 'mw-rcfilters-ui-table' )
+                       .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget-savedLinksTable' )
                        .append(
                                $( '<div>' )
                                        .addClass( 'mw-rcfilters-ui-row' )