1
0

link.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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.colors import color
  8. from reflex.components.core.cond import cond
  9. from reflex.components.el.elements.inline import A
  10. from reflex.components.next.link import NextLink
  11. from reflex.utils import imports
  12. from reflex.vars import Var
  13. from ..base import (
  14. LiteralAccentColor,
  15. RadixThemesComponent,
  16. )
  17. from .base import (
  18. LiteralTextSize,
  19. LiteralTextTrim,
  20. LiteralTextWeight,
  21. )
  22. LiteralLinkUnderline = Literal["auto", "hover", "always", "none"]
  23. next_link = NextLink.create()
  24. class Link(RadixThemesComponent, A, MemoizationLeaf):
  25. """A semantic element for navigation between pages."""
  26. tag = "Link"
  27. # Change the default rendered element for the one passed as a child, merging their props and behavior.
  28. as_child: Var[bool]
  29. # Text size: "1" - "9"
  30. size: Var[LiteralTextSize]
  31. # Thickness of text: "light" | "regular" | "medium" | "bold"
  32. weight: Var[LiteralTextWeight]
  33. # Removes the leading trim space: "normal" | "start" | "end" | "both"
  34. trim: Var[LiteralTextTrim]
  35. # Sets the visibility of the underline affordance: "auto" | "hover" | "always" | "none"
  36. underline: Var[LiteralLinkUnderline]
  37. # Overrides the accent color inherited from the Theme.
  38. color_scheme: Var[LiteralAccentColor]
  39. # Whether to render the text with higher contrast color
  40. high_contrast: Var[bool]
  41. # If True, the link will open in a new tab
  42. is_external: Var[bool]
  43. def _get_imports_list(self) -> list[imports.ImportVar]:
  44. return [*super()._get_imports_list(), *next_link._get_imports_list()]
  45. @classmethod
  46. def create(cls, *children, **props) -> Component:
  47. """Create a Link component.
  48. Args:
  49. *children: The children of the component.
  50. **props: The props of the component.
  51. Raises:
  52. ValueError: in case of missing children
  53. Returns:
  54. Component: The link component
  55. """
  56. props.setdefault(":hover", {"color": color("accent", 8)})
  57. is_external = props.pop("is_external", None)
  58. if is_external is not None:
  59. props["target"] = cond(is_external, "_blank", "")
  60. if props.get("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. return super().create(*children, **props)