Hero.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { useRouter } from "next/router"
  2. import Image, { StaticImageData } from "next/legacy/image"
  3. import { CSSProperties } from "react"
  4. import { getDirForLocale } from "../utils/locales"
  5. import defaultMobileImage from "../public/illustrations/default_hero_mobile.png"
  6. import defaultDesktopImage from "../public/illustrations/default_hero_desktop.png"
  7. import classNames from "classnames"
  8. export type HeroProps = {
  9. /** Static import of mobile image */
  10. mobileImage?: StaticImageData
  11. /** Static import of desktop image */
  12. desktopImage?: StaticImageData
  13. /** Text content */
  14. children: React.ReactNode
  15. /** Large, centered hero style used on the homepage */
  16. homepage?: boolean
  17. /** Adds a text shadow to the hero's content */
  18. safeTextShadow?: boolean
  19. /** Don't set a height on the container **/
  20. noHeight?: boolean
  21. }
  22. /**
  23. * Illustrated hero component used at the top of all pages.
  24. *
  25. * The height of the hero is calculated from:
  26. * `(the height of the image / 2)`
  27. * so @2x images are required.
  28. */
  29. const Hero = ({
  30. mobileImage = defaultMobileImage,
  31. desktopImage = defaultDesktopImage,
  32. children,
  33. homepage,
  34. safeTextShadow = true,
  35. noHeight,
  36. }: HeroProps) => {
  37. const { locale } = useRouter()
  38. const dir = getDirForLocale(locale)
  39. return (
  40. <section
  41. className={classNames(
  42. "full-width-bg relative pt-[var(--header-area)] text-white",
  43. noHeight ? "" : "h-[var(--mobile-hero-height)]",
  44. noHeight
  45. ? ""
  46. : homepage
  47. ? "2xl:h-[var(--desktop-hero-height)]"
  48. : "xl:h-[var(--desktop-hero-height)]"
  49. )}
  50. style={
  51. {
  52. "--desktop-hero-height": `${desktopImage.height / 2}px`,
  53. "--mobile-hero-height": `${mobileImage.height / 2}px`,
  54. } as CSSProperties
  55. }
  56. >
  57. {homepage ? (
  58. <div
  59. className={classNames(
  60. "full-width-bg__inner flex flex-col items-center justify-center py-20 text-center",
  61. {
  62. "drop-shadow-safe-text": safeTextShadow,
  63. }
  64. )}
  65. >
  66. {children}
  67. </div>
  68. ) : (
  69. <div className="full-width-bg__inner grid py-20 drop-shadow-safe-text lg:grid-cols-12 lg:justify-center lg:gap-x-gutter">
  70. <div className="col-span-12 lg:col-span-7 xl:col-span-5 xl:col-start-2">
  71. {children}
  72. </div>
  73. </div>
  74. )}
  75. <div
  76. className={classNames(
  77. "absolute inset-0 -z-10 h-[var(--mobile-hero-height)]",
  78. homepage ? "md:ms-[-25%] 2xl:hidden" : "xl:hidden",
  79. homepage
  80. ? "2xl:h-[var(--desktop-hero-height)]"
  81. : "xl:h-[var(--desktop-hero-height)]",
  82. dir === "rtl" && "-scale-x-100"
  83. )}
  84. >
  85. <Image
  86. src={mobileImage}
  87. alt=""
  88. layout="fill"
  89. objectFit="cover"
  90. objectPosition="center bottom"
  91. placeholder="empty"
  92. unoptimized
  93. priority={true}
  94. />
  95. </div>
  96. <div
  97. className={classNames(
  98. "absolute inset-0 -z-10 hidden h-[var(--mobile-hero-height)]",
  99. homepage ? "2xl:block" : "xl:block",
  100. homepage
  101. ? "2xl:h-[var(--desktop-hero-height)]"
  102. : "xl:h-[var(--desktop-hero-height)]",
  103. dir === "rtl" && "-scale-x-100"
  104. )}
  105. >
  106. <Image
  107. className="desktop-hero"
  108. src={desktopImage}
  109. alt=""
  110. layout="fill"
  111. objectFit="cover"
  112. objectPosition="center bottom"
  113. placeholder="empty"
  114. unoptimized
  115. priority={true}
  116. />
  117. </div>
  118. </section>
  119. )
  120. }
  121. export default Hero