diff --git a/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.js b/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.js index 8914a87979e7e..7b4fb58840ace 100644 --- a/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.js +++ b/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.js @@ -20,16 +20,4 @@ export class CustomizeTab extends Component { this.state.hasContent = hasContent; }); } - - removeElement(el) { - this.env.editor.shared.remove.removeElement(el); - } - - cloneElement(el) { - this.env.editor.shared.clone.cloneElement(el); - } - - selectElement(el) { - this.env.editor.shared["builder-options"].updateContainers(el); - } } diff --git a/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.xml b/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.xml index f2a65b86193ae..28a5135a9783c 100644 --- a/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.xml +++ b/addons/html_builder/static/src/builder/builder_sidebar/tabs/customize_tab.xml @@ -14,10 +14,7 @@ + isRemovable="optionsContainer.isRemovable"/> diff --git a/addons/html_builder/static/src/builder/components/option_container.js b/addons/html_builder/static/src/builder/components/option_container.js index d10b355ecb381..f4ea09043c395 100644 --- a/addons/html_builder/static/src/builder/components/option_container.js +++ b/addons/html_builder/static/src/builder/components/option_container.js @@ -11,9 +11,6 @@ export class OptionsContainer extends Component { options: { type: Array }, editingElement: true, // HTMLElement from iframe isRemovable: false, - removeElement: { type: Function }, - cloneElement: { type: Function }, - selectElement: { type: Function }, }; setup() { @@ -31,15 +28,33 @@ export class OptionsContainer extends Component { } selectElement() { - this.props.selectElement(this.props.editingElement); + this.env.editor.shared["builder-options"].updateContainers(this.props.editingElement); + } + + toggleOverlayPreview(el, show) { + if (show) { + this.env.editor.shared.overlayButtons.hideOverlayButtons(); + this.env.editor.shared.builderOverlay.showOverlayPreview(el); + } else { + this.env.editor.shared.overlayButtons.showOverlayButtons(); + this.env.editor.shared.builderOverlay.hideOverlayPreview(el); + } + } + + onMouseEnter() { + this.toggleOverlayPreview(this.props.editingElement, true); + } + + onMouseLeave() { + this.toggleOverlayPreview(this.props.editingElement, false); } // Actions of the buttons in the title bar. removeElement() { - this.props.removeElement(this.props.editingElement); + this.env.editor.shared.remove.removeElement(this.props.editingElement); } cloneElement() { - this.props.cloneElement(this.props.editingElement); + this.env.editor.shared.clone.cloneElement(this.props.editingElement); } } diff --git a/addons/html_builder/static/src/builder/components/option_container.xml b/addons/html_builder/static/src/builder/components/option_container.xml index f1b679be00aa4..c21ac2718ceec 100644 --- a/addons/html_builder/static/src/builder/components/option_container.xml +++ b/addons/html_builder/static/src/builder/components/option_container.xml @@ -2,7 +2,7 @@ -
+
diff --git a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.js b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.js index 473a72726a1f9..f6341d3b15b8c 100644 --- a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.js +++ b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.js @@ -60,7 +60,7 @@ export class BuilderOverlay { isActive() { // TODO active still necessary ? (check when we have preview mode) - return this.overlayElement.classList.contains("oe_active"); + return this.overlayElement.matches(".oe_active, .o_we_overlay_preview"); } refreshPosition() { @@ -105,7 +105,13 @@ export class BuilderOverlay { } toggleOverlay(show) { - this.overlayElement.classList.add("oe_active", show); + this.overlayElement.classList.toggle("oe_active", show); + this.refreshPosition(); + this.refreshHandles(); + } + + toggleOverlayPreview(show) { + this.overlayElement.classList.toggle("o_we_overlay_preview", show); this.refreshPosition(); this.refreshHandles(); } diff --git a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.scss b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.scss index 47fd55e1ca478..57e0edf9c4eb6 100644 --- a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.scss +++ b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay.scss @@ -15,11 +15,17 @@ div[data-oe-local-overlay-id="builder-overlay-container"] { opacity: 0 !important; transition: none; } - &.oe_active { + + &.oe_active, + &.o_we_overlay_preview { display: block; z-index: 1; } + &.o_we_overlay_preview { + transition: none; + } + // HANDLES .o_handles { @include o-position-absolute(-$o-we-handles-offset-to-hide, 0, auto, 0); diff --git a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay_plugin.js b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay_plugin.js index 690b66250290c..b66b69d6a2fb5 100644 --- a/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay_plugin.js +++ b/addons/html_builder/static/src/builder/plugins/builder_overlay/builder_overlay_plugin.js @@ -6,6 +6,7 @@ import { BuilderOverlay } from "./builder_overlay"; export class BuilderOverlayPlugin extends Plugin { static id = "builderOverlay"; static dependencies = ["selection", "localOverlay", "history"]; + static shared = ["showOverlayPreview", "hideOverlayPreview"]; resources = { step_added_handlers: this._update.bind(this), change_current_options_containers_listeners: this.openBuilderOverlay.bind(this), @@ -133,4 +134,21 @@ export class BuilderOverlayPlugin extends Plugin { overlay.toggleOverlayVisibility(show); }); } + + showOverlayPreview(el) { + // Hide all the active overlays. + this.toggleOverlaysVisibility(false); + // Show the preview of the one corresponding to the given element. + const overlayToShow = this.overlays.find((overlay) => overlay.overlayTarget === el); + overlayToShow.toggleOverlayPreview(true); + overlayToShow.toggleOverlayVisibility(true); + } + + hideOverlayPreview(el) { + // Remove the preview. + const overlayToHide = this.overlays.find((overlay) => overlay.overlayTarget === el); + overlayToHide.toggleOverlayPreview(false); + // Show back the active overlays. + this.toggleOverlaysVisibility(true); + } } diff --git a/addons/html_builder/static/src/builder/plugins/overlay_buttons/overlay_buttons_plugin.js b/addons/html_builder/static/src/builder/plugins/overlay_buttons/overlay_buttons_plugin.js index 6bda6d7e0c934..d2614a3a9df53 100644 --- a/addons/html_builder/static/src/builder/plugins/overlay_buttons/overlay_buttons_plugin.js +++ b/addons/html_builder/static/src/builder/plugins/overlay_buttons/overlay_buttons_plugin.js @@ -51,6 +51,7 @@ function isResizable(el) { export class OverlayButtonsPlugin extends Plugin { static id = "overlayButtons"; static dependencies = ["selection", "overlay", "history"]; + static shared = ["hideOverlayButtons", "showOverlayButtons"]; resources = { step_added_handlers: this.refreshButtons.bind(this), change_current_options_containers_listeners: this.addOverlayButtons.bind(this), @@ -96,12 +97,12 @@ export class OverlayButtonsPlugin extends Plugin { // On keydown, hide the buttons and then show them again when the mouse // moves. const onMouseMoveOrDown = throttleForAnimation((ev) => { - this.toggleVisibility(true); + this.showOverlayButtons(); ev.currentTarget.removeEventListener("mousemove", onMouseMoveOrDown); ev.currentTarget.removeEventListener("mousedown", onMouseMoveOrDown); }); this.addDomListener(this.editable, "keydown", (ev) => { - this.toggleVisibility(false); + this.hideOverlayButtons(); ev.currentTarget.addEventListener("mousemove", onMouseMoveOrDown); ev.currentTarget.addEventListener("mousedown", onMouseMoveOrDown); }); @@ -114,10 +115,10 @@ export class OverlayButtonsPlugin extends Plugin { scrollingTarget, "scroll", throttleForAnimation(() => { - this.toggleVisibility(false); + this.hideOverlayButtons(); clearTimeout(this.scrollingTimeout); this.scrollingTimeout = setTimeout(() => { - this.toggleVisibility(true); + this.showOverlayButtons(); }, 250); }), { capture: true } @@ -140,8 +141,12 @@ export class OverlayButtonsPlugin extends Plugin { this.state.buttons = buttons; } - toggleVisibility(show) { - this.state.isVisible = show; + hideOverlayButtons() { + this.state.isVisible = false; + } + + showOverlayButtons() { + this.state.isVisible = true; } addOverlayButtons(optionsContainer) { @@ -153,6 +158,7 @@ export class OverlayButtonsPlugin extends Plugin { ); if (optionWithOverlayButtons) { this.target = optionWithOverlayButtons.element; + this.state.isVisible = true; this.refreshButtons(); this.overlay.open({ target: optionWithOverlayButtons.element, diff --git a/addons/html_builder/static/tests/custom_tab/container_buttons.test.js b/addons/html_builder/static/tests/custom_tab/container_buttons.test.js index a519758a9a48c..4c955bd25a1d4 100644 --- a/addons/html_builder/static/tests/custom_tab/container_buttons.test.js +++ b/addons/html_builder/static/tests/custom_tab/container_buttons.test.js @@ -20,7 +20,7 @@ const dummySnippet = ` `; test("Use the sidebar 'remove' buttons", async () => { - await setupWebsiteBuilder(dummySnippet, { loadIframeBundles: true }); + await setupWebsiteBuilder(dummySnippet); const removeSectionSelector = ".o_customize_tab .options-container > div:contains('Dummy Section') button.oe_snippet_remove"; @@ -38,7 +38,7 @@ test("Use the sidebar 'remove' buttons", async () => { }); test("Use the sidebar 'clone' buttons", async () => { - await setupWebsiteBuilder(dummySnippet, { loadIframeBundles: true }); + await setupWebsiteBuilder(dummySnippet); const cloneSectionSelector = ".o_customize_tab .options-container > div:contains('Dummy Section') button.oe_snippet_clone"; @@ -58,7 +58,7 @@ test("Use the sidebar 'clone' buttons", async () => { }); test("Clicking on the options container title selects the corresponding element", async () => { - await setupWebsiteBuilder(dummySnippet, { loadIframeBundles: true }); + await setupWebsiteBuilder(dummySnippet); await contains(":iframe .col-lg-7").click(); expect(".o_customize_tab .options-container").toHaveCount(2); @@ -68,3 +68,27 @@ test("Clicking on the options container title selects the corresponding element" expect(".o_customize_tab .options-container").toHaveCount(1); expect(".oe_overlay.oe_active").toHaveRect(":iframe section"); }); + +test("Show the overlay preview when hovering an options container", async () => { + await setupWebsiteBuilder(dummySnippet); + + await contains(":iframe .col-lg-7").click(); + expect(".overlay .o_overlay_options").toHaveCount(1); + expect(".oe_overlay").toHaveCount(2); + expect(".oe_overlay.oe_active").toHaveRect(":iframe .col-lg-7"); + + await contains(".o_customize_tab .options-container span:contains('Dummy Section')").hover(); + expect(".overlay .o_overlay_options").toHaveCount(0); + expect(".oe_overlay.oe_active.o_overlay_hidden").toHaveCount(1); + expect(".oe_overlay.o_we_overlay_preview").toHaveRect(":iframe section"); + + await contains(".o_customize_tab .options-container span:contains('Column')").hover(); + expect(".overlay .o_overlay_options").toHaveCount(0); + expect(".oe_overlay.oe_active.o_we_overlay_preview").toHaveCount(1); + expect(".oe_overlay.o_we_overlay_preview").toHaveRect(":iframe .col-lg-7"); + + await contains(":iframe .col-lg-7").hover(); + expect(".overlay .o_overlay_options").toHaveCount(1); + expect(".oe_overlay.o_we_overlay_preview").toHaveCount(0); + expect(".oe_overlay.oe_active:not(.o_overlay_hidden)").toHaveRect(":iframe .col-lg-7"); +});