Add dynamic breadcrumbs to Header via React Context

Replace hardcoded "Coffee Project / Projects" with a BreadcrumbsContext
that each page registers into via useBreadcrumbs(). The Header reads
breadcrumb items dynamically, renders links for items with href, and
makes "Coffee Project" clickable to open the navigation drawer. Also
removes the unused currentScreenName from Redux appState.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniil
2026-02-19 22:25:27 +03:00
parent 674d5d735b
commit 42ce5fa0fe
10 changed files with 307 additions and 34 deletions
+6 -3
View File
@@ -7,6 +7,7 @@ import { Provider as ReduxProvider } from "react-redux"
import { store } from "@shared/store"
import { BreadcrumbsProvider } from "./BreadcrumbsContext"
import { QueryClientProvider } from "./QueryClientProvider"
import { UserSync } from "./UserSync"
@@ -19,9 +20,11 @@ export const AppProviders = ({
<ReduxProvider store={store}>
<QueryClientProvider>
<UserSync />
<Theme accentColor="violet" grayColor="slate" radius="medium">
{children}
</Theme>
<BreadcrumbsProvider>
<Theme accentColor="iris" grayColor="slate" radius="medium" scaling="100%">
{children}
</Theme>
</BreadcrumbsProvider>
</QueryClientProvider>
</ReduxProvider>
)
+52
View File
@@ -0,0 +1,52 @@
"use client"
import {
createContext,
type JSX,
type ReactNode,
useContext,
useEffect,
useState,
} from "react"
export interface BreadcrumbItem {
label: string
href?: string
}
interface BreadcrumbsContextValue {
items: BreadcrumbItem[]
setItems: (items: BreadcrumbItem[]) => void
}
const BreadcrumbsContext = createContext<BreadcrumbsContextValue>({
items: [],
setItems: () => {},
})
export const BreadcrumbsProvider = ({
children,
}: {
children: ReactNode
}): JSX.Element => {
const [items, setItems] = useState<BreadcrumbItem[]>([])
return (
<BreadcrumbsContext.Provider value={{ items, setItems }}>
{children}
</BreadcrumbsContext.Provider>
)
}
export const useBreadcrumbs = (items: BreadcrumbItem[]): void => {
const { setItems } = useContext(BreadcrumbsContext)
useEffect(() => {
setItems(items)
return () => setItems([])
}, [JSON.stringify(items)])
}
export const useBreadcrumbItems = (): BreadcrumbItem[] => {
return useContext(BreadcrumbsContext).items
}
+4 -11
View File
@@ -1,25 +1,18 @@
import type { PayloadAction } from "@reduxjs/toolkit"
import { createSlice } from "@reduxjs/toolkit"
import { AppState } from "./types"
const initialState: AppState = {
currentScreenName: "",
}
const initialState: AppState = {}
const appStateSlice = createSlice({
name: "appState",
initialState,
reducers: {
setCurrentScreenName(state, action: PayloadAction<string>) {
state.currentScreenName = action.payload
},
resetAppState(state) {
state.currentScreenName = initialState.currentScreenName
resetAppState() {
return initialState
},
},
})
export const { resetAppState, setCurrentScreenName } = appStateSlice.actions
export const { resetAppState } = appStateSlice.actions
export const appStateReducer = appStateSlice.reducer
+1 -3
View File
@@ -1,3 +1 @@
export interface AppState {
currentScreenName: string
}
export interface AppState {}