reflex-dev / reflex

🕸️ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
20.46k stars 1.18k forks source link

Bug: is_external=True in rx.link breaks component rendering in hover_card and tooltip #4344

Open Seikened opened 2 weeks ago

Seikened commented 2 weeks ago

Describe the bug
When using is_external=True in an rx.link inside components such as hover_card and tooltip, the component fails to render. However, replacing is_external=True with target="_blank" allows the component to render correctly, enabling the link to open in a new tab as expected. The Reflex documentation recommends is_external=True as a modern replacement for target="_blank", yet this implementation leads to rendering issues in advanced components, while target="_blank" works as intended.

To Reproduce

  1. Use the Bug Code Example below with is_external=True on an rx.link inside hover_card.
  2. Attempt to render the component.
    • Observed behavior: The component does not render.
  3. Replace is_external=True with target="_blank" as shown in the Functional Code Example below.
    • Observed behavior: The component renders correctly, and the link opens in a new tab.

Code/Link to Repo

Bug Code Example (is_external=True)

import reflex as rx
from blog.styles.styles import Size
from blog.components.info_text import info_text

def link_icon(icon:bool=True,link_imagen:str ="",color: str = "white", icon_name: str = "github",tamano:str = Size.BIG.value,url:str = "/", title:str = "title", subtitle:str = "subtitle") -> rx.Component:
    transition="all 0.3s"
    hover ={
        "scale": 1.2,
    }
    color_schema="gray"
    color_badge: str = "white"
    if icon:
        return rx.hover_card.root(
                rx.hover_card.trigger(
                    rx.link(
                        rx.icon(
                            tag=icon_name,
                            width=tamano,
                            height=tamano,
                            color=color,
                            transition=transition,
                            _hover=hover,
                        ),
                        href=url,
                        is_external=True,  # Causes component to fail to render
                    ),
                ),
                rx.hover_card.content(
                    info_text(
                        title, 
                        subtitle,
                        color=color_badge,
                        color_schema=color_schema
                    ), 
                ),
            )

    else:
        return rx.hover_card.root(
                rx.hover_card.trigger(
                    rx.link(
                        rx.image(
                            src=link_imagen,
                            width=tamano,
                            height=tamano,
                            transition=transition,
                            _hover=hover,
                        ),
                        href=url,
                        is_external=True,  # Causes component to fail to render
                    ),
                ),
                rx.hover_card.content(
                    info_text(
                        title, 
                        subtitle,
                        color=color_badge,
                        color_schema=color_schema
                    ), 
                ),
            )

Functional Code Example (target="_blank")

import reflex as rx
from blog.styles.styles import Size
from blog.components.info_text import info_text

def link_icon(icon:bool=True,link_imagen:str ="",color: str = "white", icon_name: str = "github",tamano:str = Size.BIG.value,url:str = "/", title:str = "title", subtitle:str = "subtitle") -> rx.Component:
    transition="all 0.3s"
    hover ={
        "scale": 1.2,
    }
    color_schema="gray"
    color_badge: str = "white"
    if icon:
        return rx.hover_card.root(
                rx.hover_card.trigger(
                    rx.link(
                        rx.icon(
                            tag=icon_name,
                            width=tamano,
                            height=tamano,
                            color=color,
                            transition=transition,
                            _hover=hover,
                        ),
                        href=url,
                        target="_blank",  # This works as expected
                    ),
                ),
                rx.hover_card.content(
                    info_text(
                        title, 
                        subtitle,
                        color=color_badge,
                        color_schema=color_schema
                    ), 
                ),
            )

    else:
        return rx.hover_card.root(
                rx.hover_card.trigger(
                    rx.link(
                        rx.image(
                            src=link_imagen,
                            width=tamano,
                            height=tamano,
                            transition=transition,
                            _hover=hover,
                        ),
                        href=url,
                        target="_blank",  # This works as expected
                    ),
                ),
                rx.hover_card.content(
                    info_text(
                        title, 
                        subtitle,
                        color=color_badge,
                        color_schema=color_schema
                    ), 
                ),
            )

Expected behavior
The expected behavior is for is_external=True to render the component as target="_blank" does, without causing any rendering issues.

Screenshots
Please see the attached screenshots showing:

  1. The error when using is_external=True

    Captura de pantalla 2024-11-10 a la(s) 1 02 03 a m
  2. The successful rendering using target="_blank"

    Captura de pantalla 2024-11-10 a la(s) 1 01 34 a m

Specifics:

Additional context
This issue appears when using is_external=True in hover_card or tooltip. Reflex documentation encourages the use of is_external=True as a best practice, but the current implementation is not functional in these specific components.

linear[bot] commented 2 weeks ago

ENG-4087 Bug: is_external=True in rx.link breaks component rendering in hover_card and tooltip

ElijahAhianyo commented 2 weeks ago

is_external = True is implicitly mapped to target= rx.cond(True, "_blank", ""). Issue is with the cond statement which is surprising. If you modify your code to

...
rx.link(
  href=url,
  target=rx.cond(True, "_blank", "_self"),
),

You'd see that it doesn't render the hovercard either. Will investigate this