Merge "Refactor search component expand behavior and add auto-expand-width prop to search component"

This commit is contained in:
jenkins-bot 2022-01-05 17:52:35 +00:00 committed by Gerrit Code Review
commit 42fec59f54
6 changed files with 101 additions and 55 deletions

View File

@ -105,7 +105,8 @@ class SkinVector extends SkinMustache {
'tabindex' => '-1', 'tabindex' => '-1',
'class' => 'sticky-header-icon' 'class' => 'sticky-header-icon'
]; ];
private const SEARCH_EXPANDING_CLASS = 'vector-search-box-show-thumbnail'; private const SEARCH_SHOW_THUMBNAIL_CLASS = 'vector-search-box-show-thumbnail';
private const SEARCH_AUTO_EXPAND_WIDTH_CLASS = 'vector-search-box-auto-expand-width';
private const STICKY_HEADER_ENABLED_CLASS = 'vector-sticky-header-enabled'; private const STICKY_HEADER_ENABLED_CLASS = 'vector-sticky-header-enabled';
private const CLASS_QUIET_BUTTON = 'mw-ui-button mw-ui-quiet'; private const CLASS_QUIET_BUTTON = 'mw-ui-button mw-ui-quiet';
private const CLASS_PROGRESSIVE = 'mw-ui-progressive'; private const CLASS_PROGRESSIVE = 'mw-ui-progressive';
@ -583,7 +584,8 @@ class SkinVector extends SkinMustache {
!$this->isLegacy(), !$this->isLegacy(),
// is primary mode of search // is primary mode of search
true, true,
'searchform' 'searchform',
true
), ),
'data-vector-sticky-header' => VectorServices::getFeatureManager()->isFeatureEnabled( 'data-vector-sticky-header' => VectorServices::getFeatureManager()->isFeatureEnabled(
Constants::FEATURE_STICKY_HEADER Constants::FEATURE_STICKY_HEADER
@ -593,7 +595,8 @@ class SkinVector extends SkinMustache {
// Collapse inside search box is disabled. // Collapse inside search box is disabled.
false, false,
false, false,
'vector-sticky-search-form' 'vector-sticky-search-form',
false
), ),
VectorServices::getFeatureManager()->isFeatureEnabled( VectorServices::getFeatureManager()->isFeatureEnabled(
Constants::FEATURE_STICKY_HEADER_EDIT Constants::FEATURE_STICKY_HEADER_EDIT
@ -657,9 +660,16 @@ class SkinVector extends SkinMustache {
* @param bool $isCollapsible * @param bool $isCollapsible
* @param bool $isPrimary * @param bool $isPrimary
* @param string $formId * @param string $formId
* @param bool $autoExpandWidth
* @return array modified version of $searchBoxData * @return array modified version of $searchBoxData
*/ */
private function getSearchData( array $searchBoxData, bool $isCollapsible, bool $isPrimary, string $formId ) { private function getSearchData(
array $searchBoxData,
bool $isCollapsible,
bool $isPrimary,
string $formId,
bool $autoExpandWidth
) {
$searchClass = ''; $searchClass = '';
// Determine the search widget treatment to send to the user // Determine the search widget treatment to send to the user
@ -671,8 +681,9 @@ class SkinVector extends SkinMustache {
$searchClass .= ' vector-search-box-collapses '; $searchClass .= ' vector-search-box-collapses ';
} }
if ( $this->shouldSearchExpand() ) { if ( $this->doesSearchHaveThumbnails() ) {
$searchClass .= ' ' . self::SEARCH_EXPANDING_CLASS; $searchClass .= ' ' . self::SEARCH_SHOW_THUMBNAIL_CLASS .
( $autoExpandWidth ? ' ' . self::SEARCH_AUTO_EXPAND_WIDTH_CLASS : '' );
} }
// Annotate search box with a component class. // Annotate search box with a component class.
@ -728,15 +739,12 @@ class SkinVector extends SkinMustache {
} }
/** /**
* Determines whether or not the search input should expand when focused * Returns `true` if WVUI is enabled to show thumbnails and `false` otherwise.
* before WVUI search is loaded. In WVUI, the search input expands to * Note this is only relevant for WVUI search (not legacy search).
* accomodate thumbnails in the suggestion list. When thumbnails are
* disabled, the input should not expand. Note this is only relevant for WVUI
* search (not legacy search).
* *
* @return bool * @return bool
*/ */
private function shouldSearchExpand(): bool { private function doesSearchHaveThumbnails(): bool {
$featureManager = VectorServices::getFeatureManager(); $featureManager = VectorServices::getFeatureManager();
return $featureManager->isFeatureEnabled( Constants::FEATURE_USE_WVUI_SEARCH ) && return $featureManager->isFeatureEnabled( Constants::FEATURE_USE_WVUI_SEARCH ) &&

View File

@ -17,6 +17,7 @@
:show-thumbnail="showThumbnail" :show-thumbnail="showThumbnail"
:show-description="showDescription" :show-description="showDescription"
:highlight-query="highlightQuery" :highlight-query="highlightQuery"
:auto-expand-width="autoExpandWidth"
@fetch-start="instrumentation.onFetchStart" @fetch-start="instrumentation.onFetchStart"
@fetch-end="instrumentation.onFetchEnd" @fetch-end="instrumentation.onFetchEnd"
@suggestion-click="instrumentation.onSuggestionClick" @suggestion-click="instrumentation.onSuggestionClick"
@ -121,6 +122,10 @@ module.exports = {
highlightQuery: { highlightQuery: {
type: Boolean, type: Boolean,
default: true default: true
},
autoExpandWidth: {
type: Boolean,
default: false
} }
}, },
data: function () { data: function () {

View File

@ -6,18 +6,18 @@ var
config = require( './config.json' ); config = require( './config.json' );
/** /**
* @param {Element} searchForm * @param {Element} searchBox
* @return {void} * @return {void}
*/ */
function initApp( searchForm ) { function initApp( searchBox ) {
var var searchForm = searchBox.querySelector( '.vector-search-box-form' ),
titleInput = /** @type {HTMLInputElement|null} */ ( titleInput = /** @type {HTMLInputElement|null} */ (
searchForm.querySelector( 'input[name=title]' ) searchBox.querySelector( 'input[name=title]' )
), ),
search = /** @type {HTMLInputElement|null} */ ( searchForm.querySelector( 'input[name="search"]' ) ), search = /** @type {HTMLInputElement|null} */ ( searchBox.querySelector( 'input[name="search"]' ) ),
searchPageTitle = titleInput && titleInput.value; searchPageTitle = titleInput && titleInput.value;
if ( !search || !titleInput ) { if ( !searchForm || !search || !titleInput ) {
throw new Error( 'Attempted to create Vue search element from an incompatible element.' ); throw new Error( 'Attempted to create Vue search element from an incompatible element.' );
} }
@ -31,7 +31,8 @@ function initApp( searchForm ) {
searchPageTitle: searchPageTitle, searchPageTitle: searchPageTitle,
searchTitle: search.getAttribute( 'title' ), searchTitle: search.getAttribute( 'title' ),
searchPlaceholder: search.getAttribute( 'placeholder' ), searchPlaceholder: search.getAttribute( 'placeholder' ),
searchQuery: search.value searchQuery: search.value,
autoExpandWidth: searchBox ? searchBox.classList.contains( 'vector-search-box-auto-expand-width' ) : false
// Pass additional config from server. // Pass additional config from server.
}, config ) }, config )
) )
@ -42,11 +43,10 @@ function initApp( searchForm ) {
* @return {void} * @return {void}
*/ */
function main( document ) { function main( document ) {
var var searchBoxes = document.querySelectorAll( '.vector-search-box' );
searchForms = document.querySelectorAll( '.vector-search-box-form' );
searchForms.forEach( function ( searchForm ) { searchBoxes.forEach( function ( searchBox ) {
initApp( searchForm ); initApp( searchBox );
} ); } );
} }
main( document ); main( document );

View File

@ -32,9 +32,20 @@
flex-grow: 1; flex-grow: 1;
} }
// Allocate space for the extra width of the input when the search component
// has thumbnails.
//
// FIXME: This can be removed when WVUI in core has been upgraded to use the
// `.wvui-typeahead-search--auto-expand-width` class.
.wvui-typeahead-search--show-thumbnail:not( .wvui-typeahead-search--auto-expand-width ) {
margin-left: @size-search-expand;
}
@media ( min-width: @width-breakpoint-desktop ) { @media ( min-width: @width-breakpoint-desktop ) {
@margin-start-search: 40px;
.vector-search-box { .vector-search-box {
margin-left: unit( 40px / @font-size-browser / @font-size-base, em ); // 2.85714286em @ 16 & 0.875em margin-left: unit( @margin-start-search / @font-size-browser / @font-size-base, em ); // 2.85714286em @ 16 & 0.875em
margin-right: @margin-end-search; margin-right: @margin-end-search;
// Support: IE 8, Firefox 18-, Chrome 19-, Safari 5.1-, Opera 19-, Android 4.4.4-. // Support: IE 8, Firefox 18-, Chrome 19-, Safari 5.1-, Opera 19-, Android 4.4.4-.
@ -45,10 +56,17 @@
min-width: @min-width-search-desktop; min-width: @min-width-search-desktop;
flex-basis: @min-width-search; flex-basis: @min-width-search;
&-form, > div {
.wvui-typeahead-search {
max-width: @max-width-search; max-width: @max-width-search;
} }
&.vector-search-box-show-thumbnail {
margin-left: unit( ( @margin-start-search - @size-search-expand ) / @font-size-browser / @font-size-base, em ); // 1.14285714em @ 16 & 0.875em
> div {
max-width: @max-width-search + unit( @size-search-expand / @font-size-browser / @font-size-base, em ); // 37.42857143em @ 16 & 0.875em
}
}
} }
} }
@ -75,15 +93,19 @@
margin-right: @margin-end-search; margin-right: @margin-end-search;
} }
// Increase the start margin of the search box to account for the input
// expanding on focus.
.vector-search-box-show-thumbnail {
margin-left: @size-search-expand + @padding-horizontal-tabs;
}
.wvui-typeahead-search__wrapper { .wvui-typeahead-search__wrapper {
position: static; position: static;
} }
// Position the start of suggestion list at the start of the input.
//
// FIXME: This can be removed when WVUI in core has been upgraded to use
// the `.wvui-typeahead-search--auto-expand-width` class.
.wvui-typeahead-search--show-thumbnail:not( .wvui-typeahead-search--auto-expand-width ) {
.wvui-typeahead-search__suggestions {
left: 0;
}
}
} }
} }
} }

