diff --git a/addons/website/models/theme_models.py b/addons/website/models/theme_models.py index 4f50869301d..7ea51e50ce5 100644 --- a/addons/website/models/theme_models.py +++ b/addons/website/models/theme_models.py @@ -172,11 +172,15 @@ class Theme(models.AbstractModel): 'navbar-font': 'null', 'buttons-font': 'null', 'color-palettes-number': 'null', + 'btn-ripple': 'null', 'header-template': 'null', 'footer-template': 'null', } ) + # Reinitialize effets + self.disable_view('website.option_ripple_effect') + # Reinitialize header templates self.disable_view('website.template_header_hamburger') self.disable_view('website.template_header_hamburger_left') diff --git a/addons/website/static/src/js/content/ripple_effect.js b/addons/website/static/src/js/content/ripple_effect.js new file mode 100644 index 00000000000..2e61d5b7cd8 --- /dev/null +++ b/addons/website/static/src/js/content/ripple_effect.js @@ -0,0 +1,72 @@ +odoo.define('website.ripple_effect', function (require) { +'use strict'; + +const publicWidget = require('web.public.widget'); + +publicWidget.registry.RippleEffect = publicWidget.Widget.extend({ + selector: '.btn, .dropdown-toggle, .dropdown-item', + events: { + 'click': '_onClick', + }, + duration: 350, + + /** + * @override + */ + start: async function () { + this.diameter = Math.max(this.$el.outerWidth(), this.$el.outerHeight()); + this.offsetX = this.$el.offset().left; + this.offsetY = this.$el.offset().top; + return this._super(...arguments); + }, + /** + * @override + */ + destroy: function () { + this._super(...arguments); + if (this.rippleEl) { + this.rippleEl.remove(); + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @param {boolean} [toggle] + */ + _toggleRippleEffect: function (toggle) { + this.el.classList.toggle('o_js_ripple_effect', toggle); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {Event} ev + */ + _onClick: function (ev) { + if (!this.rippleEl) { + this.rippleEl = document.createElement('span'); + this.rippleEl.classList.add('o_ripple_item'); + this.rippleEl.style.animationDuration = `${this.duration}ms`; + this.rippleEl.style.width = `${this.diameter}px`; + this.rippleEl.style.height = `${this.diameter}px`; + this.el.appendChild(this.rippleEl); + } + + clearTimeout(this.timeoutID); + this._toggleRippleEffect(false); + + this.rippleEl.style.top = `${ev.pageY - this.offsetY - this.diameter / 2}px`; + this.rippleEl.style.left = `${ev.pageX - this.offsetX - this.diameter / 2}px`; + + this._toggleRippleEffect(true); + this.timeoutID = setTimeout(() => this._toggleRippleEffect(false), this.duration); + }, +}); +}); diff --git a/addons/website/static/src/scss/options/ripple_effect.scss b/addons/website/static/src/scss/options/ripple_effect.scss new file mode 100644 index 00000000000..cff35300d55 --- /dev/null +++ b/addons/website/static/src/scss/options/ripple_effect.scss @@ -0,0 +1,28 @@ +@keyframes o-btn-ripple { + 100% { + opacity: 0; + transform: scale(2.5); + } +} + +.o_ripple_item { + display: none; + position: absolute; + z-index: -1; + border-radius: 100%; + opacity: .3; + background: currentColor; + pointer-events: none; + transform: scale(0); +} + +.o_js_ripple_effect { + transform-style: preserve-3d; + position: relative !important; + overflow: hidden !important; + + .o_ripple_item { + display: block; + animation: o-btn-ripple ease-in; + } +} diff --git a/addons/website/static/src/scss/primary_variables.scss b/addons/website/static/src/scss/primary_variables.scss index c4c6d80a446..044f2629cf2 100644 --- a/addons/website/static/src/scss/primary_variables.scss +++ b/addons/website/static/src/scss/primary_variables.scss @@ -252,6 +252,7 @@ $o-base-website-values-palette: ( 'btn-primary-outline': false, 'btn-secondary-outline': false, 'link-underline': 'hover', // 'never' / 'hover' / 'always' + 'btn-ripple': false, // A key from the $o-theme-font-configs map (null = default to the first key) 'font': null, diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index d49d03291e8..1da86d618d6 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -916,6 +916,10 @@ Fill Outline + Normal Underline On Hover diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 94685591390..c65f65ca386 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -721,6 +721,16 @@ + +