[IMP] website: partially hide content in headers on scroll
Following the redesign of website template headers, this commit introduces a new class `.o_header_hide_on_scroll` to hide some part of the header when scrolling. task-3474743 Part-of: odoo/odoo#119650
This commit is contained in:
committed by
qsm-odoo
parent
5cf32b489f
commit
143d475c3a
@@ -6,6 +6,10 @@ export const extraMenuUpdateCallbacks = [];
|
||||
import dom from "@web/legacy/js/core/dom";
|
||||
import { SIZES, utils as uiUtils } from "@web/core/ui/ui_service";
|
||||
|
||||
// The header height may vary with sections hidden on scroll (see the class
|
||||
// `o_header_hide_on_scroll`). To avoid scroll jumps, we cache the value.
|
||||
let headerHeight;
|
||||
|
||||
const BaseAnimatedHeader = animations.Animation.extend({
|
||||
disabledInEditableMode: false,
|
||||
effects: [{
|
||||
@@ -35,6 +39,7 @@ const BaseAnimatedHeader = animations.Animation.extend({
|
||||
this.$main = this.$el.next('main');
|
||||
this.isOverlayHeader = !!this.$el.closest('.o_header_overlay, .o_header_overlay_theme').length;
|
||||
this.$dropdowns = this.$el.find('.dropdown, .dropdown-menu');
|
||||
this.hiddenOnScrollEl = this.el.querySelector(".o_header_hide_on_scroll");
|
||||
this.$navbarCollapses = this.$el.find('.navbar-collapse');
|
||||
|
||||
// While scrolling through navbar menus on medium devices, body should not be scrolled with it
|
||||
@@ -164,13 +169,13 @@ const BaseAnimatedHeader = animations.Animation.extend({
|
||||
* @private
|
||||
*/
|
||||
_updateMainPaddingTop: function () {
|
||||
this.headerHeight = this.$el.outerHeight();
|
||||
headerHeight ||= this.el.getBoundingClientRect().height;
|
||||
this.topGap = this._computeTopGap();
|
||||
|
||||
if (this.isOverlayHeader) {
|
||||
return;
|
||||
}
|
||||
this.$main.css('padding-top', this.fixedHeader ? this.headerHeight : '');
|
||||
this.$main.css('padding-top', this.fixedHeader ? headerHeight : '');
|
||||
},
|
||||
/**
|
||||
* Checks if the size of the header will decrease by adding the
|
||||
@@ -196,7 +201,7 @@ const BaseAnimatedHeader = animations.Animation.extend({
|
||||
clonedHeader.classList.add('o_header_is_scrolled', 'o_header_affixed', 'o_header_no_transition');
|
||||
const endHeaderHeight = clonedHeader.offsetHeight;
|
||||
clonedHeader.remove();
|
||||
const heightDiff = this.headerHeight - endHeaderHeight;
|
||||
const heightDiff = headerHeight - endHeaderHeight;
|
||||
return heightDiff > 0 ? remainingScroll <= heightDiff : false;
|
||||
},
|
||||
|
||||
@@ -273,7 +278,7 @@ publicWidget.registry.StandardAffixedHeader = BaseAnimatedHeader.extend({
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.headerHeight = this.$el.outerHeight();
|
||||
headerHeight ||= this.el.getBoundingClientRect().height;
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
@@ -303,7 +308,7 @@ publicWidget.registry.StandardAffixedHeader = BaseAnimatedHeader.extend({
|
||||
_updateHeaderOnScroll: function (scroll) {
|
||||
this._super(...arguments);
|
||||
|
||||
const mainPosScrolled = (scroll > this.headerHeight + this.topGap);
|
||||
const mainPosScrolled = (scroll > headerHeight + this.topGap);
|
||||
const reachPosScrolled = (scroll > this.scrolledPoint + this.topGap) && !this.scrollHeightTooShort;
|
||||
const fixedUpdate = (this.fixedHeader !== mainPosScrolled);
|
||||
const showUpdate = (this.fixedHeaderShow !== reachPosScrolled);
|
||||
@@ -319,6 +324,7 @@ publicWidget.registry.StandardAffixedHeader = BaseAnimatedHeader.extend({
|
||||
}
|
||||
|
||||
this.fixedHeaderShow = reachPosScrolled;
|
||||
this.hiddenOnScrollEl?.classList.toggle("hidden", mainPosScrolled);
|
||||
|
||||
if (fixedUpdate) {
|
||||
this._toggleFixedHeader(mainPosScrolled);
|
||||
@@ -353,6 +359,28 @@ publicWidget.registry.FixedHeader = BaseAnimatedHeader.extend({
|
||||
void this.$el[0].offsetWidth; // Force a paint refresh
|
||||
this.$el.css('transform', '');
|
||||
}
|
||||
|
||||
if (this.hiddenOnScrollEl) {
|
||||
const scrollDelta = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches ?
|
||||
scroll : Math.floor(scroll / 4);
|
||||
const elHeight = Math.max(0, this.hiddenOnScrollEl.scrollHeight - scrollDelta);
|
||||
this.hiddenOnScrollEl.classList.toggle("hidden", elHeight === 0);
|
||||
if (elHeight === 0) {
|
||||
this.hiddenOnScrollEl.removeAttribute("style");
|
||||
} else {
|
||||
this.hiddenOnScrollEl.style.overflow = "hidden";
|
||||
this.hiddenOnScrollEl.style.height = `${elHeight}px`;
|
||||
let elPadding = parseInt(getComputedStyle(this.hiddenOnScrollEl).paddingBlock);
|
||||
if (elHeight < elPadding * 2) {
|
||||
const heightDifference = elPadding * 2 - elHeight;
|
||||
elPadding = Math.max(0, elPadding - Math.floor(heightDifference / 2));
|
||||
this.hiddenOnScrollEl.style
|
||||
.setProperty("padding-block", `${elPadding}px`, "important");
|
||||
} else {
|
||||
this.hiddenOnScrollEl.style.paddingBlock = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -988,6 +988,12 @@ $-transition-duration: 200ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_header_hide_on_scroll.hidden {
|
||||
max-height: 0;
|
||||
padding-block: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.o_hoverable_dropdown .nav-link.dropdown-toggle:focus {
|
||||
|
||||
@@ -725,8 +725,8 @@
|
||||
<t t-call="website.navbar">
|
||||
<t t-set="_navbar_classes" t-valuef="d-none d-lg-block pt-3 shadow-sm"/>
|
||||
|
||||
<div id="o_main_nav" class="container flex-wrap gap-3">
|
||||
<div class="d-grid align-items-center w-100 o_grid_header_3_cols">
|
||||
<div id="o_main_nav" class="container flex-wrap">
|
||||
<div class="o_header_hide_on_scroll d-grid align-items-center w-100 o_grid_header_3_cols pb-3">
|
||||
<ul class="navbar-nav align-items-center gap-1">
|
||||
<!-- Search bar -->
|
||||
<t t-call="website.placeholder_header_search_box">
|
||||
@@ -797,7 +797,7 @@
|
||||
<t t-set="_navbar_classes" t-valuef="d-none d-lg-block p-0 shadow-sm"/>
|
||||
|
||||
<div id="o_main_nav" class="flex-wrap">
|
||||
<div aria-label="Top" class="border-bottom o_border_contrast">
|
||||
<div aria-label="Top" class="o_header_hide_on_scroll border-bottom o_border_contrast">
|
||||
<div class="container d-flex justify-content-between flex-wrap w-100">
|
||||
<ul class="o_header_search_left_col navbar-nav flex-wrap">
|
||||
<!-- Language Selector -->
|
||||
@@ -952,7 +952,7 @@
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div aria-label="Bottom" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links')" class="o_header_sales_one_bot gap-3 py-2">
|
||||
<div aria-label="Bottom" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links')" class="o_header_sales_one_bot o_header_hide_on_scroll gap-3 py-2">
|
||||
<ul class="navbar-nav container justify-content-between align-items-center">
|
||||
<!-- Text element -->
|
||||
<t t-call="website.placeholder_header_text_element">
|
||||
@@ -993,57 +993,59 @@
|
||||
<t t-set="_navbar_classes" t-valuef="d-none d-lg-block p-0 shadow-sm"/>
|
||||
|
||||
<div id="o_main_nav">
|
||||
<div aria-label="Top" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links') or is_view_active('website.header_language_selector')" class="o_header_sales_two_top py-1">
|
||||
<ul class="navbar-nav container d-grid h-100 px-3 o_grid_header_3_cols">
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_lang_selector_placeholder" t-if="is_view_active('website.header_language_selector') == False"/>
|
||||
<!-- Language Selector -->
|
||||
<t t-call="website.placeholder_header_language_selector">
|
||||
<t t-set="_div_classes" t-valuef="d-flex align-items-center h-100"/>
|
||||
<t t-set="_btn_class" t-valuef="btn-sm btn-outline-secondary border-0"/>
|
||||
<div class="o_header_hide_on_scroll">
|
||||
<div aria-label="Top" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links') or is_view_active('website.header_language_selector')" class="o_header_sales_two_top py-1">
|
||||
<ul class="navbar-nav container d-grid h-100 px-3 o_grid_header_3_cols">
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_lang_selector_placeholder" t-if="is_view_active('website.header_language_selector') == False"/>
|
||||
<!-- Language Selector -->
|
||||
<t t-call="website.placeholder_header_language_selector">
|
||||
<t t-set="_div_classes" t-valuef="d-flex align-items-center h-100"/>
|
||||
<t t-set="_btn_class" t-valuef="btn-sm btn-outline-secondary border-0"/>
|
||||
</t>
|
||||
<!-- Text element -->
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_txt_elts_placeholder" t-if="is_view_active('website.header_text_element') == False"/>
|
||||
<t t-call="website.placeholder_header_text_element">
|
||||
<t t-set="_txt_elt_content" t-valuef="sentence"/>
|
||||
<t t-set="_div_class" t-valuef="d-flex align-items-center mx-auto"/>
|
||||
<t t-set="_item_class" t-valuef="d-flex align-items-center"/>
|
||||
</t>
|
||||
<!-- Social -->
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_social_links_placeholder" t-if="is_view_active('website.header_social_links') == False"/>
|
||||
<t t-call="website.header_social_links_no_color">
|
||||
<t t-set="_div_class" t-valuef="d-flex align-items-center justify-content-end h-100"/>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div aria-label="Middle" class="container d-flex justify-content-between align-items-center py-1">
|
||||
<!-- Brand -->
|
||||
<t t-call="website.placeholder_header_brand">
|
||||
<t t-set="_link_class" t-valuef="me-4"/>
|
||||
</t>
|
||||
<!-- Text element -->
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_txt_elts_placeholder" t-if="is_view_active('website.header_text_element') == False"/>
|
||||
<t t-call="website.placeholder_header_text_element">
|
||||
<t t-set="_txt_elt_content" t-valuef="sentence"/>
|
||||
<t t-set="_div_class" t-valuef="d-flex align-items-center mx-auto"/>
|
||||
<t t-set="_item_class" t-valuef="d-flex align-items-center"/>
|
||||
</t>
|
||||
<!-- Social -->
|
||||
<!-- Return empty placeholder if the element is not active to keep the right layout -->
|
||||
<li class="o_header_sales_two_social_links_placeholder" t-if="is_view_active('website.header_social_links') == False"/>
|
||||
<t t-call="website.header_social_links_no_color">
|
||||
<t t-set="_div_class" t-valuef="d-flex align-items-center justify-content-end h-100"/>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div aria-label="Middle" class="container d-flex justify-content-between align-items-center py-1">
|
||||
<!-- Brand -->
|
||||
<t t-call="website.placeholder_header_brand">
|
||||
<t t-set="_link_class" t-valuef="me-4"/>
|
||||
</t>
|
||||
<ul class="navbar-nav align-items-center gap-1">
|
||||
<!-- Search bar -->
|
||||
<t t-call="website.placeholder_header_search_box">
|
||||
<t t-set="_input_classes" t-valuef="rounded-start-pill ps-3 text-bg-light"/>
|
||||
<t t-set="_submit_classes" t-valuef="rounded-end-pill p-3 bg-o-color-3 lh-1"/>
|
||||
</t>
|
||||
<!-- Sign In -->
|
||||
<t t-call="portal.placeholder_user_sign_in">
|
||||
<t t-set="_link_class" t-valuef="btn btn-outline-secondary"/>
|
||||
</t>
|
||||
<!-- User Dropdown -->
|
||||
<t t-call="portal.user_dropdown">
|
||||
<t t-set="_user_name" t-value="true"/>
|
||||
<t t-set="_icon" t-value="true"/>
|
||||
<t t-set="_icon_class" t-valuef="fa-stack"/>
|
||||
<t t-set="_item_class" t-valuef="dropdown"/>
|
||||
<t t-set="_link_class" t-valuef="d-flex align-items-center border-0 fw-bold text-reset o_navlink_background_hover"/>
|
||||
<t t-set="_icon_wrap_class" t-value="'position-relative me-2 rounded-circle border p-2 bg-o-color-3'"/>
|
||||
<t t-set="_dropdown_menu_class" t-valuef="dropdown-menu-end"/>
|
||||
</t>
|
||||
</ul>
|
||||
<ul class="navbar-nav align-items-center gap-1">
|
||||
<!-- Search bar -->
|
||||
<t t-call="website.placeholder_header_search_box">
|
||||
<t t-set="_input_classes" t-valuef="rounded-start-pill ps-3 text-bg-light"/>
|
||||
<t t-set="_submit_classes" t-valuef="rounded-end-pill p-3 bg-o-color-3 lh-1"/>
|
||||
</t>
|
||||
<!-- Sign In -->
|
||||
<t t-call="portal.placeholder_user_sign_in">
|
||||
<t t-set="_link_class" t-valuef="btn btn-outline-secondary"/>
|
||||
</t>
|
||||
<!-- User Dropdown -->
|
||||
<t t-call="portal.user_dropdown">
|
||||
<t t-set="_user_name" t-value="true"/>
|
||||
<t t-set="_icon" t-value="true"/>
|
||||
<t t-set="_icon_class" t-valuef="fa-stack"/>
|
||||
<t t-set="_item_class" t-valuef="dropdown"/>
|
||||
<t t-set="_link_class" t-valuef="d-flex align-items-center border-0 fw-bold text-reset o_navlink_background_hover"/>
|
||||
<t t-set="_icon_wrap_class" t-value="'position-relative me-2 p-2 rounded-circle border bg-o-color-3'"/>
|
||||
<t t-set="_dropdown_menu_class" t-valuef="dropdown-menu-end"/>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div aria-label="Bottom" class="border-top o_border_contrast">
|
||||
<div class="container d-flex justify-content-between">
|
||||
@@ -1094,7 +1096,8 @@
|
||||
<t t-set="_navbar_classes" t-valuef="d-none d-lg-block p-0 shadow-sm"/>
|
||||
|
||||
<div id="o_main_nav">
|
||||
<div aria-label="Top" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links') or is_view_active('website.header_search_box') or is_view_active('website.header_call_to_action')" class="o_header_sales_three_top position-relative border-bottom z-index-1 o_border_contrast">
|
||||
<div aria-label="Top" t-if="is_view_active('website.header_text_element') or is_view_active('website.header_social_links') or is_view_active('website.header_search_box') or is_view_active('website.header_call_to_action')"
|
||||
class="o_header_sales_three_top o_header_hide_on_scroll position-relative border-bottom z-index-1 o_border_contrast">
|
||||
<div class="container d-flex justify-content-between gap-3 h-100">
|
||||
<ul class="navbar-nav align-items-center gap-3 py-1">
|
||||
<!-- Social -->
|
||||
@@ -1225,7 +1228,7 @@
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div aria-label="Bottom" class="o_header_sales_four_bot z-index-0">
|
||||
<div aria-label="Bottom" class="o_header_sales_four_bot o_header_hide_on_scroll z-index-0">
|
||||
<div class="container">
|
||||
<ul class="navbar-nav d-grid align-items-center py-2 o_grid_header_3_cols">
|
||||
<!-- Search bar -->
|
||||
|
||||
Reference in New Issue
Block a user