mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-04 09:15:58 +02:00
feat: implement collapsable first level tree
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import React, { useState } from "react"
|
||||
|
||||
interface SidebarProviderProps {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export interface SidebarContextInterface {
|
||||
current: number
|
||||
setCurrent: (index: number) => void
|
||||
}
|
||||
|
||||
export const SidebarContext = React.createContext<SidebarContextInterface | null>(
|
||||
null
|
||||
)
|
||||
|
||||
export function SidebarProvider({
|
||||
children,
|
||||
}: SidebarProviderProps): JSX.Element {
|
||||
const [current, setCurrent] = useState(0)
|
||||
|
||||
function selectFirstLevel(index: number) {
|
||||
setCurrent(index)
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarContext.Provider
|
||||
value={{
|
||||
current,
|
||||
setCurrent: selectFirstLevel,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SidebarContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { useStaticQuery, graphql } from "gatsby"
|
||||
import { GlobalStyles } from "../../globalStyles"
|
||||
import { ResourcesSidebar } from "../ResourcesSidebar"
|
||||
import * as SC from "./styles"
|
||||
import { SidebarProvider } from "../../SidebarProvider"
|
||||
|
||||
export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
||||
const data = useStaticQuery(graphql`
|
||||
@@ -24,7 +25,7 @@ export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
||||
`)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SidebarProvider>
|
||||
<GlobalStyles />
|
||||
<SC.Main>
|
||||
<ResourcesSidebar />
|
||||
@@ -35,6 +36,6 @@ export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
||||
</SC.Container>
|
||||
</SC.MainContent>
|
||||
</SC.Main>
|
||||
</div>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState } from "react"
|
||||
import Tree from "react-treeview"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
import useBuildTree from "./useBuildTree"
|
||||
import useSidebar from "./../../hooks/useSidebar"
|
||||
import banner from "../../images/tph-banner.png"
|
||||
import * as SC from "./styles"
|
||||
|
||||
@@ -57,20 +58,24 @@ const ALL_RESOURCES = graphql`
|
||||
}
|
||||
`
|
||||
|
||||
function plantTree(item: IFileOrFolder) {
|
||||
function plantTree(item: IFileOrFolder, index?: number, firstLevel?: boolean) {
|
||||
if (item.type === "file") {
|
||||
return (
|
||||
<SC.PageLink to={item.path} activeClassName="active">
|
||||
<SC.PageLink key={item.title} to={item.path} activeClassName="active">
|
||||
{item.title}
|
||||
</SC.PageLink>
|
||||
)
|
||||
}
|
||||
|
||||
return <Folder item={item} />
|
||||
if (firstLevel && index !== undefined) {
|
||||
return <FirstLevelFolder key={item.title} item={item} index={index} />
|
||||
}
|
||||
|
||||
return <Folder key={item.title} item={item} />
|
||||
}
|
||||
|
||||
function Folder({ item }: { item: IFolder }) {
|
||||
const [collapsed, setCollapse] = useState(false)
|
||||
const [collapsed, setCollapse] = useState(true)
|
||||
|
||||
function toggleCollapse() {
|
||||
setCollapse(prevState => !prevState)
|
||||
@@ -82,7 +87,23 @@ function Folder({ item }: { item: IFolder }) {
|
||||
collapsed={collapsed}
|
||||
nodeLabel={<div onClick={toggleCollapse}>{item.title}</div>}
|
||||
>
|
||||
{item.children.map(plantTree)}
|
||||
{item.children.map(node => plantTree(node))}
|
||||
</Tree>
|
||||
</SC.TreeWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
function FirstLevelFolder({ item, index }: { item: IFolder; index: number }) {
|
||||
const { current, setCurrent } = useSidebar()
|
||||
const collapsed = current !== index
|
||||
|
||||
return (
|
||||
<SC.TreeWrapper>
|
||||
<Tree
|
||||
collapsed={collapsed}
|
||||
nodeLabel={<div onClick={() => setCurrent(index)}>{item.title}</div>}
|
||||
>
|
||||
{item.children.map(node => plantTree(node))}
|
||||
</Tree>
|
||||
</SC.TreeWrapper>
|
||||
)
|
||||
@@ -95,7 +116,9 @@ export function ResourcesSidebar() {
|
||||
return (
|
||||
<SC.ResourcesSidebarWrapper>
|
||||
<SC.Banner src={banner} />
|
||||
<SC.Inner>{tree.map(node => plantTree(node))}</SC.Inner>
|
||||
<SC.Inner>
|
||||
{tree.map((node, index) => plantTree(node, index, true))}
|
||||
</SC.Inner>
|
||||
</SC.ResourcesSidebarWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useContext } from "react"
|
||||
import { SidebarContext, SidebarContextInterface } from "../SidebarProvider"
|
||||
|
||||
export default function useSidebar(): SidebarContextInterface {
|
||||
const sidebarContext = useContext(SidebarContext)
|
||||
|
||||
if (!sidebarContext) {
|
||||
throw Error("Need context")
|
||||
}
|
||||
|
||||
return sidebarContext
|
||||
}
|
||||
Reference in New Issue
Block a user