Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/chronicle/src/components/ui/breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import { Link as RouterLink } from 'react-router'
interface BreadcrumbsProps {
slug: string[]
tree: Root
className?: string
}

export function Breadcrumbs({ slug, tree }: BreadcrumbsProps) {
export function Breadcrumbs({ slug, tree, className }: BreadcrumbsProps) {
const url = slug.length === 0 ? '/' : `/${slug.join('/')}`
const items = getBreadcrumbItems(url, tree, { includePage: true })

if (items.length === 0) return null

return (
<Breadcrumb size="small">
<Breadcrumb size="small" className={className}>
{items.flatMap((item, index) => {
const isCurrent = index === items.length - 1
const breadcrumbItem = (
Expand Down
4 changes: 4 additions & 0 deletions packages/chronicle/src/themes/paper/ChapterNav.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
flex-shrink: 0;
}

.subFolder {
margin-top: var(--rs-space-5);
}

.subLabel {
font-family: var(--paper-font-mono);
font-size: var(--rs-font-size-small);
Expand Down
2 changes: 1 addition & 1 deletion packages/chronicle/src/themes/paper/ChapterNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function ChapterItem({

if (item.type === 'folder') {
return (
<li>
<li className={styles.subFolder}>
<span className={styles.subLabel}>{item.name}</span>
<ul className={styles.chapterItems}>
{item.children.map(child => (
Expand Down
25 changes: 3 additions & 22 deletions packages/chronicle/src/themes/paper/Page.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,34 +68,12 @@
}

.breadcrumb {
display: flex;
align-items: center;
font-family: var(--paper-font-mono);
font-size: var(--rs-font-size-small);
line-height: var(--rs-line-height-small);
letter-spacing: var(--rs-letter-spacing-small);
}

.separator {
margin: 0 var(--rs-space-1);
color: var(--rs-color-foreground-base-tertiary);
}

.crumbLink {
color: var(--rs-color-foreground-base-tertiary);
font-weight: var(--rs-font-weight-medium);
text-decoration: none;
}

.crumbLink:hover {
color: var(--rs-color-foreground-base-primary);
}

.crumbActive {
color: var(--rs-color-foreground-base-primary);
font-weight: var(--rs-font-weight-medium);
}

.article {
flex: 1;
min-width: 0;
Expand Down Expand Up @@ -219,6 +197,9 @@
}

.content table {
display: block;
width: 100%;
overflow-x: auto;
margin-bottom: var(--rs-space-5);
}

Expand Down
31 changes: 5 additions & 26 deletions packages/chronicle/src/themes/paper/Page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
ArrowLeftIcon,
ArrowRightIcon,
ChevronRightIcon,
AdjustmentsHorizontalIcon,
EyeIcon,
SunIcon,
Expand All @@ -11,8 +10,8 @@ import {
import { IconButton, useTheme } from '@raystack/apsara';
import { useEffect, useMemo, useState } from 'react';
import { Link as RouterLink, useLocation } from 'react-router';
import { getBreadcrumbItems } from 'fumadocs-core/breadcrumb';
import { flattenTree } from 'fumadocs-core/page-tree';
import { Breadcrumbs } from '@/components/ui/breadcrumbs';
import type { ThemePageProps } from '@/types';
import styles from './Page.module.css';
import { useReaderMode } from './ReaderModeContext';
Expand All @@ -27,21 +26,14 @@ export function Page({ page, tree }: ThemePageProps) {

useEffect(() => { setIsClient(true); }, []);

const { prev, next, crumbs } = useMemo(() => {
const slug = pathname === '/' ? [] : pathname.replace(/^\//, '').split('/');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Normalize slug segments to avoid trailing-slash breadcrumb mismatches.

At Line 29, splitting pathname directly can leave empty segments (/guides/), which may produce incorrect breadcrumb URLs. Filter empty parts when deriving slug.

Suggested fix
-  const slug = pathname === '/' ? [] : pathname.replace(/^\//, '').split('/');
+  const slug =
+    pathname === '/'
+      ? []
+      : pathname.replace(/^\//, '').split('/').filter(Boolean);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const slug = pathname === '/' ? [] : pathname.replace(/^\//, '').split('/');
const slug =
pathname === '/'
? []
: pathname.replace(/^\//, '').split('/').filter(Boolean);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/chronicle/src/themes/paper/Page.tsx` at line 29, The slug derivation
can produce empty segments for paths with trailing slashes (e.g., "/guides/"),
causing breadcrumb URL mismatches; update the logic that computes slug (the
const slug variable that uses pathname) to trim leading/trailing slashes and
filter out empty parts after splitting (e.g., split on '/' and apply
.filter(Boolean) or equivalent) while preserving the root case so pathname ===
'/' still yields an empty array.


const { prev, next } = useMemo(() => {
const pages = flattenTree(tree.children);
const currentIndex = pages.findIndex(p => p.url === pathname);
const breadcrumbItems = getBreadcrumbItems(
pathname,
tree,
{ includePage: true }
);
return {
prev: currentIndex > 0 ? pages[currentIndex - 1] : null,
next: currentIndex < pages.length - 1 ? pages[currentIndex + 1] : null,
crumbs: breadcrumbItems.map(item => ({
label: item.name,
href: item.url ?? pathname,
})),
};
}, [tree, pathname]);

Expand Down Expand Up @@ -70,20 +62,7 @@ export function Page({ page, tree }: ThemePageProps) {
</span>
)}
</div>
<nav className={styles.breadcrumb}>
{crumbs.map((crumb, i) => (
<span key={crumb.href}>
{i > 0 && <ChevronRightIcon width={12} height={12} className={styles.separator} />}
{i === crumbs.length - 1 ? (
<span className={styles.crumbActive}>{crumb.label}</span>
) : (
<RouterLink to={crumb.href} className={styles.crumbLink}>
{crumb.label}
</RouterLink>
)}
</span>
))}
</nav>
<Breadcrumbs slug={slug} tree={tree} className={styles.breadcrumb} />
</div>
<div className={styles.navRight}>
{settingsOpen ? (
Expand Down
Loading