View File

@ -101,6 +101,11 @@
} }
&.vector-header-search-toggled { &.vector-header-search-toggled {
// .wvui-input__input left padding (36px) - the .wvui-icon svg width (20px)
// - the icon left padding (12px [1]) = 4px
// [1] see .wvui-typeahead-search--show-thumbnail .wvui-input__input:focus)
@margin-start-search-box: 4px;
.vector-sticky-header-search-toggle, .vector-sticky-header-search-toggle,
.vector-sticky-header-context-bar { .vector-sticky-header-context-bar {
display: none; display: none;
@ -109,24 +114,27 @@
.vector-search-box { .vector-search-box {
display: block; display: block;
flex-basis: unit( 500px / @font-size-browser / @font-size-base, em ); flex-basis: unit( 500px / @font-size-browser / @font-size-base, em );
margin-left: @margin-start-search-box;
.wvui-typeahead-search {
// .wvui-input__input left padding (36px) - the .wvui-icon svg width (20px)
// - the icon left padding (12px [1]) = 4px
// [1] see .wvui-typeahead-search--show-thumbnail .wvui-input__input:focus)
margin-left: 4px;
}
} }
// T296318 Increase the start margin of the search box to account for the input // T296318 Decrease the start margin of the search box to account for the
// expanding on focus. // icon's increased start position when the search component has thumbnails.
.vector-search-box-show-thumbnail { .vector-search-box-show-thumbnail {
margin-left: @margin-end-search; margin-left: @margin-start-search-box - ( @size-search-expand / 2 );
.wvui-input__start-icon { .wvui-input__start-icon {
color: @colorGray2; color: @colorGray2;
} }
} }
// Allocate space for the extra width of the input when the search component
// has thumbnails.
//
// FIXME: This can be removed when WVUI in core has been upgraded
// to use the `.wvui-typeahead-search--full-width` class.
.wvui-typeahead-search--show-thumbnail:not( .wvui-typeahead-search--full-width ) {
margin-left: @size-search-expand;
}
} }
} }

