From 37d385e44b123b6f7a1293c346d99f58378fe3ab Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Fri, 1 May 2026 12:07:35 -0700 Subject: [PATCH] Fix docs breadcrumb overview routes --- .../reflex_docs/templates/docpage/docpage.py | 44 +++++++++++++++---- docs/app/tests/test_breadcrumbs.py | 32 ++++++++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 docs/app/tests/test_breadcrumbs.py diff --git a/docs/app/reflex_docs/templates/docpage/docpage.py b/docs/app/reflex_docs/templates/docpage/docpage.py index 96dfe4b5d6b..166922ceed5 100644 --- a/docs/app/reflex_docs/templates/docpage/docpage.py +++ b/docs/app/reflex_docs/templates/docpage/docpage.py @@ -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 @@ -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).""" @@ -607,12 +636,8 @@ 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 = [] @@ -620,7 +645,7 @@ def breadcrumb(path: str, nav_sidebar: rx.Component, doc_content: str | None = N # 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( @@ -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), ) ) @@ -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 diff --git a/docs/app/tests/test_breadcrumbs.py b/docs/app/tests/test_breadcrumbs.py new file mode 100644 index 00000000000..30f122c80ad --- /dev/null +++ b/docs/app/tests/test_breadcrumbs.py @@ -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