import { type ReactElement, type ReactNode } from "react"; import type { TocEntry } from "../../blog/types.js"; /** * Props for {@link BlogSidebar}. */ export interface BlogSidebarProps { /** The post's heading minimap; when empty, no table of contents is rendered. */ toc: TocEntry[]; /** Heading shown above the minimap, doubling as the mobile collapse toggle. Defaults to `"On this page"`. */ title?: string; /** Heading shown above the similar-post cards. Defaults to `"Similar pages"`. */ similarTitle?: string; /** * The "similar posts" cards, pre-rendered by the (server) `BlogPage` so they can use its * `linkComponent`/`imgComponent`; omitted when there are no similar posts. */ similar?: ReactNode; } /** * The `BlogPage` sidebar: a docs-style heading minimap with jump links and an active-section * highlight that tracks scrolling, plus a "Similar pages" slot. * * This is a client component (the scroll-spy and mobile collapse need browser APIs and state). * It receives already-computed, serialisable data from the server `BlogPage`; the similar-post * cards arrive as a pre-rendered `similar` node so they keep the page's link/image components. * On viewports at/under the layout breakpoint the minimap collapses behind the heading toggle; * on wider viewports the stylesheet keeps it open and sticky. * * @param props - see {@link BlogSidebarProps}. * @returns the sidebar `