Files
dify/web/app/components/develop/toc-panel.tsx
Stephen Zhou a84c2d36a3 style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

93 lines
3.9 KiB
TypeScript

'use client'
import type { TocItem } from './hooks/use-doc-toc'
import { cn } from '@langgenius/dify-ui/cn'
import { useTranslation } from 'react-i18next'
type TocPanelProps = {
toc: TocItem[]
activeSection: string
isTocExpanded: boolean
onToggle: (expanded: boolean) => void
onItemClick: (e: React.MouseEvent<HTMLAnchorElement>, item: TocItem) => void
}
const TocPanel = ({ toc, activeSection, isTocExpanded, onToggle, onItemClick }: TocPanelProps) => {
const { t } = useTranslation()
if (!isTocExpanded) {
return (
<button
type="button"
onClick={() => onToggle(true)}
className="group flex h-11 w-11 items-center justify-center rounded-full border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg transition-all duration-150 hover:bg-background-default-hover hover:shadow-xl"
aria-label="Open table of contents"
>
<span className="i-ri-list-unordered size-5 text-text-tertiary transition-colors group-hover:text-text-secondary" />
</button>
)
}
return (
<nav className="toc flex max-h-[calc(100vh-150px)] w-full flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-background-default-hover shadow-xl">
<div className="relative z-10 flex items-center justify-between border-b border-components-panel-border-subtle bg-background-default-hover px-4 py-2.5">
<span className="text-xs font-medium tracking-wide text-text-tertiary uppercase">
{t(($) => $['develop.toc'], { ns: 'appApi' })}
</span>
<button
type="button"
onClick={() => onToggle(false)}
className="group flex size-6 items-center justify-center rounded-md transition-colors hover:bg-state-base-hover"
aria-label="Close"
>
<span className="i-ri-close-line size-3 text-text-quaternary transition-colors group-hover:text-text-secondary" />
</button>
</div>
<div className="pointer-events-none absolute top-[41px] right-0 left-0 z-10 h-2 bg-linear-to-b from-components-panel-border-subtle/20 to-transparent"></div>
<div className="pointer-events-none absolute top-[43px] right-0 left-0 z-10 h-3 bg-linear-to-b from-background-default-hover to-transparent"></div>
<div className="relative flex-1 overflow-y-auto p-3 pt-1">
{toc.length === 0 ? (
<div className="px-2 py-8 text-center text-xs text-text-quaternary">
{t(($) => $['develop.noContent'], { ns: 'appApi' })}
</div>
) : (
<ul className="space-y-0.5">
{toc.map((item) => {
const isActive = activeSection === item.href.replace('#', '')
return (
<li key={item.href}>
<a
href={item.href}
onClick={(e) => onItemClick(e, item)}
className={cn(
'group relative flex items-center rounded-md px-3 py-2 text-[13px] transition-all duration-200',
isActive
? 'bg-state-base-hover font-medium text-text-primary'
: 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
)}
>
<span
className={cn(
'mr-2 size-1.5 rounded-full transition-all duration-200',
isActive
? 'scale-100 bg-text-accent'
: 'scale-75 bg-components-panel-border',
)}
/>
<span className="flex-1 truncate">{item.text}</span>
</a>
</li>
)
})}
</ul>
)}
</div>
<div className="pointer-events-none absolute inset-x-0 bottom-0 z-10 h-4 rounded-b-xl bg-linear-to-t from-background-default-hover to-transparent"></div>
</nav>
)
}
export default TocPanel