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="/"/>
+
+
+
+
-
-
-
-
+
+
+
@@ -228,11 +227,10 @@
-
-