diff --git a/bundlesize.config.json b/bundlesize.config.json index e14d7ab3..102f49da 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -5,7 +5,7 @@ }, { "resourceModule": "skins.vector.styles", - "maxSize": "8.6 kB" + "maxSize": "8.7 kB" }, { "resourceModule": "skins.vector.icons", diff --git a/includes/Constants.php b/includes/Constants.php index 86ab1655..a394fda5 100644 --- a/includes/Constants.php +++ b/includes/Constants.php @@ -74,6 +74,11 @@ final class Constants { */ public const CONFIG_KEY_LAYOUT_MAX_WIDTH = 'VectorLayoutMaxWidth'; + /** + * @var string + */ + public const CONFIG_SEARCH_IN_HEADER = 'VectorIsSearchInHeader'; + /** * @var string */ diff --git a/includes/Hooks.php b/includes/Hooks.php index d4a984ce..f1b15606 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -276,6 +276,11 @@ class Hooks { if ( self::getConfig( Constants::CONFIG_KEY_LAYOUT_MAX_WIDTH ) ) { $bodyAttrs['class'] .= ' skin-vector-max-width'; } + if ( self::getConfig( Constants::CONFIG_SEARCH_IN_HEADER ) ) { + $bodyAttrs['class'] .= ' skin-vector-search-header'; + } else { + $bodyAttrs['class'] .= ' skin-vector-search-header-legacy'; + } } /** diff --git a/includes/SkinVector.php b/includes/SkinVector.php index af946bfc..adcdd2ed 100644 --- a/includes/SkinVector.php +++ b/includes/SkinVector.php @@ -131,6 +131,7 @@ class SkinVector extends SkinMustache { 'html-categories' => $skin->getCategories(), 'data-footer' => $this->getFooterData(), 'html-navigation-heading' => $skin->msg( 'navigation-heading' ), + 'is-search-in-header' => $this->getConfig()->get( Constants::CONFIG_SEARCH_IN_HEADER ), // Header 'data-logos' => ResourceLoaderSkinModule::getAvailableLogos( $this->getConfig() ), diff --git a/includes/templates/skin.mustache b/includes/templates/skin.mustache index 85abb3f0..8efa9808 100644 --- a/includes/templates/skin.mustache +++ b/includes/templates/skin.mustache @@ -85,12 +85,18 @@ {{#data-sidebar}}{{>Sidebar}}{{/data-sidebar}} {{>Logo}} + {{#is-search-in-header}} + {{#data-search-box}}{{>SearchBox}}{{/data-search-box}} + {{#data-personal-menu}}{{>Menu}}{{/data-personal-menu}} + {{/is-search-in-header}}

{{{html-navigation-heading}}}

+ {{^is-search-in-header}} {{#data-personal-menu}}{{>Menu}}{{/data-personal-menu}} + {{/is-search-in-header}}
{{#data-namespace-tabs}}{{>Menu}}{{/data-namespace-tabs}} @@ -99,7 +105,9 @@
{{#data-page-actions}}{{>Menu}}{{/data-page-actions}} {{#data-page-actions-more}}{{>Menu}}{{/data-page-actions-more}} + {{^is-search-in-header}} {{#data-search-box}}{{>SearchBox}}{{/data-search-box}} + {{/is-search-in-header}}
diff --git a/resources/skins.vector.styles/layout-default.less b/resources/skins.vector.styles/layout-default.less index ee8d5494..9e08711e 100644 --- a/resources/skins.vector.styles/layout-default.less +++ b/resources/skins.vector.styles/layout-default.less @@ -116,7 +116,11 @@ body { margin-top: @height-header; } -#p-personal { +// FIXME: Remove the body:not selector when +// skin-vector-search-header-legacy class is available in cached HTML +// i.e. deploy after I7f8059d43eaab49de362405784b34a4fe502c7b0 lands. +body:not( .skin-vector-search-header ) #p-personal, +.skin-vector-search-header-legacy #p-personal { position: absolute; top: @top-personal-tools; right: 0.75em; @@ -128,7 +132,9 @@ body { // As a result it is possible for the personal tools to overlap the logo. padding-left: @width-grid-column-one; } +} +#p-personal { li { display: inline-block; } diff --git a/resources/skins.vector.styles/layout-max-width.less b/resources/skins.vector.styles/layout-max-width.less index 0258cd65..126fdbf8 100644 --- a/resources/skins.vector.styles/layout-max-width.less +++ b/resources/skins.vector.styles/layout-max-width.less @@ -174,6 +174,13 @@ } } + &.skin-vector-search-header { + // 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; + } + // We want it to appear like the sidebar is going into/coming out of // `.mw-page-container`, but we can't use `overflow: hidden` on // `.mw-page-container` because that will cut off the sidebar. Therefore, we diff --git a/resources/skins.vector.styles/layout-search-header.less b/resources/skins.vector.styles/layout-search-header.less new file mode 100644 index 00000000..c81f7497 --- /dev/null +++ b/resources/skins.vector.styles/layout-search-header.less @@ -0,0 +1,107 @@ +// This assumes the presence of variables inside layout.less. DO NOT import it separately. +// Assumes various variables defined there. + +@min-width-search: unit( 350px / @font-size-browser, em ); +@max-width-search: unit( 580px / @font-size-browser, em ); + +// The logo is variable width but typically consists of: +// - a icon (50x50) +// - a wordmark (approx 120px) +@min-width-logo: unit( 170px / @font-size-browser, em ); + +@min-width-personal-tools: @max-width-search; + +@padding-horizontal-page-container: 30px; +@padding-horizontal-page-container-ems: unit( @padding-horizontal-page-container / @font-size-browser, em ); + +@min-width-supported: @width-grid-column-one + @min-width-personal-tools + ( @padding-horizontal-page-container-ems * 2 ); +@width-comfortable: @min-width-logo + @size-sidebar-button + @min-width-search + @min-width-personal-tools; + +@height-personal-tools: 2em; + +.skin-vector-search-header { + + // Header components + #p-search { + // Override values to reflect new behaviour. + min-width: @min-width-search; + max-width: @max-width-search; + margin: 0 40px; + } + + // Support IE9: float will be disabled if display flex is supported + #p-search, + #mw-sidebar-button { + float: left; + } + + #p-personal { + text-align: right; + + // Support IE9: This is reset in @support query below if Flexbox is available. + float: right; + } + + // If we don't have the space adjust header. + // Increase height and margins to accommodate personal tools underneath. + @media ( max-width: @width-comfortable ) { + @height-header-adjusted: @height-header + @height-personal-tools; + + #mw-panel { + top: @height-header-adjusted - @margin-top-header; + } + + .mw-header-placeholder { + height: @height-header-adjusted + @height-tabs; + } + + #left-navigation { + margin-top: @height-header-adjusted; + margin-bottom: 0; + } + + #right-navigation { + margin-top: -@height-tabs; + clear: left; + } + } +} + +// when max-width is also enabled... +.skin-vector-search-header.skin-vector-max-width { + #left-navigation { + margin-top: 0; + } + + .mw-article-toolbar-container { + margin-top: @height-header + @height-personal-tools; + } + + @media ( min-width: @width-comfortable ) { + .mw-article-toolbar-container { + margin-top: @height-header; + } + } +} + +// If flexbox supported reset the floats that are supporting IE9 +// When IE9 is no longer supported this entire query can be dropped. +@supports ( display: flex ) { + .skin-vector-search-header { + .mw-header { + flex-wrap: wrap; + } + + #p-personal, + #p-search { + flex-grow: 1; + // Disable the float: left rule for IE9 support + float: none; + } + + #mw-sidebar-button { + // Disable the float: left rule for IE9 support + float: none; + } + } +} diff --git a/resources/skins.vector.styles/layout.less b/resources/skins.vector.styles/layout.less index a3f2e77d..00e48388 100644 --- a/resources/skins.vector.styles/layout.less +++ b/resources/skins.vector.styles/layout.less @@ -28,3 +28,4 @@ // Feature flag modifications to layout (additive) // @import 'layout-max-width.less'; +@import 'layout-search-header.less'; diff --git a/skin.json b/skin.json index 55f6d095..08786fc4 100644 --- a/skin.json +++ b/skin.json @@ -194,6 +194,9 @@ "VectorUseCoreSearch": { "value": true }, + "VectorIsSearchInHeader": { + "value": false + }, "VectorDefaultSidebarVisibleForAuthorisedUser": { "value": true },