Skip to content

Commit

Permalink
Merge pull request #1120 from newrelic/develop
Browse files Browse the repository at this point in the history
fix: Navigation in Tabs Component
  • Loading branch information
akashreddy-nr authored Feb 5, 2025
2 parents 50b8ccb + 35b50c0 commit 6b6bbec
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 4 deletions.
23 changes: 23 additions & 0 deletions demo/src/content/build-apps/build-hello-world-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,26 @@ Now that you've completed the steps in this example, you learned the basic steps
- Publish the application to the New Relic One catalog so you can share it with your colleagues.
- Add details to the project in the catalog so users understand how to use it.
- Subscribe accounts to your application so other users can use it.


## Tabs

<Tabs>
<TabsBar>
<TabsBarItem id="tab-1">Tabs 1</TabsBarItem>
<TabsBarItem id="tab-2">Tabs 2</TabsBarItem>
<TabsBarItem id="tab-3">Tabs 3</TabsBarItem>
</TabsBar>
<TabsPages>
<TabsPageItem id="tab-1">
Tab 1
</TabsPageItem>
<TabsPageItem id="tab-2">
Tab 2
</TabsPageItem>
<TabsPageItem id="tab-3">
Tab 3
</TabsPageItem>

</TabsPages>
</Tabs>
6 changes: 6 additions & 0 deletions packages/gatsby-theme-newrelic/src/components/MDX.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import MDXTable from './MDXTable';
import MDXVideo from './MDXVideo';
import SideBySide from './SideBySide';
import Walkthrough from './Walkthrough';
import Tabs from './Tabs';

const defaultComponents = {
a: (props) => <MDXLink {...props} displayExternalIcon />,
Expand All @@ -33,6 +34,11 @@ const defaultComponents = {
Step: Walkthrough.Step,
table: MDXTable,
Video: MDXVideo,
Tabs: Tabs,
TabsBar: Tabs.Bar,
TabsBarItem: Tabs.BarItem,
TabsPageItem: Tabs.Page,
TabsPages: Tabs.Pages,
};

const MDX = ({ body, components }) => {
Expand Down
27 changes: 26 additions & 1 deletion packages/gatsby-theme-newrelic/src/components/Tabs/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ const Page = ({ index, children, id, className }) => {
const isSelected =
index === currentTabIndex || (currentTabIndex === undefined && index === 0);

// overide the default scrolling of mdx plugin
useEffect(() => {
const anchorClickHandler = (e) => {
e.preventDefault();
const targetId = e.currentTarget.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.scrollIntoView({
behavior: 'smooth',
});
}
history.pushState(null, null, `#${targetId}`);
};

const anchors = document.querySelectorAll('a[href^="#"]');
anchors.forEach((anchor) => {
anchor.addEventListener('click', anchorClickHandler);
});

return () => {
anchors.forEach((anchor) => {
anchor.removeEventListener('click', anchorClickHandler);
});
};
}, []);
useEffect(() => {
if (
tabpanel.current == null ||
Expand Down Expand Up @@ -68,7 +93,7 @@ const Page = ({ index, children, id, className }) => {
left: 1em;
transition-delay: 0ms, 0ms, 170ms;
transition-duration: 620ms, 620ms, 340ms;
transition-duration: 0ms, 620ms, 340ms;
transition-timing-function: cubic-bezier(0.55, 0, 0.45, 1);
transition-property: visibility, transform, opacity;
${!isSelected &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const Pages = ({ children }) => {
padding: 1em;
margin-bottom: 1em;
overflow: hidden;
position: relative;
@media screen and (max-width: ${mobileBreakpoint}) {
border-top: #afe2e3 solid 1px;
Expand Down
38 changes: 36 additions & 2 deletions packages/gatsby-theme-newrelic/src/components/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,37 @@ const Tabs = ({ children, initialTab = 0 }) => {

const location = useLocation();

const findPageIndexById = (pages, hash) => {
const findInChildren = (children, hash) => {
if (!Array.isArray(children)) {
return false;
}
for (const child of children) {
if (child.props?.id === hash) {
return true;
}
if (child.props?.children) {
if (findInChildren(child.props.children, hash)) {
return true;
}
}
}
return false;
};
for (let index = 0; index < pages.length; index++) {
const page = pages[index];
if (page.props?.id === hash) {
return index;
} else if (
page.props?.children &&
findInChildren(page.props.children, hash)
) {
return index;
}
}
return -1;
};

// this needs to run in a useEffect since the hash
// isn't available on the server during SSG.
// to put it another way, in order to have this work with SSG
Expand All @@ -51,8 +82,11 @@ const Tabs = ({ children, initialTab = 0 }) => {
// <Tabs.Pages>...</Tabs.Pages>
// </Tabs>
// ```
const bars = _tabBar.props.children;
const pages = tabPages.props.children;
const index = pages.findIndex((page) => page.props.id === hash);
// const index = pages.findIndex((page) => page.props.id === hash);
const index = findPageIndexById(pages, hash);
const isTabBar = bars.some((bar) => bar.props.id === hash);
if (index !== -1) {
// this is so the animation doesn't play on page load
// if the first tab is selected.
Expand All @@ -65,7 +99,7 @@ const Tabs = ({ children, initialTab = 0 }) => {
// header height
72;

window.scrollTo({ top: y, behavior: 'smooth' });
isTabBar && window.scrollTo({ top: y, behavior: 'smooth' });
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down

0 comments on commit 6b6bbec

Please sign in to comment.