mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-24 07:43:47 +00:00
Merge "Wire up sticky header search feature"
This commit is contained in:
commit
20135a348e
|
@ -87,3 +87,10 @@
|
|||
.vector-user-menu-legacy #pt-userpage a {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAx0lEQVQ4jdXSzQmEQAwFYEuYUixhSwgkA8mQgKXYgS3YgXZgCZagHWgHuxf14t8osssGcv145CVJvjk+hBRFK2TrkK1D0cqHkN7CUBRI7L21KAqXMIDModiwD9oAkLlH0i3L+ooGiTWPAPPfJQTIHLGOB9h46YZnKS+3PI8PISW2GkV7FO2Jrb79h4+ODyElsYJYm437NSRWRCWdylgj++U0u+UAZI5E22hsWW03UWQtr2NT66zlCjz8uzNQbFiDN7F5/xB8aj57Ynp2FKI0bAAAAABJRU5ErkJggg==") !important;
|
||||
}
|
||||
|
||||
.mw-ui-icon-wikimedia-speechBubbles:before {
|
||||
background-image: linear-gradient(transparent, transparent), url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3Espeech bubbles%3C/title%3E%3Cg fill=%22%23000%22%3E%3Cpath d=%22M17 4v7a2 2 0 01-2 2H4v1a2 2 0 002 2h10l4 4V6a2 2 0 00-2-2zM6 10H0v6z%22/%3E%3Crect width=%2216%22 height=%2212%22 rx=%222%22/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
.mw-ui-icon-wikimedia-history:before {
|
||||
background-image: linear-gradient(transparent, transparent), url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%2220%22 height=%2220%22 viewBox=%220 0 20 20%22%3E%3Ctitle%3Ehistory%3C/title%3E%3Cg fill=%22%23000%22%3E%3Cpath d=%22M9 6v5h.06l2.48 2.47 1.41-1.41L11 10.11V6z%22/%3E%3Cpath d=%22M10 1a9 9 0 00-7.85 13.35L.5 16H6v-5.5l-2.38 2.38A7 7 0 1110 17v2a9 9 0 000-18z%22/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
|
|
|
@ -326,21 +326,19 @@ class SkinVector extends SkinMustache {
|
|||
/**
|
||||
* Generate data needed to generate the sticky header.
|
||||
* Lack of i18n is intentional and will be done as part of follow up work.
|
||||
* @param array $searchBoxData
|
||||
* @return array
|
||||
*/
|
||||
private function getStickyHeaderData() {
|
||||
private function getStickyHeaderData( $searchBoxData ) {
|
||||
return [
|
||||
'data-primary-action' => !$this->shouldHideLanguages() ? $this->getULSButtonData() : null,
|
||||
'data-button-start' => [
|
||||
'href' => '#p-search',
|
||||
'label' => $this->msg( 'search' ),
|
||||
'icon' => 'wikimedia-search',
|
||||
'is-quiet' => true,
|
||||
'class' => 'vector-sticky-header-search-toggle',
|
||||
],
|
||||
'data-search' => [
|
||||
'class' => $this->shouldSearchExpand() ? self::SEARCH_EXPANDING_CLASS : '',
|
||||
],
|
||||
'data-search' => $searchBoxData,
|
||||
'data-buttons' => [
|
||||
self::TALK_ICON, self::HISTORY_ICON, self::NO_ICON, self::NO_ICON
|
||||
]
|
||||
|
@ -382,9 +380,24 @@ class SkinVector extends SkinMustache {
|
|||
|
||||
'is-language-in-header' => $this->isLanguagesInHeader(),
|
||||
|
||||
'data-search-box' => $this->getSearchData(
|
||||
$parentData['data-search-box'],
|
||||
!$this->isLegacy(),
|
||||
// is primary mode of search
|
||||
true,
|
||||
'searchform'
|
||||
),
|
||||
'data-vector-sticky-header' => VectorServices::getFeatureManager()->isFeatureEnabled(
|
||||
Constants::FEATURE_STICKY_HEADER
|
||||
) ? $this->getStickyHeaderData() : false,
|
||||
) ? $this->getStickyHeaderData(
|
||||
$this->getSearchData(
|
||||
$parentData['data-search-box'],
|
||||
// Collapse inside search box is disabled.
|
||||
false,
|
||||
false,
|
||||
'vector-sticky-search-form'
|
||||
)
|
||||
) : false,
|
||||
] );
|
||||
|
||||
if ( $skin->getUser()->isRegistered() ) {
|
||||
|
@ -406,13 +419,6 @@ class SkinVector extends SkinMustache {
|
|||
);
|
||||
}
|
||||
|
||||
$commonSkinData['data-search-box'] = $this->getSearchData(
|
||||
$commonSkinData['data-search-box'],
|
||||
!$this->isLegacy(),
|
||||
true,
|
||||
'searchform'
|
||||
);
|
||||
|
||||
return $commonSkinData;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,12 @@
|
|||
class="vector-search-box-inner"
|
||||
{{#input-location}} data-search-loc="{{.}}"{{/input-location}}>
|
||||
<input class="vector-search-box-input"
|
||||
{{{html-input-attributes}}} {{#is-primary}}id="searchInput"{{/is-primary}} />
|
||||
{{#is-primary}}{{{html-input-attributes}}} id="searchInput"{{/is-primary}}
|
||||
{{^is-primary}}
|
||||
type="search" name="search"
|
||||
placeholder="{{msg-searchsuggest-search}}"
|
||||
{{/is-primary}}
|
||||
/>
|
||||
<input type="hidden" name="title" value="{{page-title}}"/>
|
||||
{{! We construct two buttons (for 'go' and 'fulltext' search modes), but only one will be
|
||||
visible and actionable at a time (they are overlaid on top of each other in CSS).
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
{{/data-button-start}}
|
||||
</div>
|
||||
{{#data-search}}
|
||||
<div class="vector-search-box {{class}}">
|
||||
<div class="vector-secondary-search" id="vector-sticky-header-search"></div>
|
||||
</div>
|
||||
{{>SearchBox}}
|
||||
{{/data-search}}
|
||||
<div class="vector-sticky-header-context-bar">
|
||||
<div class="vector-sticky-header-context-bar-primary">{{html-title}}</div>
|
||||
|
|
|
@ -23,7 +23,6 @@ var /** @type {VectorResourceLoaderVirtualConfig} */
|
|||
LOAD_START_MARK = 'mwVectorVueSearchLoadStart',
|
||||
LOAD_END_MARK = 'mwVectorVueSearchLoadEnd',
|
||||
LOAD_MEASURE = 'mwVectorVueSearchLoadStartToLoadEnd',
|
||||
SEARCH_INPUT_ID = 'searchInput',
|
||||
SEARCH_LOADING_CLASS = 'search-form__loader';
|
||||
|
||||
/**
|
||||
|
@ -75,8 +74,8 @@ function renderSearchLoadingIndicator( event ) {
|
|||
|
||||
if (
|
||||
!( event.currentTarget instanceof HTMLElement ) ||
|
||||
!( event.target instanceof HTMLInputElement ) ||
|
||||
!( input.id === SEARCH_INPUT_ID ) ) {
|
||||
!( event.target instanceof HTMLInputElement )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -177,6 +176,14 @@ function initSearchLoader( document ) {
|
|||
searchBoxes.forEach( function ( searchBox ) {
|
||||
var searchInner = searchBox.querySelector( 'form > div' ),
|
||||
searchInput = searchBox.querySelector( 'input[name="search"]' ),
|
||||
clearLoadingIndicators = function () {
|
||||
setLoadingIndicatorListeners(
|
||||
// @ts-ignore
|
||||
searchInner,
|
||||
false,
|
||||
renderSearchLoadingIndicator
|
||||
);
|
||||
},
|
||||
isPrimarySearch = searchInput && searchInput.getAttribute( 'id' ) === 'searchInput';
|
||||
|
||||
if ( !searchInput || !searchInner ) {
|
||||
|
@ -190,15 +197,12 @@ function initSearchLoader( document ) {
|
|||
searchInput,
|
||||
'skins.vector.search',
|
||||
isPrimarySearch ? LOAD_START_MARK : null,
|
||||
// Make sure we clearLoadingIndicators so that event listeners are removed.
|
||||
// Note, loading Vue.js will remove the element from the DOM.
|
||||
isPrimarySearch ? function () {
|
||||
markLoadEnd( LOAD_START_MARK, LOAD_END_MARK, LOAD_MEASURE );
|
||||
setLoadingIndicatorListeners(
|
||||
// @ts-ignore
|
||||
searchInner,
|
||||
false,
|
||||
renderSearchLoadingIndicator
|
||||
);
|
||||
} : null
|
||||
clearLoadingIndicators();
|
||||
} : clearLoadingIndicators
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
var
|
||||
STICKY_HEADER_ID = 'vector-sticky-header',
|
||||
initSearchToggle = require( './searchToggle.js' ),
|
||||
STICKY_HEADER_APPENDED_ID = '-sticky-header',
|
||||
STICKY_HEADER_VISIBLE_CLASS = 'vector-sticky-header-visible',
|
||||
STICKY_HEADER_USER_MENU_CONTAINER_CLASS = 'vector-sticky-header-icon-end',
|
||||
|
@ -145,14 +146,7 @@ function setupSearchIfNeeded( header ) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Load the `skins.vector.search` module here or setup an event handler to
|
||||
// load it depending on the outcome of T289718. After it loads, initialize the
|
||||
// search toggle.
|
||||
//
|
||||
// Example:
|
||||
// mw.loader.using( 'skins.vector.search', function () {
|
||||
// initSearchToggle( searchToggle );
|
||||
// } );
|
||||
initSearchToggle( searchToggle );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
// Hide any open menus/search results unless sticky header is visible
|
||||
&:not( .vector-sticky-header-visible ) > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-visible {
|
||||
transform: translateY( 0% );
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"search",
|
||||
"searchbutton",
|
||||
"searcharticle",
|
||||
"searchsuggest-search",
|
||||
"sitesubtitle",
|
||||
"sitetitle",
|
||||
"tagline"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import template from '!!raw-loader!../includes/templates/StickyHeader.mustache';
|
||||
import Button from '!!raw-loader!../includes/templates/Button.mustache';
|
||||
import { searchBoxData } from './SearchBox.stories.data';
|
||||
|
||||
const NO_ICON = {
|
||||
icon: 'none',
|
||||
|
@ -7,6 +8,18 @@ const NO_ICON = {
|
|||
class: 'sticky-header-icon'
|
||||
};
|
||||
|
||||
const TALK_ICON = {
|
||||
icon: 'none',
|
||||
'is-quiet': true,
|
||||
class: 'sticky-header-icon mw-ui-icon-wikimedia-speechBubbles'
|
||||
};
|
||||
|
||||
const HISTORY_ICON = {
|
||||
icon: 'none',
|
||||
'is-quiet': true,
|
||||
class: 'sticky-header-icon mw-ui-icon-wikimedia-history'
|
||||
};
|
||||
|
||||
const data = {
|
||||
title: 'Audre Lorde',
|
||||
heading: 'Introduction',
|
||||
|
@ -18,19 +31,16 @@ const data = {
|
|||
label: '196 languages',
|
||||
'html-vector-button-icon': `<span class="mw-ui-icon mw-ui-icon-wikimedia-language"></span>`
|
||||
},
|
||||
'data-search': {
|
||||
class: ''
|
||||
},
|
||||
'data-search': searchBoxData,
|
||||
'data-button-start': {
|
||||
icon: 'wikimedia-search',
|
||||
href: '#',
|
||||
class: 'search-toggle',
|
||||
class: 'vector-sticky-header-search-toggle',
|
||||
'is-quiet': true,
|
||||
label: 'Search'
|
||||
},
|
||||
'data-button-end': NO_ICON,
|
||||
'data-buttons': [
|
||||
NO_ICON, NO_ICON, NO_ICON, NO_ICON
|
||||
TALK_ICON, HISTORY_ICON, NO_ICON, NO_ICON
|
||||
]
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue