Skip to content

Commit

Permalink
fix(masthead): display L0 nav with L1 when scrolling up (#7591)
Browse files Browse the repository at this point in the history
* refactor(table-of-contents): use defined type

* fix(dotcom-shell-composite): show L1 with L0 on scrollup

* fix(Masthead): show L1 with L0 on scrollup

* chore: update snapshots

* fix(TOCDesktop): account for masthead height

* refactor(TableOfContents): refactor menu item validation

* fix(TableOfContents): account for stickyOffset for active item indicator

* fix(table-of-contents): calc stickyOffset in active item indicator

* fix(masthead): reposition mobile toc with L1

Co-authored-by: Jeff Chew <[email protected]>
  • Loading branch information
emyarod and jeffchew authored Nov 18, 2021
1 parent fa146b1 commit a5bb87e
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 43 deletions.
40 changes: 29 additions & 11 deletions packages/react/src/__tests__/__snapshots__/storyshots.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -40118,7 +40118,9 @@ exports[`Storyshots Components|Dotcom shell Default (footer language only) 1`] =
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -47206,7 +47208,9 @@ exports[`Storyshots Components|Dotcom shell Default 1`] = `
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -53598,7 +53602,9 @@ exports[`Storyshots Components|Dotcom shell Search open 1`] = `
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -65236,11 +65242,13 @@ exports[`Storyshots Components|Dotcom shell With L1 1`] = `
}
}
>
<Content>
<Content
withL1={true}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
stickyOffset="48"
stickyOffset="96"
theme="white"
>
<section
Expand Down Expand Up @@ -65273,7 +65281,7 @@ exports[`Storyshots Components|Dotcom shell With L1 1`] = `
style={
Object {
"position": "sticky",
"top": "48px",
"top": "96px",
}
}
>
Expand Down Expand Up @@ -71861,7 +71869,9 @@ exports[`Storyshots Components|Dotcom shell With micro footer (language only) 1`
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -77945,7 +77955,9 @@ exports[`Storyshots Components|Dotcom shell With micro footer 1`] = `
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -83776,7 +83788,9 @@ exports[`Storyshots Components|Dotcom shell With platform 1`] = `
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -90405,7 +90419,9 @@ exports[`Storyshots Components|Dotcom shell With short footer (language only) 1`
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down Expand Up @@ -97559,7 +97575,9 @@ exports[`Storyshots Components|Dotcom shell With short footer 1`] = `
}
}
>
<Content>
<Content
withL1={false}
>
<TableOfContents
menuItems={null}
menuLabel="Jump to"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const Default = ({ parameters }) => {
<DotcomShell mastheadProps={mastheadProps} footerProps={footerProps}>
<main id="main-content">
<div style={{ paddingTop: '6rem' }}>
<Content />
<Content withL1={!!mastheadProps.mastheadL1Data} />
</div>
</main>
</DotcomShell>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,20 @@ import logoMicrosoft from '../../../../../../storybook-images/assets/logos/logo-
import logoRabobank from '../../../../../../storybook-images/assets/logos/logo-rabobank.png';
import logoUsBank from '../../../../../../storybook-images/assets/logos/logo-usbank.png';

import PropTypes from 'prop-types';
import React from 'react';

/**
* DDS patterns template
*
* @returns {*} JSX for Learn template
*/
const Content = () => (
const Content = ({ withL1 }) => (
<>
<TableOfContents menuLabel="Jump to" theme="white" stickyOffset="48">
<TableOfContents
menuLabel="Jump to"
theme="white"
stickyOffset={withL1 ? '96' : '48'}>
<a name="section-1" data-title="Lorem ipsum dolor sit amet" />
<LeadSpaceBlock
title="Lorem ipsum dolor sit amet"
Expand Down Expand Up @@ -426,4 +430,11 @@ const Content = () => (
</>
);

Content.propTypes = {
/**
* `true` if content is rendered with an L1 on the page
*/
withL1: PropTypes.bool,
};

export default Content;
14 changes: 8 additions & 6 deletions packages/react/src/components/Masthead/Masthead.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,28 +148,30 @@ const Masthead = ({
[`${prefix}--masthead__header--search-active`]: isSearchActive,
});

const [scrollOffset, setScrollOffset] = useState(window.scrollY);

useEffect(() => {
/**
* Sets sticky masthead. If both L0 and L1 are present, L1 will be sticky.
*
*/
const hideTopnavThreshold = 0.25;
const handleScroll = root.addEventListener('scroll', () => {
/**
* L0 will hide/show only in the top 25% of the viewport.
* L0 will hide on scroll down, show on scroll up
*
*/
if (mastheadL1Ref.current != null) {
setIsMastheadSticky(
root.pageYOffset > root.innerHeight * hideTopnavThreshold
);
const prevOffset = scrollOffset;
const currOffset = window.scrollY;
setIsMastheadSticky(currOffset > prevOffset);
setScrollOffset(currOffset);
}
});

return () => {
root.removeEventListener('scroll', () => handleScroll);
};
}, []);
}, [scrollOffset]);

if (navigation) {
switch (typeof navigation) {
Expand Down
5 changes: 4 additions & 1 deletion packages/react/src/components/TableOfContents/TOCDesktop.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ const TOCDesktop = ({ menuItems, selectedId }) => {
const handleOnClick = (e, id) => {
e.preventDefault();
const selector = `a[name="${id}"]`;
smoothScroll(null, selector);
const masthead = e.target.ownerDocument.querySelector(
`.${prefix}--masthead`
);
smoothScroll(null, selector, masthead?.offsetHeight);
triggerFocus(selector);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const TableOfContents = ({
.filter((elem, index, arr) =>
elem.height === null
? arr[index - 1].position < arr[index - 1].height
: elem.position - 50 > -elem.height
: elem.position - 50 - stickyOffset > -elem.height
);

// Sets last section as active at the end of page in case there is not enough height for it to dynamically activate
Expand Down Expand Up @@ -164,11 +164,10 @@ const TableOfContents = ({
* @param {Array} menuItems array of Items
* @returns {Array} filtered array of items
*/
const validateMenuItems = menuItems => {
return menuItems.filter(
item => item.title.trim().length > 0 && item.id.trim().length > 0
const validateMenuItems = menuItems =>
menuItems.filter(
item => item?.title?.trim().length && item?.id?.trim().length
);
};

/**
* Props for TOCDesktop and TOCMobile
Expand Down
21 changes: 11 additions & 10 deletions packages/styles/scss/components/masthead/_masthead.scss
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,26 @@ $search-transition-timing: 95ms;
}

.#{$prefix}--masthead--sticky.#{$prefix}--masthead--sticky__l1 {
top: -98px;

@include carbon--breakpoint-up(800px) {
top: -48px;
}
}

.#{$prefix}--masthead--sticky__l1 + .#{$prefix}--dotcom-shell {
@include carbon--breakpoint-up(800px) {
.#{$prefix}--tableofcontents__sidebar {
top: 98px;
}
}
.#{$prefix}--masthead--sticky__l1
+ .#{$prefix}--dotcom-shell
.#{$prefix}--tableofcontents__sidebar {
top: 98px;
}

.#{$prefix}--masthead--sticky__l1.#{$prefix}--masthead--sticky
+ .#{$prefix}--dotcom-shell {
+ .#{$prefix}--dotcom-shell
.#{$prefix}--tableofcontents__sidebar {
@include carbon--breakpoint-up(800px) {
top: 48px;
}
top: 0;

@include carbon--breakpoint-up(800px) {
top: 48px;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { FOOTER_SIZE } from '../footer/footer';
import '../footer/footer-composite';
import './dotcom-shell';
import styles from './dotcom-shell-composite.scss';
import DDSTableOfContents from '../table-of-contents/table-of-contents';

const { prefix } = settings;
const { stablePrefix: ddsPrefix } = ddsSettings;
Expand Down Expand Up @@ -85,6 +86,11 @@ class DDSDotcomShellComposite extends LitElement {
*/
private _masthead?: HTMLElement;

/**
* The tableOfContents element.
*/
private _tableOfContents?: DDSTableOfContents;

/**
* The tableOfContents inner navBar or sideBar depending on layout.
*/
Expand Down Expand Up @@ -178,10 +184,20 @@ class DDSDotcomShellComposite extends LitElement {
this._masthead!.style.top = `${mastheadTop}px`;
}
} else if (l1Element) {
this._masthead!.style.top = `-${Math.min(
this._masthead!.offsetHeight - l1Element.offsetHeight,
Math.abs(mastheadTop)
)}px`;
const toc = this._tableOfContents;
const stickyOffset = Number(toc?.getAttribute('stickyOffset'));
if (window.scrollY < this._lastScrollPosition) {
// scrolling up
this._masthead!.style.top = '0';
toc!.stickyOffset = stickyOffset + l1Element.offsetHeight;
} else {
// scrolling down
this._masthead!.style.top = `-${Math.min(
this._masthead!.offsetHeight - l1Element.offsetHeight,
Math.abs(mastheadTop)
)}px`;
toc!.stickyOffset = Math.max(stickyOffset - l1Element.offsetHeight, stickyOffset);
}
} else if (this._tableOfContentsLayout === 'horizontal') {
this._tableOfContentsInnerBar!.style.top = `${Math.max(Math.min(tocPosition, this._masthead!.offsetHeight), 0)}px`;
this._masthead!.style.top = `${mastheadTop}px`;
Expand Down Expand Up @@ -579,7 +595,8 @@ class DDSDotcomShellComposite extends LitElement {
super.update(changedProperties);

if (!this._tableOfContentsInnerBar) {
const toc = document.querySelector(`${ddsPrefix}-table-of-contents`);
this._tableOfContents = document.querySelector(`${ddsPrefix}-table-of-contents`) as DDSTableOfContents;
const toc = this._tableOfContents;
if (toc?.getAttribute('toc-layout') === 'horizontal') {
this._tableOfContentsInnerBar = toc?.shadowRoot?.querySelector(`.${prefix}--tableofcontents__navbar`) as HTMLElement;
this._tableOfContentsLayout = 'horizontal';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ class DDSTableOfContents extends HostListenerMixin(StableSelectorMixin(LitElemen
position: elem.getBoundingClientRect().y,
}))
.filter((elem, index, arr) =>
elem.height === null ? arr[index - 1].position < arr[index - 1].height! : elem.position - 50 > -elem.height
elem.height === null
? arr[index - 1].position < arr[index - 1].height!
: elem.position - 50 - this.stickyOffset > -elem.height
);

// Sets last section as active at the end of page in case there is not enough height for it to dynamically activate
Expand Down Expand Up @@ -659,7 +661,7 @@ class DDSTableOfContents extends HostListenerMixin(StableSelectorMixin(LitElemen
: ``}
<div
class="${ddsPrefix}-ce--table-of-contents__items-container"
style="position: sticky; top: ${stickyOffset && this.layout !== 'horizontal' ? `${stickyOffset}px` : 0}"
style="position: sticky; top: ${stickyOffset && this.layout !== TOC_TYPES.HORIZONTAL ? `${stickyOffset}px` : 0}"
>
<div class="${prefix}--tableofcontents__desktop-container">
<div
Expand Down

0 comments on commit a5bb87e

Please sign in to comment.