View File

@ -81,7 +81,7 @@
bottom: 0; bottom: 0;
// Accounts for the 1px input border. Derived from // Accounts for the 1px input border. Derived from
// https://gerrit.wikimedia.org/g/wvui/+/refs/changes/93/650593/10/src/components/input/Input.vue#163 // https://gerrit.wikimedia.org/g/wvui/+/refs/changes/93/650593/10/src/components/input/Input.vue#163
left: 1px; left: @border-width-base;
// Increase size to match WVUI. // Increase size to match WVUI.
width: @size-search-figure; width: @size-search-figure;
} }
@ -93,13 +93,23 @@
} }
.vector-search-box-show-thumbnail { .vector-search-box-show-thumbnail {
.searchButton {
// Accounts for the margin that allocates space for the input expanding and
// 1px input border.
left: @size-search-expand + @border-width-base;
}
.vector-search-box-input {
margin-left: @size-search-expand;
width: ~'calc( 100% - @{size-search-expand} )';
}
// Recreate WVUI expanding input. // Recreate WVUI expanding input.
.vector-search-box-input:focus { .vector-search-box-input:focus {
position: relative; margin-left: 0;
// Use ~ and fixed values to disable the LESS transformation in ResourceLoader LESS implementation. // Use ~ and fixed values to disable the LESS transformation in ResourceLoader LESS implementation.
padding-left: ~'calc( @{size-search-figure} + @{size-search-expand} )'; padding-left: ~'calc( @{size-search-figure} + @{size-search-expand} )';
width: ~'calc( 100% + @{size-search-expand} )'; width: 100%;
left: ~'calc( -1 * @{size-search-expand} )';
} }
// Reposition search icon for expanded input. // Reposition search icon for expanded input.
@ -107,15 +117,8 @@
// Derived from // Derived from
// https://gerrit.wikimedia.org/g/wvui/+/refs/changes/93/650593/10/src/components/typeahead-search/TypeaheadSearch.vue#655 // https://gerrit.wikimedia.org/g/wvui/+/refs/changes/93/650593/10/src/components/typeahead-search/TypeaheadSearch.vue#655
// (12px of space between the border and the icon) with 1px to account for the focused input border. // (12px of space between the border and the icon) with 1px to account for the focused input border.
@space-icon-start: 12px; @space-icon-start: @size-search-expand / 2;
left: -@size-search-expand + @space-icon-start + @border-width-base; left: @space-icon-start + @border-width-base;
}
// Update search loader to match width and position of WVUI expanding input.
.vector-search-box-inner.search-form__loader:after {
width: ~'calc( 100% + @{size-search-expand} )';
left: ~'calc( -1 * @{size-search-expand} )';
padding-left: @size-search-expand;
} }
} }
} }