diff --git a/docs/app/tests/test_docs_site.py b/docs/app/tests/test_docs_site.py index f3c45aef..d8b1c25a 100644 --- a/docs/app/tests/test_docs_site.py +++ b/docs/app/tests/test_docs_site.py @@ -68,7 +68,7 @@ page_with_api_reference_toc, render_xy_markdown_page, ) -from xy_docs.navbar import XY_GITHUB_STARS, XY_REPOSITORY_URL, xy_docs_navbar +from xy_docs.navbar import XY_REPOSITORY_URL, xy_docs_navbar from xy_docs.sidebar import ( CHART_FAMILY_SIDEBAR_SECTIONS, CHART_GALLERY_SIDEBAR_LINK, @@ -2042,8 +2042,8 @@ def test_xy_sidebar_opens_only_the_current_chart_family( ) -def test_xy_mobile_navbar_uses_the_official_drawer_button() -> None: - """Match the official navbar while retaining its mobile drawer trigger.""" +def test_xy_navbar_uses_xy_links_github_and_the_official_drawer() -> None: + """Keep the XY navbar focused while retaining its mobile drawer trigger.""" component = xy_docs_navbar() assert isinstance(component, MemoComponent) @@ -2052,12 +2052,21 @@ def test_xy_mobile_navbar_uses_the_official_drawer_button() -> None: assert 'href:"/"' in rendered assert '"aria-label":"Reflex XY"' in rendered assert "M29 16H32V10H39V7H32V4H39V1H29V16" in rendered - assert 'href:"/docs/"' in rendered - assert 'href:"/docs/ai/overview/best-practices/"' in rendered - assert 'href:"/docs/getting-started/introduction/"' in rendered - assert 'href:"/docs/hosting/deploy-quick-start/"' in rendered assert 'href:"/docs/xy/"' in rendered - assert 'variant:"ghost"},"XY"' in rendered + assert 'href:"/docs/xy/integrations/reflex/"' in rendered + assert "Overview" in rendered + assert "Reflex Integration" in rendered + assert 'variant:"ghost"},"Build with AI"' not in rendered + assert 'variant:"ghost"},"Framework"' not in rendered + assert 'variant:"ghost"},"Cloud"' not in rendered + assert 'variant:"ghost"},"XY"' not in rendered + assert "Forum" not in rendered + assert "Discord Community" not in rendered + assert 'variant:"primary"' in rendered + assert "View XY on GitHub -" not in rendered + assert rendered.count("View XY on GitHub") == 2 + assert 'target:"_blank"' in rendered + assert 'rel:"noopener noreferrer"' in rendered assert "Open sidebar" in rendered assert "Menu01Icon" in rendered assert "Cancel01Icon" in rendered @@ -2065,9 +2074,6 @@ def test_xy_mobile_navbar_uses_the_official_drawer_button() -> None: assert " rx.Component: ) -def _menu_item(label: str, href: str, *, active: bool = False) -> rx.Component: +def _menu_item(label: str, href: str) -> rx.Component: """Render one desktop navbar item with the official treatment. Args: label: Visible item label. href: Destination URL. - active: Whether to render the active section underline. Returns: Official-style navigation menu item. """ - active_class = ( - "shadow-[inset_0_-1px_0_0_var(--primary-10)] " - "[&_button]:text-primary-10 [&_div]:text-primary-10" - if active - else "" - ) return ui.navigation_menu.item( rx.el.elements.a( button(label, size="sm", variant="ghost", native_button=False), href=href, class_name="no-underline", ), - class_name=ui.cn( - "hidden h-full items-center justify-center md:flex", - active_class, - ), + class_name="hidden h-full items-center justify-center md:flex", custom_attrs={"role": "menuitem"}, ) +def _github_button() -> rx.Component: + """Render the external XY repository link.""" + label = "View XY on GitHub" + return rx.el.elements.a( + button( + get_icon(icon="github_navbar", class_name="size-4 shrink-0"), + "GitHub", + custom_attrs={"aria-label": label}, + size="sm", + variant="primary", + native_button=False, + class_name="whitespace-nowrap", + ), + href=XY_REPOSITORY_URL, + target="_blank", + rel="noopener noreferrer", + aria_label=label, + ) + + def _navigation_menu() -> rx.Component: """Render the official desktop controls and mobile drawer trigger. @@ -101,8 +108,7 @@ def _navigation_menu() -> rx.Component: """ return ui.navigation_menu.root( ui.navigation_menu.list( - *(_menu_item(label, href) for label, href in _REFLEX_NAV_LINKS), - _menu_item("XY", "/docs/xy/", active=True), + *(_menu_item(label, href) for label, href in _XY_NAV_LINKS), class_name="m-0 flex h-full list-none flex-row items-center gap-2", custom_attrs={"role": "menubar"}, ), @@ -113,23 +119,9 @@ def _navigation_menu() -> rx.Component: custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( - rx.el.elements.a( - button( - get_icon(icon="github_navbar", class_name="size-4 shrink-0"), - str(XY_GITHUB_STARS), - custom_attrs={ - "aria-label": (f"View XY on GitHub - {XY_GITHUB_STARS} stars") - }, - size="sm", - variant="ghost", - ), - href=XY_REPOSITORY_URL, - target="_blank", - rel="noopener noreferrer", - aria_label=f"View XY on GitHub - {XY_GITHUB_STARS} stars", - ), + _github_button(), unstyled=True, - class_name="hidden xl:flex", + class_name="hidden md:flex", custom_attrs={"role": "menuitem"}, ), ui.navigation_menu.item( @@ -281,7 +273,6 @@ def xy_docs_navbar() -> rx.Component: __all__ = [ - "XY_GITHUB_STARS", "XY_REPOSITORY_URL", "xy_docs_logo", "xy_docs_navbar", diff --git a/docs/guides/deployment-recipes.md b/docs/guides/deployment-recipes.md index f56af485..784f08b0 100644 --- a/docs/guides/deployment-recipes.md +++ b/docs/guides/deployment-recipes.md @@ -156,20 +156,19 @@ assume the policies will merge into a working configuration. Follow for the current directives and security tradeoffs, and test the final response headers rather than only opening the file locally. -## Reflex live applications depend on an unreleased adapter +## Reflex live applications use the published adapter The [Reflex integration path](/docs/xy/integrations/reflex/) describes fixed, live-token, and state-backed application tiers, but it depends on the separate -`reflex-xy` adapter. That adapter is experimental and is not currently a -published package, so the integration guide is a preview rather than an -installable production recipe. - -Until a released adapter version is available, use core XY's standalone HTML, -PNG, or SVG outputs, or evaluate the adapter from source in a pinned test -environment. Do not place `pip install reflex-xy` in production automation and -assume it resolves from the public package index. When it is released, pin -both `xy` and `reflex-xy`, test their documented compatibility, and then follow -the live deployment boundary in the integration guide. +`reflex-xy` adapter. The adapter is published on PyPI, so install it with +`uv add reflex-xy` or `python -m pip install reflex-xy`. It remains +experimental. + +For production automation, commit the resolved uv lockfile or pin compatible +`xy` and `reflex-xy` versions in your requirements, test their documented +compatibility, and follow the live deployment boundary in the integration +guide. Core XY's standalone HTML, PNG, and SVG outputs remain available when a +live Reflex application is not required. For the capability-level decision, see [Choosing a runtime and deployment mode](/docs/xy/advanced/runtime-and-deployment/). diff --git a/docs/integrations/reflex.md b/docs/integrations/reflex.md index 438c9d4f..e3881a08 100644 --- a/docs/integrations/reflex.md +++ b/docs/integrations/reflex.md @@ -15,32 +15,22 @@ Reflex component. The core `xy` package stays framework-neutral: application state and events remain in Reflex while XY owns chart data, rendering, and interaction math. -~~~md alert warning -### Unreleased Adapter - -`reflex-xy` is not published on PyPI. The adapter is an opt-in prototype whose -API and event payloads may change before its first release. Install it from the -tagged Git subdirectory below; installing it by package name alone with uv or -pip will not work. -~~~ - ## Install and Configure -Pair the public `xy` 0.0.1 wheel with the adapter from the matching `v0.0.1` -repository tag. Pinning both sides avoids mixing an unreleased adapter revision -with a different core API: +Install `reflex-xy` from PyPI. It declares compatible `xy` and Reflex +dependencies: ~~~~md tabs ## uv ~~~bash -uv add "xy==0.0.1" "reflex-xy @ git+https://github.com/reflex-dev/xy.git@v0.0.1#subdirectory=python/reflex-xy" +uv add reflex-xy ~~~ ## pip ~~~bash -python -m pip install "xy==0.0.1" "reflex-xy @ git+https://github.com/reflex-dev/xy.git@v0.0.1#subdirectory=python/reflex-xy" +python -m pip install reflex-xy ~~~ ~~~~ diff --git a/docs/overview/installation.md b/docs/overview/installation.md index a6875ef0..630b0cc2 100644 --- a/docs/overview/installation.md +++ b/docs/overview/installation.md @@ -96,23 +96,23 @@ Rust tooling beyond the commands above. uv add pyarrow ~~~ -- The separate Reflex adapter supports state-backed application charts, but it - is experimental and is not published on PyPI. Opt in by pairing the released - `xy` core with the adapter from the matching `v0.0.1` Git tag. With uv: +- The separate `reflex-xy` adapter supports state-backed application charts + and is published on PyPI. It remains experimental. With uv: ~~~bash - uv add "xy==0.0.1" "reflex-xy @ git+https://github.com/reflex-dev/xy.git@v0.0.1#subdirectory=python/reflex-xy" + uv add reflex-xy ~~~ Or with pip: ~~~bash - python -m pip install "xy==0.0.1" "reflex-xy @ git+https://github.com/reflex-dev/xy.git@v0.0.1#subdirectory=python/reflex-xy" + python -m pip install reflex-xy ~~~ - The tag keeps the unreleased adapter aligned with the public 0.0.1 core. - Continue with the [Reflex integration guide](/docs/xy/integrations/reflex/) - for its current limitations and setup. + The adapter installs compatible `xy` and Reflex dependencies. Pin resolved + versions for production deployments. Continue with the + [Reflex integration guide](/docs/xy/integrations/reflex/) for its current + limitations and setup. - Native PNG is the default static raster path and does not launch a browser. Chromium-based PNG export is optional and discovers Chrome, Chromium, Edge, diff --git a/pr-assets/xy-navbar.jpg b/pr-assets/xy-navbar.jpg new file mode 100644 index 00000000..fb6ce5ca Binary files /dev/null and b/pr-assets/xy-navbar.jpg differ