Merge "Refactor search component expand behavior and add auto-expand-width prop to search component"
This commit is contained in:
commit
42fec59f54
|
@ -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 ) &&
|
||||||
|
|
|
@ -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 () {
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue