brf/client/admin/components/navigation_group.tsx
2025-12-18 07:31:37 +01:00

73 lines
2.0 KiB
TypeScript

import { h, type FunctionComponent } from 'preact'
import { useEffect, useReducer, useRef } from 'preact/hooks'
import cn from 'classnames'
import NavigationItem from './navigation_item.tsx'
import s from './navigation.module.scss'
import type { Route } from '../../../shared/types.ts'
type NavigationGroupProps = {
base: string
currentPath: string
path: string
routes: Route[]
title: string
}
const NavigationGroup: FunctionComponent<NavigationGroupProps> = ({ base, currentPath, path, routes, title }) => {
const itemsRef = useRef<HTMLUListElement | null>(null)
const [visible, toggle] = useReducer((visible, force) => (typeof force === 'boolean' ? force : !visible), false)
const current = currentPath === path || (path !== '/' && currentPath.startsWith(path))
useEffect(() => {
itemsRef.current!.style.height = itemsRef.current!.scrollHeight + 'px'
}, [])
useEffect(() => {
toggle(false)
}, [currentPath])
return (
<li
className={cn(s.groupBase, {
[s.visible]: current || visible,
[s.current]: current,
})}
>
<div className={s.groupTop} onClick={toggle}>
<span className={s.groupTitle}>{title}</span>
<div className={s.groupIcon} />
</div>
<ul ref={itemsRef} className={s.items}>
{routes
.filter(({ nav }) => nav !== false)
.map(({ path, title, routes }) =>
routes ? (
<NavigationGroup
key={path}
base={base}
currentPath={currentPath}
path={path}
title={title}
routes={routes}
/>
) : (
<NavigationItem
key={path}
base={base}
currentPath={currentPath}
path={path}
title={title}
name={title.toLowerCase()}
/>
),
)}
</ul>
</li>
)
}
export default NavigationGroup