Skip to content

Commit

Permalink
chore(masthead): integrate enhancements from alpha branch (#11183)
Browse files Browse the repository at this point in the history
### Related Ticket(s)

none

### Description

We made some enhancements to the alpha v2 masthead after we'd integrated its branch into the main C4IBM v2 branch. This PR ports those enhancements over.

- **fix(masthead-v2): use more explicit selector in dropdown toggle** (911f802) ([Original PR](#11084))
- **feat(masthead-v2): add masthead to document flow** (e1debd8) ([Original PR](#10998))
- **feat(masthead-v2): Minimize CMApp on megamenu open** (c4a06f3) ([Original PR](#11085))
- **fix(masthead-v2): do not fail if object data does not exist** (c9609f7) ([Original PR](#11205))
- **fix(masthead-v2): ensure L1 dropdown targets exist** (fc65086) ([Original PR](#11254))
- **fix(masthead-v2): provide accessible nav label** (f183d25) ([Original PR](#11269))
- **fix(sticky-header): prevent negative overscroll from hiding stuck elements** (51015ed) ([Original PR](#11266))

<!-- React and Web Component deploy previews are enabled by default. -->
<!-- To enable additional available deploy previews, apply the following -->
<!-- labels for the corresponding package: -->
<!-- *** "test: e2e": Codesandbox examples and e2e integration tests -->
<!-- *** "package: services": Services -->
<!-- *** "package: utilities": Utilities -->
<!-- *** "RTL": React / Web Components (RTL) -->
<!-- *** "feature flag": React / Web Components (experimental) -->
  • Loading branch information
jkaeser authored Jan 8, 2024
1 parent aa1a842 commit eec379e
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 35 deletions.
3 changes: 2 additions & 1 deletion packages/styles/scss/components/masthead/_masthead.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2016, 2023
* Copyright IBM Corp. 2016, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand Down Expand Up @@ -270,6 +270,7 @@
:host(#{$c4d-prefix}-cloud-masthead-container) {
position: relative;
z-index: 900;
display: block;
padding-block-start: $spacing-09;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class StickyHeader {
}

const newY = window.scrollY;
this._lastScrollPosition = newY;
this._lastScrollPosition = Math.max(0, newY);

/**
* maxScrollaway is a calculated value matching the height of all components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { LitElement, html, TemplateResult } from 'lit';
import { state, property } from 'lit/decorators.js';
import { state, property, query } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import ArrowRight16 from '../../internal/vendor/@carbon/web-components/icons/arrow--right/16.js';
import ifNonEmpty from '../../internal/vendor/@carbon/web-components/globals/directives/if-non-empty.js';
Expand Down Expand Up @@ -41,6 +41,7 @@ import { C4D_CUSTOM_PROFILE_LOGIN } from '../../globals/internal/feature-flags';
import C4DMastheadLogo from './masthead-logo';
import C4DMegaMenuTabs from './megamenu-tabs';
import C4DMegamenuTopNavMenu from './megamenu-top-nav-menu';
import C4DMastheadL1 from './masthead-l1';
import './masthead';
import './masthead-button-cta';
import './masthead-l1';
Expand Down Expand Up @@ -94,6 +95,7 @@ export interface CMApp {
version: string;
ready: boolean;
init: Function;
minimize: Function;
refresh: Function;
register: Function;
deregister: Function;
Expand Down Expand Up @@ -992,6 +994,9 @@ class C4DMastheadComposite extends HostListenerMixin(LitElement) {
// any previously opened megamenu.
if (active && menuIndex !== undefined) {
this._activeMegamenuIndex = menuIndex;

// Close the Contact Module upon opening megamenu.
this.contactModuleApp?.minimize();
}

// If clicking the same nav item to close megamenu, reset state to prune its
Expand All @@ -1008,6 +1013,14 @@ class C4DMastheadComposite extends HostListenerMixin(LitElement) {
resolveFn();
};

@HostListener(C4DMastheadL1.dropDownToggleEvent)
protected _handleL1DropdownToggle({ detail }: CustomEvent) {
const { isOpen } = detail;
if (isOpen) {
this.contactModuleApp?.minimize();
}
}

/**
* Sets the active megamenu tabpanel upon user interaction.
*
Expand Down Expand Up @@ -1325,6 +1338,47 @@ class C4DMastheadComposite extends HostListenerMixin(LitElement) {
: unauthenticatedCtaButtons;
}

/**
* A reference to the c4d-masthead element.
*/
@query(`${c4dPrefix}-masthead`)
mastheadRef;

/**
* Resize observer to trigger container height recalculations.
*
* @private
*/
private _heightResizeObserver = new ResizeObserver(
this._resizeObserverCallback.bind(this)
);

/**
* Prevents resize observer from blocking main thread.
*/
private _resizeObserverThrottle?: NodeJS.Timeout;

/**
* Throttled callback for _heightResizeObserver.
*/
protected _resizeObserverCallback() {
clearTimeout(this._resizeObserverThrottle);
this._resizeObserverThrottle = setTimeout(
this._setContainerHeight.bind(this),
100
);
}

/**
* Sets root element's height equal to the height of the fixed masthead elements.
*/
protected _setContainerHeight() {
const { mastheadRef } = this;
if (mastheadRef) {
this.style.display = 'block';
this.style.height = `${mastheadRef.getBoundingClientRect().height}px`;
}
}
firstUpdated() {
const { language, dataEndpoint } = this;
globalInit();
Expand All @@ -1344,6 +1398,9 @@ class C4DMastheadComposite extends HostListenerMixin(LitElement) {
this._isMobileVersion = layoutBreakpoint.matches;
this.requestUpdate();
});

// Keep render root's height in sync with c4d-masthead.
this._heightResizeObserver.observe(this.mastheadRef);
}

updated(changedProperties) {
Expand All @@ -1359,6 +1416,11 @@ class C4DMastheadComposite extends HostListenerMixin(LitElement) {
}
}

disconnectedCallback() {
super.disconnectedCallback();
this._heightResizeObserver.disconnect();
}

render() {
const {
_isMobileVersion: isMobileVersion,
Expand Down
44 changes: 23 additions & 21 deletions packages/web-components/src/components/masthead/masthead-contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ import { property } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import Chat20 from '../../internal/vendor/@carbon/web-components/icons/chat/20.js';
import settings from '../../internal/vendor/@carbon/ibmdotcom-utilities/utilities/settings/settings';
import HostListener from '../../internal/vendor/@carbon/web-components/globals/decorators/host-listener.js';
import styles from './masthead.scss';
import C4DMastheadProfile from './masthead-profile';
import C4DMastheadContainer from './masthead-container';
import { CMApp } from './masthead-composite';
import { carbonElement as customElement } from '../../internal/vendor/@carbon/web-components/globals/decorators/carbon-element.js';

const { prefix, stablePrefix: c4dPrefix } = settings;
Expand All @@ -33,6 +32,28 @@ class C4DMastheadContact extends C4DMastheadProfile {
@property({ attribute: 'trigger-label' })
triggerLabel = 'Contact';

/**
* Handles cm-app-pane-displayed event fired by CM_APP.
*
* @see DOCUMENT_EVENTS live-advisor/cm-app/js/helpers/otherConstants.js
* - https://github.ibm.com/live-advisor/cm-app/blob/master/js/helpers/otherConstants.js
*/
@HostListener('document:cm-app-pane-displayed')
protected _handleCMAppDisplayed = (_event: CustomEvent) => {
this.triggerLabel = 'Close contact window';
};

/**
* Handles cm-app-pane-hidden event fired by CM_APP.
*
* @see DOCUMENT_EVENTS live-advisor/cm-app/js/helpers/otherConstants.js
* - https://github.ibm.com/live-advisor/cm-app/blob/master/js/helpers/otherConstants.js
*/
@HostListener('document:cm-app-pane-hidden')
protected _handleCMAppHidden = (_event: CustomEvent) => {
this.triggerLabel = 'Show contact window';
};

render() {
const { triggerLabel, _handleClick: handleClick } = this;
return html`
Expand All @@ -46,25 +67,6 @@ class C4DMastheadContact extends C4DMastheadProfile {
`;
}

updated(changedProperties) {
if (changedProperties.has('expanded')) {
if (!this.expanded) {
const mastheadContainer = this.closest(
`${c4dPrefix}-masthead-container`
) as C4DMastheadContainer;

/**
* This is a workaround to minimize the chat module. Currently no minimize methods exist.
*
* @see https://github.ibm.com/live-advisor/cm-app
*/
if (mastheadContainer?.contactModuleApp) {
(mastheadContainer.contactModuleApp as CMApp).init();
}
}
}
}

static styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,17 @@ export function mapStateToProps(
: translations?.[language]?.mastheadNav?.links,
authenticatedProfileItems: !language
? undefined
: translations?.[language]?.profileMenu.signedin,
: translations?.[language]?.profileMenu?.signedin,
unauthenticatedProfileItems: !language
? undefined
: translations?.[language]?.profileMenu.signedout,
: translations?.[language]?.profileMenu?.signedout,
authenticatedCtaButtons: !language
? undefined
: translations?.[language]?.masthead?.profileMenu.signedin.ctaButtons,
: translations?.[language]?.masthead?.profileMenu?.signedin?.ctaButtons,
unauthenticatedCtaButtons: !language
? undefined
: translations?.[language]?.masthead?.profileMenu.signedout.ctaButtons,
: translations?.[language]?.masthead?.profileMenu?.signedout
?.ctaButtons,
contactUsButton: !language
? undefined
: translations?.[language]?.masthead?.contact,
Expand Down
29 changes: 25 additions & 4 deletions packages/web-components/src/components/masthead/masthead-l1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
${title}${ChevronDown16()}
</button>
<div
data-dropdown-target
class="${prefix}--masthead__l1-dropdown ${prefix}--masthead__l1-dropdown__${columns}-col">
${announcement
? html`<div class="${prefix}--masthead__l1-dropdown-announcement">
Expand Down Expand Up @@ -551,7 +552,7 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
<button class="${prefix}--masthead__l1-title" @click=${toggleSubsection}>
${title}${ChevronDown16()}
</button>
<ul class="${prefix}--masthead__l1-dropdown">
<ul data-dropdown-target class="${prefix}--masthead__l1-dropdown">
${url
? html` <li>
<a class="${prefix}--masthead__l1-dropdown-item" href="${url}">
Expand Down Expand Up @@ -617,7 +618,9 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
@click=${toggleSubsection}>
${title}${ChevronDown16()}
</button>
<div class="${prefix}--masthead__l1-dropdown-subsection">
<div
data-dropdown-target
class="${prefix}--masthead__l1-dropdown-subsection">
${announcement
? html`<div class="${prefix}--masthead__l1-dropdown-announcement">
${unsafeHTML(announcement)}
Expand Down Expand Up @@ -670,10 +673,13 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
*/
protected _toggleSubsection(event: PointerEvent) {
const { isMobileVersion } = this;
const { dropDownToggleEvent } = this.constructor as typeof C4DMastheadL1;
const { currentTarget } = event;
const button = currentTarget as HTMLElement;
const dropdown = button.nextElementSibling as HTMLElement;
const isOpen = dropdown.classList.contains('is-open');
const dropdown = button.parentNode?.querySelector(
'[data-dropdown-target]'
) as HTMLElement;
const isOpen = dropdown?.classList.contains('is-open');

if (!isMobileVersion && dropdown && !isOpen) {
// Get Button & Dropdown locations & widths
Expand Down Expand Up @@ -731,6 +737,17 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
dropdown.style.maxHeight = `calc(${maxHeight}px - 4rem)`;
}

this.dispatchEvent(
new CustomEvent(dropDownToggleEvent, {
bubbles: true,
composed: true,
cancelable: false,
detail: {
isOpen: !isOpen,
},
})
);

button.classList.toggle('is-open', !isOpen);
dropdown.classList.toggle('is-open', !isOpen);
}
Expand Down Expand Up @@ -952,6 +969,10 @@ class C4DMastheadL1 extends StableSelectorMixin(LitElement) {
return `${c4dPrefix}--masthead__l1`;
}

static get dropDownToggleEvent() {
return `${c4dPrefix}-masthead-l1-dropdown-toggle`;
}

static styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader
}

Expand Down
15 changes: 12 additions & 3 deletions packages/web-components/src/components/masthead/top-nav.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @license
*
* Copyright IBM Corp. 2020, 2023
* Copyright IBM Corp. 2020, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand Down Expand Up @@ -120,6 +120,12 @@ class C4DTopNav extends StableSelectorMixin(HostListenerMixin(CDSHeaderNav)) {
@property({ type: Boolean })
importedMegamenu = false;

/**
* The `aria-label` attribute for the nav element.
*/
@property({ attribute: 'nav-label' })
navLabel: string = 'Primary navigation';

/**
* The English title of the selected nav item.
*/
Expand Down Expand Up @@ -556,7 +562,10 @@ class C4DTopNav extends StableSelectorMixin(HostListenerMixin(CDSHeaderNav)) {
</div>
<div class="${c4dPrefix}-ce--header__nav-content-container">
<div class="${prefix}--header__nav-content">
<nav part="nav" class="${prefix}--header__nav">
<nav
part="nav"
class="${prefix}--header__nav"
aria-label="${ifDefined(this.navLabel)}">
<div class="${prefix}--sub-content-right"></div>
<div
part="menubar"
Expand Down Expand Up @@ -599,7 +608,7 @@ class C4DTopNav extends StableSelectorMixin(HostListenerMixin(CDSHeaderNav)) {
<nav
part="nav"
class="${prefix}--header__nav"
aria-label="Main Navigation">
aria-label="${ifDefined(this.navLabel)}">
<div class="${prefix}--sub-content-left"></div>
<div
part="menubar"
Expand Down

0 comments on commit eec379e

Please sign in to comment.