Skip to content
Draft
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
44 changes: 35 additions & 9 deletions docs/app/reflex_docs/templates/docpage/docpage.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Template for documentation pages."""

import functools
from collections.abc import Callable, Collection
from datetime import datetime
from typing import Callable

import reflex as rx
import reflex_components_internal as ui
Expand All @@ -22,6 +22,35 @@
from reflex_site_shared.utils.docpage import right_sidebar_item_highlight
from reflex_site_shared.views.footer import dark_mode_toggle

_REGISTERED_DOC_ROUTES: set[str] = set()


def _normalize_doc_route(path: str) -> str:
"""Normalize a docs route to use leading and trailing slashes."""
route = f"/{path.strip('/')}"
return "/" if route == "/" else f"{route}/"


def _register_doc_route(path: str) -> None:
"""Track a route registered through the docpage template."""
_REGISTERED_DOC_ROUTES.add(_normalize_doc_route(path))


def _resolve_breadcrumb_href(
href: str, registered_routes: Collection[str] | None = None
) -> str:
"""Resolve a generated breadcrumb href to a registered docs route."""
routes = _REGISTERED_DOC_ROUTES if registered_routes is None else registered_routes
route = _normalize_doc_route(href)
if route in routes:
return route

overview_route = _normalize_doc_route(f"{route}overview")
if overview_route in routes:
return overview_route

return href


class FeedbackState(rx.State):
"""Minimal stub for feedback buttons (full implementation removed)."""
Expand Down Expand Up @@ -607,20 +636,16 @@ def breadcrumb(path: str, nav_sidebar: rx.Component, doc_content: str | None = N
docs_sidebar_drawer,
)

# Split the path into segments, removing 'docs' and capitalizing each segment
segments = [
segment.capitalize()
for segment in path.split("/")
if segment and segment != "docs"
]
# Split the path into segments, removing 'docs'.
segments = [segment for segment in path.split("/") if segment and segment != "docs"]

# Initialize an empty list to store the breadcrumbs and their separators
breadcrumbs = []

# Iteratively build the href for each segment (paths are app-relative, no /docs prefix)
current_path = ""
for i, segment in enumerate(segments):
current_path += f"/{segment.lower()}"
current_path += f"/{segment}"

# Add the breadcrumb item to the list
breadcrumbs.append(
Expand All @@ -629,7 +654,7 @@ def breadcrumb(path: str, nav_sidebar: rx.Component, doc_content: str | None = N
class_name="min-h-8 flex items-center text-sm font-[525] text-m-slate-12 dark:text-m-slate-3 last:text-m-slate-7 dark:last:text-m-slate-6 hover:text-primary-10 dark:hover:text-primary-9"
+ (" truncate" if i == len(segments) - 1 else ""),
underline="none",
href=current_path,
href=_resolve_breadcrumb_href(current_path),
)
)

Expand Down Expand Up @@ -713,6 +738,7 @@ def docpage(contents: Callable[[], Route]) -> Route:
The final route with the template applied.
"""
path = get_path(contents, "reflex-docs/pages") if set_path is None else set_path
_register_doc_route(path)

title = contents.__name__.replace("_", " ").title() if t is None else t

Expand Down
32 changes: 32 additions & 0 deletions docs/app/tests/test_breadcrumbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Tests for docs breadcrumbs."""

import importlib
import sys
from pathlib import Path

import reflex as rx

sys.path.append(str(Path(__file__).resolve().parent.parent))


def test_enterprise_parent_breadcrumb_uses_overview_route(monkeypatch):
"""Parent breadcrumbs should link to a real overview route when needed."""
docpage_module = importlib.import_module("reflex_docs.templates.docpage.docpage")
monkeypatch.setattr(
docpage_module,
"_REGISTERED_DOC_ROUTES",
{
"/enterprise/overview/",
"/enterprise/ag-grid/",
"/enterprise/ag-grid/pivot-mode/",
},
raising=False,
)

rendered = str(
docpage_module.breadcrumb("/enterprise/ag-grid/pivot-mode/", rx.box())
)

assert 'to:"/enterprise/overview/"' in rendered
assert 'to:"/enterprise/ag-grid/"' in rendered
assert 'to:"/enterprise/ag-grid/pivot-mode/"' in rendered
Loading