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:
@@ -73,12 +73,6 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-sharp`,
|
||||
{
|
||||
resolve: "gatsby-plugin-anchor-links",
|
||||
options: {
|
||||
offset: -100,
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-react-svg`,
|
||||
`gatsby-plugin-remove-trailing-slashes`,
|
||||
`gatsby-plugin-sharp`,
|
||||
|
||||
Generated
+19
-24
@@ -3753,6 +3753,15 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-scrollspy": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-scrollspy/-/react-scrollspy-3.3.2.tgz",
|
||||
"integrity": "sha512-nbCB4wg2AhsFWKZ0LnMqGZWWC+6fNOC4USCzvBC++YST7tLMGvQKLVdWCQHec5/HzSlrSD4UfnYYVcuSYIhvmg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/rimraf": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.4.tgz",
|
||||
@@ -10151,14 +10160,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gatsby-plugin-anchor-links": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-anchor-links/-/gatsby-plugin-anchor-links-1.1.1.tgz",
|
||||
"integrity": "sha512-mgSHUAEa7RRWD/lcmJVUWD9mIT14EIJvMPcxJ1W2Ev+rNuqBBpk1j4vDWy1uxas+qusi0vrtZ4HdU7mse12qDw==",
|
||||
"requires": {
|
||||
"scroll-to-element": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"gatsby-plugin-google-fonts": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-google-fonts/-/gatsby-plugin-google-fonts-1.0.1.tgz",
|
||||
@@ -17348,14 +17349,6 @@
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
|
||||
"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
|
||||
},
|
||||
"raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"requires": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"ramda": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz",
|
||||
@@ -17734,6 +17727,16 @@
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.7.2.tgz",
|
||||
"integrity": "sha512-u5l7fhAJXecWUJzVxzMRU2Zvw8m4QmDNHlTrT5uo3KBlYBhmChd7syAakBoay1yIiVhx/8Fi7a6v6kQZfsw81Q=="
|
||||
},
|
||||
"react-scrollspy": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/react-scrollspy/-/react-scrollspy-3.4.2.tgz",
|
||||
"integrity": "sha512-mFev6IBPPGdn0WsAiS0eCoHGUUet0ZRZUHHUw3qLcsvsQZPlubik0N9cf8CcgIbdVzNd04K9L9A0inHhPt7drw==",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"classnames": "^2.2.5",
|
||||
"prop-types": "^15.5.10"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
||||
@@ -18716,14 +18719,6 @@
|
||||
"invariant": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"scroll-to-element": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/scroll-to-element/-/scroll-to-element-2.0.3.tgz",
|
||||
"integrity": "sha512-5herPcm9jMfQgRwu94lH5mei+2YhipR4RQ2nAvnBxJb2tG+P7O0ctOKAaAZBXbBejnn+MImh3wrAUA5EcLnjEQ==",
|
||||
"requires": {
|
||||
"raf": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"scuid": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz",
|
||||
|
||||
+2
-1
@@ -33,7 +33,6 @@
|
||||
"@reach/router": "^1.3.3",
|
||||
"classnames": "^2.2.6",
|
||||
"gatsby": "^2.22.11",
|
||||
"gatsby-plugin-anchor-links": "^1.1.1",
|
||||
"gatsby-plugin-google-fonts": "^1.0.1",
|
||||
"gatsby-plugin-layout": "^1.3.2",
|
||||
"gatsby-plugin-manifest": "^2.4.9",
|
||||
@@ -57,6 +56,7 @@
|
||||
"react-highlight": "^0.12.0",
|
||||
"react-particles-js": "^3.2.1",
|
||||
"react-perfect-scrollbar": "^1.5.8",
|
||||
"react-scrollspy": "^3.4.2",
|
||||
"styled-components": "^5.1.1",
|
||||
"typescript": "^3.9.3"
|
||||
},
|
||||
@@ -72,6 +72,7 @@
|
||||
"@types/react": "^16.9.35",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react-helmet": "^6.0.0",
|
||||
"@types/react-scrollspy": "^3.3.2",
|
||||
"@types/styled-components": "^5.1.0",
|
||||
"babel-plugin-polished": "^1.1.0",
|
||||
"babel-plugin-styled-components": "^1.10.7",
|
||||
|
||||
@@ -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