mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-04 09:15:58 +02:00
feat: implement scrollspy
This commit is contained in:
@@ -16,7 +16,7 @@ export const PageSidebarLink: FC<IPageSidebarLinkProps> = ({
|
||||
type = "internal",
|
||||
}) => {
|
||||
if (type === "anchor") {
|
||||
return <SC.Anchor to={href}>{text}</SC.Anchor>
|
||||
return <SC.Anchor href={href}>{text}</SC.Anchor>
|
||||
}
|
||||
|
||||
if (type === "external") {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AnchorLink } from "gatsby-plugin-anchor-links"
|
||||
import styled, { css } from "styled-components"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
@@ -13,7 +12,7 @@ const extraLink = css`
|
||||
}
|
||||
`
|
||||
|
||||
export const Anchor = styled(AnchorLink)`
|
||||
export const Anchor = styled.a`
|
||||
${extraLink};
|
||||
`
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import cx from "classnames"
|
||||
import React, { FC } from "react"
|
||||
import Scrollspy from "react-scrollspy"
|
||||
import { PageSidebarLink } from "../PageSidebarLink"
|
||||
import { ITocItem } from "../../types"
|
||||
import * as SC from "./styles"
|
||||
@@ -24,31 +26,40 @@ function extractTitle(title: string): ITitle {
|
||||
}
|
||||
|
||||
export const Toc: FC<ITocProps> = ({ header, items }) => {
|
||||
const windowGlobal = typeof window !== "undefined" && window
|
||||
const [scrollSpyCache, setScrollSpyCache] = React.useState<string>()
|
||||
|
||||
// window is not available on build
|
||||
if (!windowGlobal) {
|
||||
return null
|
||||
}
|
||||
|
||||
const { pathname } = windowGlobal.location
|
||||
return (
|
||||
<SC.TocWrapper>
|
||||
{header}
|
||||
{items.map((item) => {
|
||||
const { prefix, title } = extractTitle(item.title)
|
||||
<Scrollspy
|
||||
items={items.map((item) => item.link.substring(1))}
|
||||
currentClassName="scrollspy-current"
|
||||
scrolledPastClassName="scrollspy-past"
|
||||
componentTag={SC.ScrollspyWrapper}
|
||||
onUpdate={(updatedElement: HTMLDivElement) => {
|
||||
// @ts-ignore
|
||||
const id = updatedElement?.id
|
||||
if (id) {
|
||||
setScrollSpyCache(id)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{items.map((item) => {
|
||||
const { prefix, title } = extractTitle(item.title)
|
||||
|
||||
return (
|
||||
<SC.TocItem key={item.link} className={`depth-${item.depth}`}>
|
||||
{prefix}
|
||||
<PageSidebarLink
|
||||
href={`${pathname}${item.link}`}
|
||||
text={title}
|
||||
type="anchor"
|
||||
/>
|
||||
</SC.TocItem>
|
||||
)
|
||||
})}
|
||||
return (
|
||||
<SC.TocItem
|
||||
key={item.link}
|
||||
className={cx(`depth-${item.depth}`, {
|
||||
"scrollspy-cached": scrollSpyCache === item.link.substring(1),
|
||||
})}
|
||||
>
|
||||
{prefix}
|
||||
<PageSidebarLink href={item.link} text={title} type="anchor" />
|
||||
</SC.TocItem>
|
||||
)
|
||||
})}
|
||||
</Scrollspy>
|
||||
</SC.TocWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,15 +5,34 @@ export const TocWrapper = styled.div`
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
export const ScrollspyWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
export const TocItem = styled.div`
|
||||
display: inline-block;
|
||||
|
||||
&.depth-3 {
|
||||
margin-left: 8px;
|
||||
&.scrollspy-current,
|
||||
&.scrollspy-cached {
|
||||
position: relative;
|
||||
text-shadow: 0 0 0.65px ${(props) => props.theme.main.foreground},
|
||||
0 0 0.65px ${(props) => props.theme.main.foreground};
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -16px;
|
||||
content: "";
|
||||
display: block;
|
||||
background: ${(props) => props.theme.main.foreground};
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.depth-2 + &.depth-2,
|
||||
&.depth-3 + &.depth-2 {
|
||||
margin-top: 8px;
|
||||
&.depth-2,
|
||||
&.depth-3 {
|
||||
padding: 4px 0;
|
||||
}
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user