link.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. """Components for rendering heading.
  2. https://www.radix-ui.com/themes/docs/theme/typography
  3. """
  4. from __future__ import annotations
  5. from typing import Literal
  6. from reflex.components.component import Component, MemoizationLeaf
  7. from reflex.components.core.breakpoints import Responsive
  8. from reflex.components.core.colors import color
  9. from reflex.components.core.cond import cond
  10. from reflex.components.el.elements.inline import A
  11. from reflex.components.markdown.markdown import MarkdownComponentMap
  12. from reflex.components.next.link import NextLink
  13. from reflex.utils.imports import ImportDict
  14. from reflex.vars.base import Var
  15. from ..base import LiteralAccentColor, RadixThemesComponent
  16. from .base import LiteralTextSize, LiteralTextTrim, LiteralTextWeight
  17. LiteralLinkUnderline = Literal["auto", "hover", "always", "none"]
  18. next_link = NextLink.create()
  19. class Link(RadixThemesComponent, A, MemoizationLeaf, MarkdownComponentMap):
  20. """A semantic element for navigation between pages."""
  21. tag = "Link"
  22. # Change the default rendered element for the one passed as a child, merging their props and behavior.
  23. as_child: Var[bool]
  24. # Text size: "1" - "9"
  25. size: Var[Responsive[LiteralTextSize]]
  26. # Thickness of text: "light" | "regular" | "medium" | "bold"
  27. weight: Var[Responsive[LiteralTextWeight]]
  28. # Removes the leading trim space: "normal" | "start" | "end" | "both"
  29. trim: Var[Responsive[LiteralTextTrim]]
  30. # Sets the visibility of the underline affordance: "auto" | "hover" | "always" | "none"
  31. underline: Var[LiteralLinkUnderline]
  32. # Overrides the accent color inherited from the Theme.
  33. color_scheme: Var[LiteralAccentColor]
  34. # Whether to render the text with higher contrast color
  35. high_contrast: Var[bool]
  36. # If True, the link will open in a new tab
  37. is_external: Var[bool]
  38. def add_imports(self) -> ImportDict:
  39. """Add imports for the Link component.
  40. Returns:
  41. The import dict.
  42. """
  43. return next_link._get_imports() # pyright: ignore [reportReturnType]
  44. @classmethod
  45. def create(cls, *children, **props) -> Component:
  46. """Create a Link component.
  47. Args:
  48. *children: The children of the component.
  49. **props: The props of the component.
  50. Raises:
  51. ValueError: in case of missing children
  52. Returns:
  53. Component: The link component
  54. """
  55. props.setdefault("_hover", {"color": color("accent", 8)})
  56. href = props.get("href")
  57. is_external = props.pop("is_external", None)
  58. if is_external is not None:
  59. props["target"] = cond(is_external, "_blank", "")
  60. if href is not None:
  61. if not len(children):
  62. raise ValueError("Link without a child will not display")
  63. if "as_child" not in props:
  64. # Extract props for the NextLink, the rest go to the Link/A element.
  65. known_next_link_props = NextLink.get_props()
  66. next_link_props = {}
  67. for prop in props.copy():
  68. if prop in known_next_link_props:
  69. next_link_props[prop] = props.pop(prop)
  70. # If user does not use `as_child`, by default we render using next_link to avoid page refresh during internal navigation
  71. return super().create(
  72. NextLink.create(*children, **next_link_props),
  73. as_child=True,
  74. **props,
  75. )
  76. else:
  77. props["href"] = "#"
  78. return super().create(*children, **props)
  79. link = Link.create