diff --git a/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-item.scss b/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-item.scss index e15f2d360..7258ccd7b 100644 --- a/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-item.scss +++ b/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-item.scss @@ -3,6 +3,13 @@ padding-bottom: 0; } +:host([theme~="cxl-marketing-nav"]:not(.has-description).section-header) { + color: var(--lumo-body-text-color); + background: var(--lumo-shade-10pct); + font-weight: 300; + text-transform: uppercase; +} + :host([theme~="cxl-marketing-nav"]:hover), :host([theme~="cxl-marketing-nav"][expanded]) { color: var(--lumo-primary-color); diff --git a/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-list-box.scss b/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-list-box.scss index 652cb6c41..61989a4ea 100644 --- a/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-list-box.scss +++ b/packages/cxl-lumo-styles/scss/themes/vaadin-context-menu-list-box.scss @@ -22,7 +22,7 @@ :host([theme~="cxl-marketing-nav"]) { display: block; width: var(--cxl-vaadin-context-menu-item-max-width); - padding: 0 8px; + padding: 0 var(--lumo-space-s); } } diff --git a/packages/cxl-lumo-styles/scss/themes/vaadin-overlay.scss b/packages/cxl-lumo-styles/scss/themes/vaadin-overlay.scss index 75c429d00..6b7d45b79 100644 --- a/packages/cxl-lumo-styles/scss/themes/vaadin-overlay.scss +++ b/packages/cxl-lumo-styles/scss/themes/vaadin-overlay.scss @@ -14,8 +14,7 @@ } :host([theme~="cxl-marketing-nav"]) [part="content"] { - padding-right: 0; - padding-left: 0; + padding: 0; } @media screen and (min-width: 750px) { @@ -25,12 +24,13 @@ right: 0; bottom: 0; left: 0 !important; /* stylelint-disable-line declaration-no-important */ - display: flex; + display: none; align-items: unset !important; /* stylelint-disable-line declaration-no-important */ justify-content: unset !important; /* stylelint-disable-line declaration-no-important */ width: 376px; margin: 0; overflow: auto; + opacity: 0; // hide while in the body, to avoid flickering render, show after being moved to the overlays-wrapper element } :host([theme~="cxl-marketing-nav"]) [part="overlay"] { diff --git a/packages/cxl-ui/scss/cxl-marketing-nav.scss b/packages/cxl-ui/scss/cxl-marketing-nav.scss index e979ba5b8..b3d7b26ab 100644 --- a/packages/cxl-ui/scss/cxl-marketing-nav.scss +++ b/packages/cxl-ui/scss/cxl-marketing-nav.scss @@ -20,12 +20,30 @@ #overlays-wrapper { position: fixed; display: flex; - border: 1px solid #d2d5da; + border: 1px solid var(--lumo-base-color); + // Use top and bottom border prevent panel divider from reaching full height. + border-top-width: var(--lumo-space-m); + border-bottom-width: var(--lumo-space-m); border-radius: 6px; - box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.25); + // Second shadow set to emulate border + box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.25), 0 0 1px 1px #D2D5DA; + opacity: 1; + transition: opacity 0.2s, left 0.1s; + + vaadin-context-menu-overlay { + display: flex; + opacity: 1; // show after being moved to the overlays-wrapper element + transition: all 0.25s; + + &+ vaadin-context-menu-overlay { + border-left: 1px solid var(--lumo-shade-20pct); + } + } - vaadin-context-menu-overlay + vaadin-context-menu-overlay { - border-left: 1px solid var(--lumo-shade-20pct); + &[hidden] { + visibility: hidden; + opacity: 0; + transition: all 0.1s; } } diff --git a/packages/cxl-ui/src/components/cxl-marketing-nav.js b/packages/cxl-ui/src/components/cxl-marketing-nav.js index 020264155..7d8d6176b 100644 --- a/packages/cxl-ui/src/components/cxl-marketing-nav.js +++ b/packages/cxl-ui/src/components/cxl-marketing-nav.js @@ -22,6 +22,9 @@ export class CXLMarketingNavElement extends LitElement { @query('.menu-items') menuShadowItemsElement; + @query('#overlays-wrapper') + overlaysWrapperElement; + @property({ type: HTMLElement }) get menuItemSearchElement() { return this.shadowRoot.querySelector('.menu-item-search'); @@ -109,7 +112,7 @@ export class CXLMarketingNavElement extends LitElement {
@@ -132,6 +135,16 @@ export class CXLMarketingNavElement extends LitElement { ); } + connectedCallback() { + super.connectedCallback(); + this._boundOnOverlayOpen = this._onOverlayOpen.bind(this); + } + + disconnectedCallback() { + super.disconnectedCallback(); + document.body.removeEventListener('vaadin-overlay-open', this._boundOnOverlayOpen); + } + firstUpdated(changedProperties) { /** * Global styles. @@ -205,11 +218,43 @@ export class CXLMarketingNavElement extends LitElement { }, 1000) ); - document.body.addEventListener('vaadin-overlay-open', this._onOverlayOpen.bind(this)); + document.body.addEventListener('vaadin-overlay-open', this._boundOnOverlayOpen); super.firstUpdated(changedProperties); } + /* + * Setup listeners on nav items to handle overlays events. + */ + _setupSlottedMenuItems () { + const navItems = this.querySelectorAll('vaadin-tab'); + navItems.forEach(tab => tab.addEventListener('click', (e) => { + const overlays = document + .querySelector("cxl-marketing-nav") + .shadowRoot.querySelectorAll( + 'vaadin-context-menu-overlay[theme="cxl-marketing-nav"]' + ); + + this.overlaysWrapperElement.style.top = `${tab.parentElement.offsetTop + (0.75 * tab.clientHeight)}px`; + this.overlaysWrapperElement.style.left = `${e.clientX}px`; + + [...overlays].forEach((overlay) => { + overlay.close(); + }); + })) + } + + _onOverlayClose (e) { + const overlay = e.target; + if (!overlay.opened) { + this.overlaysWrapperElement.removeChild(overlay); + document.body.appendChild(overlay); + if (!this.overlaysWrapperElement.children.length) { + this.overlaysWrapperElement.toggleAttribute('hidden', true); + } + } + } + /** * Store overlay when triggered for `vaadin-context-menu-item` sub menu. * @@ -219,19 +264,18 @@ export class CXLMarketingNavElement extends LitElement { */ _onOverlayOpen(e) { const overlay = e.target; + overlay.addEventListener('opened-changed', this._onOverlayClose.bind(this)); if (window.matchMedia(this._wideMediaQuery).matches) { const target = this.shadowRoot.querySelector('#overlays-wrapper'); - const firstOverlay = document.querySelector( - 'vaadin-context-menu-overlay[theme="cxl-marketing-nav"]' - ); + const overlays = document.querySelectorAll('vaadin-context-menu-overlay[theme="cxl-marketing-nav"]') + const firstOverlay = overlays[0]; if (target) { - target.style.top = target?.style?.top ? target.style.top : firstOverlay.style.top; - target.style.left = target?.style?.left ? target.style.left : firstOverlay.style.left; - target.style.maxHeight = `${window.innerHeight - (target?.style?.maxHeight ? target.style.maxHeight : firstOverlay.offsetTop)}px`; + target.style.maxHeight = `${window.innerHeight - (target.style?.maxHeight || firstOverlay.offsetTop)}px`; target.appendChild(overlay); + target.toggleAttribute('hidden', false); // to fix wrong overlay error after changing the parent overlay._placeholder = null; @@ -318,7 +362,11 @@ export class CXLMarketingNavElement extends LitElement { menuItem.appendChild(link); + // If item is at depth 1 and had no children, assume it's a section header, do not show description + if (item.sectionHeader && !item.children) { + menuItem.classList.add('section-header'); // Add `description` element, if WordPress Menu Item has `description` field set. + } else if (item.description) { const descriptionItem = document.createElement('div'); @@ -398,7 +446,7 @@ export class CXLMarketingNavElement extends LitElement { // Prevent close on upstream events: clicks, keydown, etc contextMenu.addEventListener('item-selected', (e) => { - e.stopImmediatePropagation(); + // e.stopImmediatePropagation(); }); }); }); diff --git a/packages/storybook/cxl-ui/cxl-marketing-nav.data.json b/packages/storybook/cxl-ui/cxl-marketing-nav.data.json index 60c4af520..1e529b541 100644 --- a/packages/storybook/cxl-ui/cxl-marketing-nav.data.json +++ b/packages/storybook/cxl-ui/cxl-marketing-nav.data.json @@ -83,7 +83,8 @@ "component": "a", "href": "#", "id": 361, - "parent": 36 + "parent": 36, + "sectionHeader": true }, { "depth": 1, @@ -170,7 +171,8 @@ "href": "#", "description": "Supporting knowledge base for wider success", "id": 365, - "parent": 36 + "parent": 36, + "sectionHeader": true }, { "depth": 1, @@ -234,18 +236,6 @@ "id": 372, "parent": 36, "children": [] - }, - { - "component": "hr" - }, - { - "depth": 1, - "text": "Fast marketing", - "description": "Marketing experimentation - new hot tactics every week, crazy enough they just might work!", - "component": "a", - "href": "#", - "id": 373, - "parent": 36 } ] },