feat(resources): implement breadcrumbs

This commit is contained in:
Jean-Philippe Sirois
2019-08-12 22:40:15 -04:00
parent da3f21d4d6
commit 809678383a
7 changed files with 120 additions and 24 deletions
@@ -0,0 +1,47 @@
import React from "react"
import { IFileOrFolder } from "../ResourcesSidebar/index"
import ChevronUp from "../../icons/chevron-up.svg"
import { traversePaths } from "../../utils"
import * as SC from "./styles"
interface ResourceBreadcrumbProps {
relativePath: any
}
function Link({ item }: { item: IFileOrFolder }) {
return <SC.StyledLink to={item.path}>{item.title}</SC.StyledLink>
}
function flatten([
currNode,
...previousNodes
]: IFileOrFolder[]): IFileOrFolder[] {
if (currNode.type === "file") {
return [...previousNodes, currNode]
}
return flatten([...currNode.children, ...previousNodes, currNode])
}
export function ResourceBreadcrumb({ relativePath }: ResourceBreadcrumbProps) {
const paths = relativePath.split("/")
const breadcrumbItems = flatten([traversePaths(paths)])
return (
<SC.ResourceBreadcrumbWrapper>
{breadcrumbItems.map(item => {
if (item.type === "folder") {
return (
<SC.LinkWrapper>
<Link item={item} />
<ChevronUp />
</SC.LinkWrapper>
)
}
return <SC.CurrentPage>{item.title}</SC.CurrentPage>
})}
</SC.ResourceBreadcrumbWrapper>
)
}
@@ -0,0 +1,38 @@
import styled from "styled-components"
import { Link } from "gatsby"
export const ResourceBreadcrumbWrapper = styled.div`
display: flex;
align-items: flex-start;
`
export const LinkWrapper = styled.div`
display: flex;
align-items: center;
height: 30px;
svg {
width: 12px;
transform: rotate(90deg);
margin: 6px;
}
svg path {
fill: #04b0a6;
}
`
export const StyledLink = styled(Link)`
color: #04b0a6;
cursor: pointer;
&:hover {
color: #045551;
}
`
export const CurrentPage = styled.div`
display: flex;
align-items: center;
height: 30px;
`
+5
View File
@@ -2,9 +2,11 @@ import React, { Fragment } from "react"
import { StackedAvatars } from "../StackedAvatars"
import ChevronUp from "../../icons/chevron-up.svg"
import { ResourceBreadcrumb } from "../ResourceBreadcrumb"
import * as SC from "./styles"
interface ResourceHeaderProps {
relativePath: any
title: any
authors: any
createdAt: any
@@ -42,6 +44,7 @@ function ExtraLink({
}
export function ResourceHeader({
relativePath,
title,
authors,
createdAt,
@@ -57,6 +60,8 @@ export function ResourceHeader({
return (
<SC.ResourceHeaderWrapper>
<ResourceBreadcrumb relativePath={relativePath} />
<SC.Title>{title}</SC.Title>
<SC.Top>
+1
View File
@@ -18,6 +18,7 @@ export const Title = styled.h1`
font-size: ${modularScale(6).fontSize}px;
line-height: ${modularScale(6).lineHeight}px;
letter-spacing: -1.75px;
margin-top: 0;
`
export const Meta = styled.div`
@@ -1,6 +1,7 @@
import partition from "ramda/es/partition"
import chain from "ramda/es/chain"
import { traversePaths } from "../../utils"
import {
IFileOrFolder,
IFile,
@@ -9,29 +10,6 @@ import {
IFileQuery,
} from "./index"
function traverse(
[head, ...tail]: string[],
basePath = "/resources"
): IFileOrFolder {
const path = basePath + "/" + head
const isFile = !tail.length
if (isFile) {
// probably not more than one dot
const [name] = head.split(".")
return {
title: name,
type: "file",
path,
}
}
return {
title: head,
type: "folder",
path,
children: [traverse(tail, path)],
}
}
function generateFolder({
title,
path,
@@ -85,7 +63,7 @@ function join([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] {
export default function useBuildTree(resources: IAllResourcesQuery) {
const objects = resources.allFile.edges.map(({ node: file }: IFileQuery) =>
traverse(file.relativePath.split("/"))
traversePaths(file.relativePath.split("/"))
)
return join(objects)
+3
View File
@@ -6,12 +6,14 @@ import { ResourceHeader } from "../components/ResourceHeader"
// @todo maybe find alternative type for data
function LanguagePost({ data }: any) {
const { relativePath } = data.file
const { html, fields, frontmatter, timeToRead } = data.file.post
console.log(data)
return (
<Fragment>
<SEO title={frontmatter.title} />
<ResourceHeader
relativePath={relativePath}
title={frontmatter.title}
authors={fields.authors}
createdAt={frontmatter.created_at}
@@ -29,6 +31,7 @@ export default LanguagePost
export const query = graphql`
query LanguagePost($file: String!) {
file(relativePath: { eq: $file }) {
relativePath
post: childMarkdownRemark {
html
fields {
+24
View File
@@ -0,0 +1,24 @@
import { IFileOrFolder } from "../components/ResourcesSidebar/index"
export function traversePaths(
[head, ...tail]: string[],
basePath = "/resources"
): IFileOrFolder {
const path = basePath + "/" + head
const isFile = !tail.length
if (isFile) {
// probably not more than one dot
const [name] = head.split(".")
return {
title: name,
type: "file",
path,
}
}
return {
title: head,
type: "folder",
path,
children: [traversePaths(tail, path)],
}
}