diff --git a/ui/app/src/SideContext/SideContext.tsx b/ui/app/src/SideContext/SideContext.tsx index bb5bdd970..bc000e4e5 100644 --- a/ui/app/src/SideContext/SideContext.tsx +++ b/ui/app/src/SideContext/SideContext.tsx @@ -1,7 +1,6 @@ /** @jsx jsx */ -import { FC, ReactNode, RefObject, useEffect, useState } from 'react'; +import { FC, RefObject, useEffect, useState, useCallback } from 'react'; import { jsx, Box, NavLink, Flex, Theme } from 'theme-ui'; - import { Sidebar as AppSidebar, SidebarContext, @@ -14,27 +13,50 @@ export interface SideContext { } export const SideContext: FC = ({ pageRef }) => { - const [items, setItems] = useState(); + const [items, setItems] = useState(); + const [activeItem, setActiveItem] = useState(); + + const onScroll = useCallback(() => { + const curScroll = window.scrollY; + const pageScroll = pageRef?.current?.getBoundingClientRect().top || 0; + //find first anchor element that is above the scroll position + const curItem = items + ? items.find(el => { + const itemPos = el.getBoundingClientRect().top - pageScroll + 100; + console.log(curScroll, pageScroll, itemPos); + return itemPos > curScroll; + }) + : undefined; + + if (curItem !== activeItem) { + setActiveItem(curItem); + } + }, [activeItem, items, pageRef]); + useEffect(() => { - const links: ReactNode[] = []; + const links: Element[] = []; const pageEl = pageRef?.current; if (pageEl) { const anchors = pageEl.querySelectorAll('a[data-title]'); if (anchors.length > 0) { - anchors.forEach((anchor, index) => { - const href = anchor.getAttribute('href'); + anchors.forEach(el => { + const href = el.getAttribute('href'); if (href) { - links.push( - - {anchor.getAttribute('data-title')} - , - ); + links.push(el); } }); } } setItems(links.length ? links : undefined); }, [pageRef]); + + useEffect(() => { + window.addEventListener('scroll', onScroll, false); + onScroll(); + return () => { + window.removeEventListener('scroll', onScroll); + }; + }, [onScroll]); return ( @@ -51,7 +73,17 @@ export const SideContext: FC = ({ pageRef }) => { borderLeft: (t: Theme) => `1px solid ${t.colors?.shadow}`, }} > - {items} + + {items?.map((el, index) => ( + + {el.getAttribute('data-title')} + + ))} + )} diff --git a/ui/components/src/ThemeContext/ThemeContext.tsx b/ui/components/src/ThemeContext/ThemeContext.tsx index b9b3f108f..2740783fe 100644 --- a/ui/components/src/ThemeContext/ThemeContext.tsx +++ b/ui/components/src/ThemeContext/ThemeContext.tsx @@ -102,6 +102,17 @@ export const ThemeProvider: React.FC = ({ bg: 'action', }, }, + links: { + nav: { + fontWeight: 300, + fontSize: '14px', + lineHeight: '1.6rem', + '&.active': { + fontWeight: 700, + color: 'primary', + }, + }, + }, colors: { ...polaris.colors, gray: '#f6f6f6', @@ -130,6 +141,7 @@ export const ThemeProvider: React.FC = ({ dark, ); }, [dark, customTheme]); + return (