Merge "Collapse header at lower resolutions"

This commit is contained in:
jenkins-bot 2021-06-30 22:11:34 +00:00 committed by Gerrit Code Review
commit 6597bc7d86
15 changed files with 243 additions and 55 deletions

View File

@ -56,14 +56,8 @@
}
#pt-anonuserpage,
#pt-userpage a,
.vector-user-menu-legacy #pt-userpage a,
#p-new-personal-label {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAx0lEQVQ4jdXSzQmEQAwFYEuYUixhSwgkA8mQgKXYgS3YgXZgCZagHWgHuxf14t8osssGcv145CVJvjk+hBRFK2TrkK1D0cqHkN7CUBRI7L21KAqXMIDModiwD9oAkLlH0i3L+ooGiTWPAPPfJQTIHLGOB9h46YZnKS+3PI8PISW2GkV7FO2Jrb79h4+ODyElsYJYm437NSRWRCWdylgj++U0u+UAZI5E22hsWW03UWQtr2NT66zlCjz8uzNQbFiDN7F5/xB8aj57Ynp2FKI0bAAAAABJRU5ErkJggg==") !important;
background-repeat: no-repeat;
}
// Override user page icon styles for new user links
.vector-user-links #pt-userpage a {
background: none !important;
padding-left: 0;
}

View File

