diff --git a/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss b/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss index 9f73810c4e4..58c3b7cb6b9 100644 --- a/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss +++ b/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss @@ -60,3 +60,19 @@ $form-range-thumb-active-bg: $primary !default; // a muted one. This is defined here to be consistent in the whole frontend, as // when used with background classes, it should not be forced to a gray color. $figure-caption-color: inherit !default; + +// Accordion + +$accordion-border-width: 0 !default; +$accordion-button-color: inherit !default; +$accordion-button-active-bg: inherit !default; +$accordion-button-active-color: inherit !default; +$accordion-icon-color: $accordion-button-color !default; +$accordion-icon-width: 1rem !default; +$accordion-icon-transform: rotate(0deg) !default; +$accordion-button-icon: url("data:image/svg+xml,") !default; + +// Offcanvas + +$offcanvas-border-width: 0 !default; +$offcanvas-backdrop-opacity: .3 !default; diff --git a/addons/website/static/lib/multirange/multirange_custom.js b/addons/website/static/lib/multirange/multirange_custom.js index 3e65be64315..c810bcce83c 100644 --- a/addons/website/static/lib/multirange/multirange_custom.js +++ b/addons/website/static/lib/multirange/multirange_custom.js @@ -105,7 +105,7 @@ class Multirange { if (this.rangeWithInput) { this.leftInput = document.createElement("input"); this.leftInput.type = "number"; - this.leftInput.classList.add("invisible", "form-control", "form-control-sm", "w-auto", "mb-2", "mb-lg-1"); + this.leftInput.classList.add("invisible", "form-control", "form-control-sm", "mb-2", "mb-lg-1"); this.leftInput.min = this.min; this.leftInput.max = this.max; this.leftInput.step = this.step; diff --git a/addons/website/static/src/scss/bootstrap_overridden.scss b/addons/website/static/src/scss/bootstrap_overridden.scss index 9a3d0a625e6..4ac3877c619 100644 --- a/addons/website/static/src/scss/bootstrap_overridden.scss +++ b/addons/website/static/src/scss/bootstrap_overridden.scss @@ -174,3 +174,7 @@ $o-btn-outline-defaults: () !default; // Increase default navbar pills padding for 'pills' mode and add big radius $o-navbar-nav-pills-link-padding-x: if(o-website-value('header-links-style') == 'pills', 1rem * 1.5, null) !default; $o-navbar-nav-pills-link-border-radius: if(o-website-value('header-links-style') == 'pills', 10rem, null) !default; + +// Accordion +$accordion-color: inherit !default; +$accordion-bg: inherit !default; diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index d2e28cb4630..a4b9293a306 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -156,16 +156,16 @@ publicWidget.registry.websiteSaleCartLink = publicWidget.Widget.extend({ }); }); -odoo.define('website_sale.website_sale_category', function (require) { +odoo.define('website_sale.website_sale_offcanvas', function (require) { 'use strict'; var publicWidget = require('web.public.widget'); -publicWidget.registry.websiteSaleCategory = publicWidget.Widget.extend({ - selector: '#o_shop_collapse_category', +publicWidget.registry.websiteSaleOffcanvas = publicWidget.Widget.extend({ + selector: '#o_wsale_offcanvas', events: { - 'click .o_shop_collapse_button_closed': '_onOpenClick', - 'click .o_shop_collapse_button_open': '_onCloseClick', + 'show.bs.offcanvas': '_toggleFilters', + 'hidden.bs.offcanvas': '_toggleFilters', }, //-------------------------------------------------------------------------- @@ -173,25 +173,17 @@ publicWidget.registry.websiteSaleCategory = publicWidget.Widget.extend({ //-------------------------------------------------------------------------- /** + * Unfold active filters, fold inactive ones + * * @private * @param {Event} ev */ - _onOpenClick: function (ev) { - var $btn = $(ev.currentTarget); - $btn.parent().siblings().find('.o_shop_collapse_button_open:first').click(); - $btn.parents('li').find('ul:first').show(); - $btn.toggleClass('o_shop_collapse_button_closed o_shop_collapse_button_open'); - $btn.find('.fa').toggleClass('fa-angle-down fa-angle-right'); - }, - /** - * @private - * @param {Event} ev - */ - _onCloseClick: function (ev) { - var $btn = $(ev.currentTarget); - $btn.parent().find('ul:first').hide(); - $btn.toggleClass('o_shop_collapse_button_closed o_shop_collapse_button_open'); - $btn.find('.fa').toggleClass('fa-angle-down fa-angle-right'); + _toggleFilters: function (ev) { + for (const btn of this.el.querySelectorAll('button[data-status]')) { + if(btn.classList.contains('collapsed') && btn.dataset.status == "active" || ! btn.classList.contains('collapsed') && btn.dataset.status == "inactive" ) { + btn.click(); + } + } }, }); }); @@ -960,6 +952,12 @@ publicWidget.registry.WebsiteSaleLayout = publicWidget.Widget.extend({ }, }); } + + const activeClasses = ev.target.parentElement.dataset.activeClasses.split(' '); + ev.target.parentElement.querySelectorAll('.btn').forEach((btn) => { + activeClasses.map(c => btn.classList.toggle(c)); + }); + var $grid = this.$('#products_grid'); // Disable transition on all list elements, then switch to the new // layout then reenable all transitions after having forced a redraw diff --git a/addons/website_sale/static/src/scss/website_sale.scss b/addons/website_sale/static/src/scss/website_sale.scss index 330ec2c9bee..6cbb54f6aaf 100644 --- a/addons/website_sale/static/src/scss/website_sale.scss +++ b/addons/website_sale/static/src/scss/website_sale.scss @@ -4,12 +4,40 @@ $o-wsale-products-layout-grid-gutter-width: $grid-gutter-width / 2 !default; $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale-products-layout-grid-gutter-width); -@mixin wsale-break-table-to-list() { +@mixin wsale-break-table($-list: false) { .o_wsale_products_grid_table_wrapper { - table, tbody, tr, td { + table, tbody { display: block; width: 100%; } + + tr { + display: if($-list, block, flex); + width: 100%; + flex-wrap: wrap; + } + + td { + display: if($-list, block, inline-block); + width: if($-list, 100%, 50%); + } + } +} + +@mixin o-wsale-scrollbar-subdle($-vertical: true) { + scrollbar-color: currentColor $light; + scrollbar#{if($-vertical, -width, -height)}: 2px; + + &::-webkit-scrollbar { + #{if($-vertical, width, height)}: 2px; + } + + &::-webkit-scrollbar-thumb { + background: currentColor; + } + + &::-webkit-scrollbar-track { + background: $light; } } @@ -50,6 +78,19 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale --o-wsale-card-thumb-fill-mode: cover; } + .o_wsale_filmstip_wrapper { + scroll-snap-type: x mandatory; + @include o-wsale-scrollbar-subdle($-vertical: false); + + .o_wsale_filmstip { + transform: translateX(0); + + li { + scroll-snap-align: start; + } + } + } + .o_payment_form .card { border-radius: 4px !important; } @@ -100,22 +141,6 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale padding: 0; } - .breadcrumb { - background-color: map-get($grays, '100'); - padding: 0.6rem 0.75rem; - font-size: 0.9rem; - - a { - color: map-get($theme-colors, 'primary'); - font-weight: bold; - } - .breadcrumb-item + .breadcrumb-item::before { - font-family: 'FontAwesome'; - content: "\f105"; - padding-right: 0.2rem; - } - } - .table-striped tbody tr td:nth-of-type(even) { --table-accent-bg: rgba(0, 0, 0, 0.025); } @@ -126,25 +151,52 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale padding-top: 0.75rem; padding-bottom: 0.75rem; } + + #o_wsale_offcanvas { + width: 80%; + max-width: $offcanvas-horizontal-width; + + .o_searchbar_form .dropdown-menu { + right: 0; + } + + #o_wsale_offcanvas_content { + @include o-wsale-scrollbar-subdle(); + } + + .o_wsale_offcanvas_title { + &::after, &:not(.collapsed)::after { + width: .75rem; + height: .75rem; + background-image: url("data:image/svg+xml,"); + background-size: .75rem; + } + + &:not(.collapsed)::after { + transform: rotate(-45deg); + } + + // Since this nav is visible on mobile only, remove all visual + // effects related to keyboard/mouse navigation. + &, &:focus, &:hover { + box-shadow: none; + z-index: 0; + } + } + } + #products_grid_before { // == Guess the distance with the navbar $-container-top-gap: calc(#{map-get($spacers, 2)} + var(--gutter-x)); // == Guess the distance with the viewport's top. // Defined using CSS variables to ease custom-headers overrides. - --o_ws_sidebar_top_gap: calc(#{($navbar-padding-y * 2) + ($btn-padding-y-lg * 2)} + #{$-container-top-gap}); + --o_ws_sidebar_top_gap: calc(#{$navbar-padding-y * 2} + #{$btn-padding-y-lg * 2} + #{$-container-top-gap}); - @include media-breakpoint-up(lg) { - @include o-position-sticky($-container-top-gap); - height: 100vh; - - @if (o-website-value('header-scroll-effect') == 'standard') or (o-website-value('header-scroll-effect') == 'fixed') { - top: var(--o_ws_sidebar_top_gap); - } - - .o_wsale_products_grid_before_rail { - overflow-y: auto; - } + @if (o-website-value('header-scroll-effect') == null) or (o-website-value('header-scroll-effect') == 'fixed') { + top: var(--o_ws_sidebar_top_gap); + } @else { + top: $-container-top-gap; } .css_attribute_color { @@ -224,12 +276,6 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale // ==== THE GRID #products_grid { - .o_wsale_products_searchbar_form { - @include media-breakpoint-up(md) { - max-width: 450px; - } - } - .o_wsale_products_grid_table_wrapper .table { table-layout: fixed; @@ -257,7 +303,7 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale #products_grid:not(.o_wsale_layout_list) { @include media-breakpoint-down(lg) { - @include wsale-break-table-to-list(); + @include wsale-break-table(); } @include media-breakpoint-up(lg) { @@ -288,7 +334,7 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale } #products_grid.o_wsale_layout_list { - @include wsale-break-table-to-list(); + @include wsale-break-table($-list: true); .oe_product { --o-wsale-card-border-radius: 0; @@ -322,8 +368,8 @@ $o-wsale-products-layout-grid-gutter-width: min($grid-gutter-width / 2, $o-wsale // mt-* / my-* / mb-* utility classes, but here we need to use the shop max // grid gutter width to prevent the grid wrapper to overflow because of its // negative margins. - margin-top: $grid-gutter-width / 2; margin-bottom: $grid-gutter-width / 2; + margin-top: $grid-gutter-width / 2; } .oe_cart { diff --git a/addons/website_sale/static/tests/tours/website_sale_shop_customize.js b/addons/website_sale/static/tests/tours/website_sale_shop_customize.js index 4eed6c4c22c..3d08b84e7aa 100644 --- a/addons/website_sale/static/tests/tours/website_sale_shop_customize.js +++ b/addons/website_sale/static/tests/tours/website_sale_shop_customize.js @@ -9,16 +9,6 @@ wTourUtils.registerEditionTour('shop_customize', { test: true, }, [ - { - content: "open customize tab", - extra_trigger: '#oe_snippets.o_loaded', - trigger: '.o_we_customize_snippet_btn', - }, - { - content: "click on 'Attributes'", - extra_trigger: '#oe_snippets .o_we_customize_panel', - trigger: 'we-button[data-name="attributes_opt"]', - }, ...wTourUtils.clickOnSave(), { content: "select product attribute Steel", diff --git a/addons/website_sale/views/snippets/snippets.xml b/addons/website_sale/views/snippets/snippets.xml index 7f71d52ed04..413e240a428 100644 --- a/addons/website_sale/views/snippets/snippets.xml +++ b/addons/website_sale/views/snippets/snippets.xml @@ -80,15 +80,15 @@ data-customize-website-views="website_sale.products_description" data-no-preview="true" data-reload="/"/> - - + - @@ -98,6 +98,18 @@ data-dependencies="categories_opt" data-no-preview="true" data-reload="/"/> + + + + -