mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-07 23:43:57 +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 { GlobalStyles } from "../../globalStyles"
|
||||||
import { ResourcesSidebar } from "../ResourcesSidebar"
|
import { ResourcesSidebar } from "../ResourcesSidebar"
|
||||||
import * as SC from "./styles"
|
import * as SC from "./styles"
|
||||||
|
import { SidebarProvider } from "../../SidebarProvider"
|
||||||
|
|
||||||
export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
||||||
const data = useStaticQuery(graphql`
|
const data = useStaticQuery(graphql`
|
||||||
@@ -24,7 +25,7 @@ export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<SidebarProvider>
|
||||||
<GlobalStyles />
|
<GlobalStyles />
|
||||||
<SC.Main>
|
<SC.Main>
|
||||||
<ResourcesSidebar />
|
<ResourcesSidebar />
|
||||||
@@ -35,6 +36,6 @@ export function ResourcesLayout({ children }: PropsWithChildren<{}>) {
|
|||||||
</SC.Container>
|
</SC.Container>
|
||||||
</SC.MainContent>
|
</SC.MainContent>
|
||||||
</SC.Main>
|
</SC.Main>
|
||||||
</div>
|
</SidebarProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { useState } from "react"
|
|||||||
import Tree from "react-treeview"
|
import Tree from "react-treeview"
|
||||||
import { useStaticQuery, graphql } from "gatsby"
|
import { useStaticQuery, graphql } from "gatsby"
|
||||||
import useBuildTree from "./useBuildTree"
|
import useBuildTree from "./useBuildTree"
|
||||||
|
import useSidebar from "./../../hooks/useSidebar"
|
||||||
import banner from "../../images/tph-banner.png"
|
import banner from "../../images/tph-banner.png"
|
||||||
import * as SC from "./styles"
|
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") {
|
if (item.type === "file") {
|
||||||
return (
|
return (
|
||||||
<SC.PageLink to={item.path} activeClassName="active">
|
<SC.PageLink key={item.title} to={item.path} activeClassName="active">
|
||||||
{item.title}
|
{item.title}
|
||||||
</SC.PageLink>
|
</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 }) {
|
function Folder({ item }: { item: IFolder }) {
|
||||||
const [collapsed, setCollapse] = useState(false)
|
const [collapsed, setCollapse] = useState(true)
|
||||||
|
|
||||||
function toggleCollapse() {
|
function toggleCollapse() {
|
||||||
setCollapse(prevState => !prevState)
|
setCollapse(prevState => !prevState)
|
||||||
@@ -82,7 +87,23 @@ function Folder({ item }: { item: IFolder }) {
|
|||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
nodeLabel={<div onClick={toggleCollapse}>{item.title}</div>}
|
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>
|
</Tree>
|
||||||
</SC.TreeWrapper>
|
</SC.TreeWrapper>
|
||||||
)
|
)
|
||||||
@@ -95,7 +116,9 @@ export function ResourcesSidebar() {
|
|||||||
return (
|
return (
|
||||||
<SC.ResourcesSidebarWrapper>
|
<SC.ResourcesSidebarWrapper>
|
||||||
<SC.Banner src={banner} />
|
<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>
|
</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