@ -111,6 +111,18 @@ class Hooks {
}
}
/**
* Updates the class on an existing item taking into account whether
* a class exists there already.
*
* @param array &$item
* @param string $newClass
*/
private static function appendClassToUserLink( &$item, $newClass ) {
$existingClass = $item['class'] ?? '';
$item['class'] = $existingClass . ' ' . $newClass;
}
/**
* Add icon class to an existing navigation item inside a menu hook.
* See self::onSkinTemplateNavigation.
@ -134,20 +146,28 @@ class Hooks {
* @param array &$content_navigation
*/
private static function updateUserLinksItems( $sk, &$content_navigation ) {
$COLLAPSE_MENU_ITEM_CLASS = 'user-links-collapsible-item';
// If the consolidate user links feature is enabled, rearrange some links in the personal toolbar.
if ( VectorServices::getFeatureManager()->isFeatureEnabled(
Constants::FEATURE_CONSOLIDATE_USER_LINKS )
) {
if ( $sk->loggedin ) {
// Remove user page from personal menu dropdown for logged in users.
unset( $content_navigation['user-menu']['userpage'] );
// Remove user page from personal menu dropdown for logged in users at higher resolutions.
self::appendClassToUserLink(
$content_navigation['user-menu']['userpage'],
$COLLAPSE_MENU_ITEM_CLASS
);
// Remove logout link from user-menu and recreate it in SkinVector,
unset( $content_navigation['user-menu']['logout'] );
} else {
// Remove "Not logged in" from personal menu dropdown for anon users.
unset( $content_navigation['user-menu']['anonuserpage'] );
// Create account is pulled out into its own button.
unset( $content_navigation['user-menu']['createaccount'] );
// Create account is pulled out into its own button and hidden at higher resolutions.
self::appendClassToUserLink(
$content_navigation['user-menu']['createaccount'],
$COLLAPSE_MENU_ITEM_CLASS
);
// "Login" link is handled manually by Vector
unset( $content_navigation['user-menu']['login'] );
}
@ -337,6 +357,14 @@ class Hooks {
$bodyAttrs['class'] .= ' skin-vector-search-vue';
}
if (
VectorServices::getFeatureManager()->isFeatureEnabled(
Constants::FEATURE_CONSOLIDATE_USER_LINKS
)
) {
$bodyAttrs['class'] .= ' skin-vector-consolidated-user-links';
}
$config = $sk->getConfig();
// Should we disable the max-width styling?
if ( !self::isSkinVersionLegacy() && $sk->getTitle() && self::shouldDisableMaxWidth(

View File

@ -239,9 +239,10 @@ class SkinVector extends SkinMustache {
* Returns template data for UserLinks.mustache
* @param array $menuData existing menu template data to be transformed and copied for UserLinks
* @param bool $isAnon if the user is logged out, used to conditionally provide data
* @param array $searchBoxData representing search box.
* @return array
*/
private function getUserLinksTemplateData( $menuData, $isAnon ) : array {
private function getUserLinksTemplateData( $menuData, $isAnon, $searchBoxData ) : array {
$returnto = $this->getReturnToParam();
$useCombinedLoginLink = $this->useCombinedLoginLink();
$htmlCreateAccount = $this->getCreateAccountHTML( $returnto );
@ -313,8 +314,6 @@ class SkinVector extends SkinMustache {
'sidebar-visible' => $this->isSidebarVisible(),
'is-language-in-header' => $this->isLanguagesInHeader(),
'should-search-expand' => $this->shouldSearchExpand(),
] );
if ( $skin->getUser()->isRegistered() ) {
@ -328,16 +327,53 @@ class SkinVector extends SkinMustache {
];
}
if ( $this->shouldConsolidateUserLinks() ) {
$shouldConsolidateUserLinks = $this->shouldConsolidateUserLinks();
if ( $shouldConsolidateUserLinks ) {
$commonSkinData['data-vector-user-links'] = $this->getUserLinksTemplateData(
$commonSkinData['data-portlets'],
$commonSkinData['is-anon']
$commonSkinData['is-anon'],
$commonSkinData['data-search-box']
);
}
$commonSkinData['data-search-box'] = $this->getSearchData(
$commonSkinData['data-search-box'],
$shouldConsolidateUserLinks
);
return $commonSkinData;
}
/**
* Annotates search box with Vector-specific information
*
* @param array $searchBoxData
* @param bool $shouldConsolidateUserLinks
* @return array modified version of $searchBoxData
*/
private function getSearchData( array $searchBoxData, bool $shouldConsolidateUserLinks ) {
$searchClass = 'vector-search-box';
if ( $shouldConsolidateUserLinks ) {
$searchClass .= ' vector-search-box-collapses';
}
if ( $this->shouldSearchExpand() ) {
$searchClass .= ' vector-search-box-show-thumbnail';
}
// Annotate search box with a component class.
$searchBoxData['class'] = $searchClass;
$searchBoxData['is-collapsible'] = $shouldConsolidateUserLinks;
// At lower resolutions the search input is hidden search and only the submit button is shown.
// It should behave like a form submit link (e.g. submit the form with no input value).
// We'll wire this up in a later task T284242.
$searchBoxData['href-search'] = Title::newFromText( $searchBoxData['page-title'] )->getLocalUrl();
return $searchBoxData;
}
/**
* Gets the value of the "input-location" parameter for the SearchBox Mustache template.
*

View File

@ -1,24 +1,32 @@
{{!
See @typedef SearchData
}}
<div id="p-search" role="search" {{#should-search-expand}}class="p-search--show-thumbnail"{{/should-search-expand}}>
<h3 {{{html-user-language-attributes}}}>
<label for="searchInput">{{msg-search}}</label>
</h3>
<form action="{{form-action}}" id="searchform">
<div id="simpleSearch"{{#input-location}} data-search-loc="{{.}}"{{/input-location}}>
{{{html-input}}}
<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).
* Browsers will use the 'fulltext' one by default (as it's the first in tree-order),
which is desirable when they are unable to show search suggestions (either due to being
broken or having JavaScript turned off).
* The mediawiki.searchSuggest module, after doing tests for the broken browsers, removes
the 'fulltext' button and handles 'fulltext' search itself; this will reveal the 'go'
button and cause it to be used. !}}
{{{html-button-search-fallback}}}
{{{html-button-search}}}
</div>
</form>
<div id="p-search" role="search" class="{{class}}">
<div>
<h3 {{{html-user-language-attributes}}}>
<label for="searchInput">{{msg-search}}</label>
</h3>
<form action="{{form-action}}" id="searchform">
<div id="simpleSearch"{{#input-location}} data-search-loc="{{.}}"{{/input-location}}>
{{{html-input}}}
<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).
* Browsers will use the 'fulltext' one by default (as it's the first in tree-order),
which is desirable when they are unable to show search suggestions (either due to being
broken or having JavaScript turned off).
* The mediawiki.searchSuggest module, after doing tests for the broken browsers, removes
the 'fulltext' button and handles 'fulltext' search itself; this will reveal the 'go'
button and cause it to be used. !}}
{{{html-button-search-fallback}}}
{{{html-button-search}}}
</div>
</form>
</div>
{{#is-collapsible}}
<a class="mw-ui-icon mw-ui-icon-wikimedia-search mw-ui-icon-element search-toggle"
href="{{href-search}}">
<span>{{msg-search}}</span>
</a>
{{/is-collapsible}}
</div>

View File

@ -94,3 +94,21 @@
background: no-repeat center/unit( 16 / @font-size-browser / @font-size-search-input, em ) url( images/search.svg );
opacity: 0.67;
}
.search-toggle {
// At lower resolutions the search input is hidden and a toggle is shown
display: block;
float: right;
@media ( min-width: @width-breakpoint-tablet ) {
display: none;
}
}
.vector-search-box-collapses > div {
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: block;
}
}

View File

@ -14,7 +14,7 @@
/* Icon for registered user names & anonymous message */
#pt-anonuserpage,
#pt-userpage a,
.vector-user-menu-legacy #pt-userpage a,
#p-personal-label {
background-image: url( images/user-avatar.svg );
background-repeat: no-repeat;

View File

@ -15,6 +15,12 @@
// This will be ignored in flexbox browsers.
float: left;
margin-right: 10px;
// Hide mobile icon at lower resolutions and defer to wordmark
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: block;
}
}
.mw-logo-container {
@ -22,6 +28,24 @@
// This will be ignored in flexbox browsers.
// The two children `div`s will lay out in a row.
float: left;
// At mobile resolutions restrict logo to 120px to optimize for a 340px display (@min-width-supported)
// (based on https://gs.statcounter.com/screen-resolution-stats/mobile/worldwide)
// This accounts for up to 5 icons
// (Echo notifications x 2, search, hamburger and personal menu)
// where the icons have 44px each (44x5 = 220px)
max-width: 120px;
img {
width: 100%;
}
@media ( min-width: @width-breakpoint-tablet ) {
max-width: none;
img {
width: auto;
}
}
}
// Note for 3rd parties where no wgLogos['wordmark'] is defined

View File

@ -5,6 +5,8 @@
align-items: center;
height: 30px;
position: relative;
justify-content: flex-end;
flex-shrink: 1;
// Overrides personal menu styles for consolidated user links.
.vector-user-menu {
@ -57,6 +59,12 @@
display: block;
color: #000;
text-decoration: none;
&.user-links-collapsible-item {
@media ( min-width: @width-breakpoint-tablet ) {
display: none;
}
}
}
}
@ -93,11 +101,18 @@
.mw-portlet-notifications {
li {
float: left;
margin-left: 0.75em;
margin-left: 0;
}
}
.mw-portlet-user-page {
// For logged-in users, below tablet threshold, the menu will collapse the user name/link to user page into the user menu
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: block;
}
li {
margin-left: 1em;
padding-bottom: 0.5em;
@ -112,6 +127,12 @@
.vector-user-links-createaccount {
margin-left: 0.75em;
// For logged-out users, below tablet threshold, the menu will collapse the create account link into the user menu
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: block;
}
}
// Adjust the user-interface-preferences menu.
@ -119,6 +140,14 @@
margin-top: -0.2em;
margin-right: 0;
padding: 0;
// The menu is collapsed into the p-personal menu at lower resolutions, because the features
// are accessible via Special:Preferences with a few more clicks and there is not space to
// accomodate this icon at this resolution.
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: block;
}
// Hide the heading of the user-interface-preferences menu.
h3 {

View File

@ -92,7 +92,9 @@
.transition( none );
}
.p-search--show-thumbnail {
// FIXME: .p-search--show-thumbnail selector is for cached HTML relating to T276566.
.p-search--show-thumbnail,
.vector-search-box-show-thumbnail {
// Recreate WVUI expanding input.
#searchInput:focus {
position: relative;

View File

@ -103,6 +103,7 @@
unit( 500px / @font-size-browser, em ) -
( 2 * @padding-horizontal-page-container );
// 31.25em - 3.75em = 27.5em @ 16
@min-width-supported-consolidated-links: unit( 340px / @font-size-browser, em );
// Width used to determine when to break the personal tools onto a separate line
// below the search box.
@ -159,20 +160,30 @@ body {
// allow z-index to apply so search results overlay article
position: relative;
z-index: @z-index-header;
.skin-vector-consolidated-user-links & {
flex-wrap: nowrap;
}
}
/* Searchbox */
#p-search {
float: left;
margin: 0 0 0 @margin-horizontal-search;
flex-grow: 1;
z-index: @z-index-menu;
flex-basis: @min-width-search;
flex-grow: 1;
.skin-vector-consolidated-user-links & {
margin: 0;
}
// #searchform is only a direct child of #p-search before wvui-loads. After
// wvui loads, `.wvui-typeahead-search` becomes the direct child and is the
// element where these styles should apply.
// FIXME: The first selector (> #searchform)
// is for cached HTML. Should be removed when T276566 has been in production.
> #searchform,
> div > #searchform,
.wvui-typeahead-search {
// Border-box sizing is used for a smooth transition from legacy to Vue
// search. The width of the container should stay the same before/after the
@ -296,10 +307,6 @@ body {
// Container logic.
.mw-page-container {
// Set a min-width to make explicit we do not support anything below this threshold.
// For devices too small, they should be more useable with horizontal scrolling.
// e.g. Portrait on an iPad
min-width: @min-width-supported;
max-width: @max-width-page-container;
// Fill the viewport even if the content height is small. This also helps
// mitigate a long sidebar overflowing the page container (T257518).
@ -310,6 +317,15 @@ body {
// Be careful not to use overflow-y: scroll here (see T270146 and T271868)
padding: 0.05px ( @padding-horizontal-page-container / 2 );
background-color: @background-color-page-container;
// Set a min-width to make explicit we do not support anything below this threshold.
// For devices too small, they should be more useable with horizontal scrolling.
// e.g. Portrait on an iPad
min-width: @min-width-supported;
// When consolidated user links is enabled, there is more space for compression.
.skin-vector-consolidated-user-links & {
min-width: @min-width-supported-consolidated-links;
}
}
.skin--responsive .mw-page-container {
@ -389,14 +405,6 @@ body {
}
@media ( max-width: @max-width-margin-start-content ) {
#p-search {
// Support: IE 8, Firefox 18-, Chrome 19-, Safari 5.1-, Opera 19-, Android 4.4.4-.
width: 13.2em;
// Support: Modern browsers, responsive width.
width: 20vw;
max-width: 100%;
}
// Adjusts the content and mw-article-toolbar-container.
.mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-content-container,
.mw-checkbox-hack-checkbox:checked ~ .mw-workspace-container .mw-article-toolbar-container {
@ -421,18 +429,34 @@ body {
// We use @width-comfortable to determine this threshold as we know it's not possible for
// personal tools to be on the same line at this resolution.
@media ( max-width: @width-comfortable ) {
// #searchform is only a direct child of #p-search before wvui-loads. After
// #searchform is only a direct child of #p-search > div before wvui-loads. After
// wvui loads, `.wvui-typeahead-search` becomes the direct child and is the
// element where these styles should apply.
/// FIXME: The first selector (#p-search > #searchform) is for cached HTML.
// Should be removed when T276566 has been in production for a week.
#p-search > #searchform,
#p-search > div > #searchform,
#p-search .wvui-typeahead-search {
margin-left: auto;
}
}
@media ( min-width: @width-breakpoint-tablet ) {
#p-search {
.mw-header {
flex-wrap: wrap;
}
#p-search,
.skin-vector-consolidated-user-links #p-search {
margin: 0 0 0 @margin-horizontal-search;
// Support: IE 8, Firefox 18-, Chrome 19-, Safari 5.1-, Opera 19-, Android 4.4.4-.
width: 13.2em;
// Support: Modern browsers, responsive width.
width: 20vw;
max-width: 100%;
min-width: @min-width-search-tablet;
flex-basis: @min-width-search;
flex-grow: 1;
}
.mw-page-container {

View File

@ -44,6 +44,7 @@
"vector-jumptonavigation",
"vector-jumptosearch",
"vector-jumptocontent",
"search",
"sitesubtitle",
"sitetitle",
"tagline"
@ -146,8 +147,10 @@
"variants": [],
"icons": [
"language",
"userAvatar",
"userTalk",
"markup",
"search",
"settings",
"labFlask",
"unStar",
@ -194,6 +197,7 @@
},
"ResourceModuleSkinStyles": {
"vector": {
"+ext.echo.styles.alert": "skinStyles/ext.echo.styles.alert.less",
"+ext.uls.compactlinks": "skinStyles/ext.uls.compactlinks.less",
"jquery.tipsy": "skinStyles/jquery.tipsy.less",
"jquery.ui": [

View File

@ -0,0 +1,16 @@
@import 'mediawiki.ui/variables.less';
// The "you have new messages" bar should be hidden at lower resolutions (temporary solution until T284243)
.vector-user-links {
#ca-talk-alert {
display: none;
@media ( min-width: @width-breakpoint-tablet ) {
display: inline-block;
}
}
#pt-notifications-alert {
margin-right: 0.75em;
}
}

View File

@ -3,6 +3,8 @@
// FIXME: With core set to 20x20 this file should become obsolete, see T191021.
@import '../resources/common/variables.less';
.vector-search-box .mw-ui-icon:before,
.vector-search-box .mw-ui-icon.mw-ui-icon-element:before,
.mw-portlet-lang .mw-ui-icon:before {
background-size: unit( @size-icon / @font-size-base, em ) auto;
width: unit( @size-icon / @font-size-base, em );

View File

@ -12,6 +12,7 @@ export { searchBoxTemplate };
*/
export const searchBoxData = {
'form-action': '/w/index.php',
class: 'vector-search-box vector-search-show-thumbnail',
'html-user-language-attributes': htmlUserLanguageAttributes,
'msg-search': 'Search',
'html-input': '<input type="search" name="search" placeholder="Search Wikipedia" title="Search Wikipedia [⌃⌥f]" accesskey="f" id="searchInput" autocomplete="off">',

View File

@ -42,6 +42,8 @@
* @property {string} [html-user-language-attributes]
* @property {string} form-action URL
* @property {string|null} html-input
* @property {boolean} [is-collapsible]
* @property {string|null} [class] of the menu
* @property {string|null} page-title the title of the search page
* @property {string|null} html-button-search-fallback
* @property {string|null} html-button-search