split page to smaller components

This commit is contained in:
Kim, Jimin 2021-12-17 13:31:10 +09:00
parent 150311472e
commit fd67ff2114
4 changed files with 192 additions and 172 deletions

View file

@ -0,0 +1,42 @@
import styled from "styled-components"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import {
faBook,
faCalendar,
faHourglass,
} from "@fortawesome/free-solid-svg-icons"
import { FetchedPage } from "../../types/typings"
import theming from "../../styles/theming"
const StyledMetaContainer = styled.div`
color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#555",
dark: "#CCC",
})};
`
const Meta = (props: { fetchedPage: FetchedPage }) => {
return (
<StyledMetaContainer>
<FontAwesomeIcon icon={faCalendar} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.date || "Unknown date"}
&nbsp;&nbsp;&nbsp;&nbsp;
<FontAwesomeIcon icon={faHourglass} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.readTime
? props.fetchedPage.readTime + " read"
: "unknown length"}
&nbsp;&nbsp;&nbsp;&nbsp;
<FontAwesomeIcon icon={faBook} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.wordCount
? props.fetchedPage.wordCount + " words"
: "unknown words"}
</StyledMetaContainer>
)
}
export default Meta

View file

@ -0,0 +1,69 @@
import styled from "styled-components"
import { Link } from "react-router-dom"
import theming from "../../styles/theming"
const StyledNextPrevContainer = styled.div`
display: flex;
justify-content: space-between;
size: 100%;
`
const StyledLink = styled(Link)`
${theming.styles.navbarButtonStyle}
background-color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#EEEEEE",
dark: "#202225",
})};
height: 1rem;
width: 2rem;
margin-top: 2rem;
line-height: 1rem;
text-align: center;
`
const StyledDisabledLink = styled.div`
font-size: 1rem;
border-radius: 0.5rem;
float: left;
padding: 14px 16px;
text-decoration: none;
transition: transform 0.1s linear;
color: grey;
background-color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#EEEEEE",
dark: "#202225",
})};
height: 1rem;
width: 2rem;
margin-top: 2rem;
line-height: 1rem;
text-align: center;
user-select: none;
`
const NextPrevButtons = (props: { prevURL?: string; nextURL?: string }) => {
return (
<StyledNextPrevContainer>
{props.prevURL ? (
<StyledLink to={props.prevURL}>prev</StyledLink>
) : (
<StyledDisabledLink>prev</StyledDisabledLink>
)}
{props.nextURL ? (
<StyledLink to={props.nextURL}>next</StyledLink>
) : (
<StyledDisabledLink>next</StyledDisabledLink>
)}
</StyledNextPrevContainer>
)
}
export default NextPrevButtons

View file

@ -0,0 +1,65 @@
import { useEffect, useState } from "react"
import { Collapse } from "react-collapse"
import storage from "local-storage-fallback"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { faCaretDown, faCaretUp } from "@fortawesome/free-solid-svg-icons"
import styled from "styled-components"
import theming from "../../styles/theming"
import { FetchedPage } from "../../types/typings"
const StyledTocToggleButton = styled.button`
border: none;
text-align: left;
background-color: rgba(0, 0, 0, 0);
width: 100%;
padding: 0.5rem;
color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "black",
dark: "white",
})};
`
const StyledCollapseContainer = styled.div`
* {
transition: height 200ms ease-out;
}
`
const Toc = (props: { fetchedPage: FetchedPage }) => {
const [isTocOpened, setIsTocOpened] = useState(
storage.getItem("isTocOpened") == "true"
)
useEffect(() => {
storage.setItem("isTocOpened", isTocOpened.toString())
}, [isTocOpened])
return (
<>
<StyledTocToggleButton
onClick={() => {
setIsTocOpened((prev) => !prev)
}}
>
<strong>Table of Content </strong>
{isTocOpened ? (
<FontAwesomeIcon icon={faCaretUp} />
) : (
<FontAwesomeIcon icon={faCaretDown} />
)}
</StyledTocToggleButton>
<StyledCollapseContainer>
<Collapse isOpened={isTocOpened}>
<div className="white-link">{props.fetchedPage.toc}</div>
</Collapse>
</StyledCollapseContainer>
<hr />
</>
)
}
export default Toc

View file

