Skip to content

Commit

Permalink
docs: explain core logic
Browse files Browse the repository at this point in the history
  • Loading branch information
isqua committed Nov 25, 2023
1 parent 4b029ef commit 4c61ee8
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ So, from a bird's eye view, the structure is as follows:
1. [hooks/](./src/hooks) contains any general logic shared between components, like:
- [useRequestWithPlaceholder](./src/hooks/useRequestWithPlaceholder.ts) to fetch data. It works like an extremely simplified idea of react-query, that hook returns state of a query with some placeholders and flags
- [useFilter](./src/hooks/useFilter.ts) holds shared logic for filter inputs
1. [toc.json](./public/toc.json) is a data structure that API sends to the client. The structure was defined by the task requirements

## Deep Dive into TOC Builder

Components composition:

1. So, the [Root](./src/app/Root/Root.tsx) component fetches the data from “API” (a static JSON file, actually), detects current url and renders the `Menu` by passing props to it.
1. The [Menu](./src/features/toc/ui/Menu/Menu.tsx) component wraps all its content to the [MenuProvider](./src/features/toc/ui/Menu/Context/MenuProvider.tsx) that holds menu data, filtering state and methods.
1. Then the [Menu](./src/features/toc/ui/Menu/Menu.tsx) renders menu `Filter` and menu `List` components.
Expand All @@ -46,6 +49,21 @@ So, from a bird's eye view, the structure is as follows:
- plain `Item` simply renders a single page in the menu with the desired styles and attributes
- the `ItemToggle` renders an `Item` with a chevron and nested section. Independently manages the open/closed state so that only this subtree is rerendered when the state changes

Core logic:

1. So how does the [Section](./src/features/toc/ui/Menu/Section/Section.tsx) know which items need to be rendered? The top `Section` is rendered by the [List](./src/features/toc/ui/Menu/List/List.tsx) component, which passes the `parentId=''` property to the `Section`.
1. Then, `Section` uses the [useSectionItems](./src/features/toc/ui/Menu/Context/hooks.ts) hook, which extracts data from the MenuContext and passes it to the `buildMenuSection` method, gets items from it, and returns them back to the `Section`.
1. The [buildMenuSection](./src/features/toc/core/buildMenuSection.ts) is as plain as its name:
- it takes `parentId` and finds its direct children in the API data
- is takes `filter`, it sifts out mismatched pages
- it takes `breadcrumbs` (path to the active page in a tree) and adjust item highlight mode based on active page url and its ancestors

Finding ancestors of a current page:

1. To properly highlight menu sections we have to know current page, and its ancestors up to the root. The path to the current page from the root of the tree is called “breadcrumbs”.
1. The [getBreadCrumbs](./src/features/toc/core/getBreadCrumbs.ts) methods takes the current page URL and ToC data, and simply traverse from the current page up to the root, collecting all visited pages in a breadcrumbs array.
1. [MenuProvider](./src/features/toc/ui/Menu/Context/MenuProvider.tsx) takes current page URL and all ToC data from the API, calls `getBreadCrumbs` method and store the result in the context. If the current URL changes, we need to rebuild the breadcrumbs as well. And vice versa, if the path remains the same, we don't need to rebuild the breadcrumbs. So, we can store computed breadcrumbs in context to reuse them when highlighting menu sections.

## Available Scripts

In the project directory, you can run:
Expand Down
3 changes: 3 additions & 0 deletions src/features/toc/core/getBreadCrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import type { PageDescriptor, PageURL, PageId, TableOfContent } from '../types'
import { getCurrentPage } from './getCurrentPage'

/**
* Traverse the ToC data from the active page node to the root,
* collecting all visited pages in the breadcrumbs array
*
* @param toc The TOC data
* @param url Page URL
* @returns Current page and the array of its ancestors from top to bottom
Expand Down

0 comments on commit 4c61ee8

Please sign in to comment.