@ -1,31 +1,22 @@
import { useState } from "react" import { useState } from "react"
import { Helmet } from "react-helmet-async" import { Helmet } from "react-helmet-async"
import { Link, useLocation } from "react-router-dom" import { useLocation } from "react-router-dom"
import styled from "styled-components" import styled from "styled-components"
import { HashLink } from "react-router-hash-link" import { HashLink } from "react-router-hash-link"
import { Collapse } from "react-collapse"
import storage from "local-storage-fallback"
import { TocElement, FetchedPage, Map } from "../types/typings" import { TocElement, FetchedPage, Map } from "../../types/typings"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" import MainContent from "../../components/MainContent"
import { import Loading from "../../components/Loading"
faBook, import TagList from "../../components/TagList"
faCalendar, import Tag from "../../components/Tag"
faCaretDown, import NotFound from "../NotFound"
faCaretUp,
faHourglass,
} from "@fortawesome/free-solid-svg-icons"
import MainContent from "../components/MainContent" import NextPrevButtons from "./NextPrevButtons"
import Loading from "../components/Loading" import Meta from "./Meta"
import TagList from "../components/TagList" import Toc from "./Toc"
import Tag from "../components/Tag"
import NotFound from "./NotFound"
import theming from "../styles/theming" import _map from "../../data/map.json"
import _map from "../data/map.json"
import { useEffect } from "react" import { useEffect } from "react"
const map: Map = _map const map: Map = _map
@ -38,79 +29,6 @@ const StyledTitle = styled.h1`
margin-bottom: 1rem; margin-bottom: 1rem;
` `
const StyledNextPrevContainer = styled.div`
display: flex;
justify-content: space-between;
size: 100%;
`
const StyledLink = styled(Link)`
${theming.styles.navbarButtonStyle}
background-color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#EEEEEE",
dark: "#202225",
})};
height: 1rem;
width: 2rem;
margin-top: 2rem;
line-height: 1rem;
text-align: center;
`
const StyledDisabledLink = styled.div`
font-size: 1rem;
border-radius: 0.5rem;
float: left;
padding: 14px 16px;
text-decoration: none;
transition: transform 0.1s linear;
color: grey;
background-color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#EEEEEE",
dark: "#202225",
})};
height: 1rem;
width: 2rem;
margin-top: 2rem;
line-height: 1rem;
text-align: center;
user-select: none;
`
const StyledTocToggleButton = styled.button`
border: none;
text-align: left;
background-color: rgba(0, 0, 0, 0);
width: 100%;
padding: 0.5rem;
color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "black",
dark: "white",
})};
`
const StyledCollapseContainer = styled.div`
* {
transition: height 200ms ease-out;
}
`
const StyledMetaContainer = styled.div`
color: ${(props) =>
theming.theme(props.theme.currentTheme, {
light: "#555",
dark: "#CCC",
})};
`
function parseToc(tocData: TocElement[]) { function parseToc(tocData: TocElement[]) {
return ( return (
<ol> <ol>
@ -126,78 +44,6 @@ function parseToc(tocData: TocElement[]) {
) )
} }
const NextPrevButton = (props: { prevURL?: string; nextURL?: string }) => {
return (
<StyledNextPrevContainer>
{props.prevURL ? (
<StyledLink to={props.prevURL}>prev</StyledLink>
) : (
<StyledDisabledLink>prev</StyledDisabledLink>
)}
{props.nextURL ? (
<StyledLink to={props.nextURL}>next</StyledLink>
) : (
<StyledDisabledLink>next</StyledDisabledLink>
)}
</StyledNextPrevContainer>
)
}
const PostMeta = (props: { fetchedPage: FetchedPage }) => {
return (
<StyledMetaContainer>
<FontAwesomeIcon icon={faCalendar} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.date || "Unknown date"}
&nbsp;&nbsp;&nbsp;&nbsp;
<FontAwesomeIcon icon={faHourglass} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.readTime
? props.fetchedPage.readTime + " read"
: "unknown length"}
&nbsp;&nbsp;&nbsp;&nbsp;
<FontAwesomeIcon icon={faBook} />
&nbsp;&nbsp;&nbsp;
{props.fetchedPage.wordCount
? props.fetchedPage.wordCount + " words"
: "unknown words"}
</StyledMetaContainer>
)
}
const PageTOC = (props: { fetchedPage: FetchedPage }) => {
const [isTocOpened, setIsTocOpened] = useState(
storage.getItem("isTocOpened") == "true"
)
useEffect(() => {
storage.setItem("isTocOpened", isTocOpened.toString())
}, [isTocOpened])
return (
<>
<StyledTocToggleButton
onClick={() => {
setIsTocOpened((prev) => !prev)
}}
>
<strong>Table of Content </strong>
{isTocOpened ? (
<FontAwesomeIcon icon={faCaretUp} />
) : (
<FontAwesomeIcon icon={faCaretDown} />
)}
</StyledTocToggleButton>
<StyledCollapseContainer>
<Collapse isOpened={isTocOpened}>
<div className="white-link">{props.fetchedPage.toc}</div>
</Collapse>
</StyledCollapseContainer>
<hr />
</>
)
}
interface SeriesData { interface SeriesData {
seriesHome: string seriesHome: string
prev?: string prev?: string
@ -221,8 +67,8 @@ const Page = () => {
url: string url: string
) => { ) => {
return isContentUnsearchable return isContentUnsearchable
? await import(`../data/content/unsearchable${url}.json`) ? await import(`../../data/content/unsearchable${url}.json`)
: await import(`../data/content${url}.json`) : await import(`../../data/content${url}.json`)
} }
useEffect(() => { useEffect(() => {
@ -315,7 +161,7 @@ const Page = () => {
<StyledPage> <StyledPage>
{isSeries ? ( {isSeries ? (
<NextPrevButton <NextPrevButtons
prevURL={seriesData?.prev} prevURL={seriesData?.prev}
nextURL={seriesData?.next} nextURL={seriesData?.next}
/> />
@ -341,16 +187,14 @@ const Page = () => {
<br /> <br />
{/* Post metadata */} {/* Post metadata */}
{!isPageUnsearchable && ( {!isPageUnsearchable && <Meta fetchedPage={fetchedPage} />}
<PostMeta fetchedPage={fetchedPage} />
)}
</small> </small>
<hr /> <hr />
{/* add table of contents if it exists */} {/* add table of contents if it exists */}
{!!fetchedPage.toc?.props.children.length && ( {!!fetchedPage.toc?.props.children.length && (
<PageTOC fetchedPage={fetchedPage} /> <Toc fetchedPage={fetchedPage} />
)} )}
{/* page content */} {/* page content */}