Hero.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { useRouter } from "next/router"
  2. import Image, { StaticImageData } from "next/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 ? "" : (homepage ? "2xl:h-[var(--desktop-hero-height)]" : "xl:h-[var(--desktop-hero-height)]")
  45. )}
  46. style={
  47. {
  48. "--desktop-hero-height": `${desktopImage.height / 2}px`,
  49. "--mobile-hero-height": `${mobileImage.height / 2}px`,
  50. } as CSSProperties
  51. }
  52. >
  53. {homepage ? (
  54. <div
  55. className={classNames(
  56. "full-width-bg__inner flex flex-col items-center justify-center py-20 text-center",
  57. {
  58. "drop-shadow-safe-text": safeTextShadow,
  59. }
  60. )}
  61. >
  62. {children}
  63. </div>
  64. ) : (
  65. <div className="full-width-bg__inner grid py-20 drop-shadow-safe-text lg:grid-cols-12 lg:justify-center lg:gap-x-gutter">
  66. <div className="col-span-12 lg:col-span-7 xl:col-span-5 xl:col-start-2">
  67. {children}
  68. </div>
  69. </div>
  70. )}
  71. <div
  72. className={classNames(
  73. "absolute inset-0 -z-10 h-[var(--mobile-hero-height)]",
  74. homepage ? "md:mis-[-25%] 2xl:hidden" : "xl:hidden",
  75. homepage ? "2xl:h-[var(--desktop-hero-height)]" : "xl:h-[var(--desktop-hero-height)]",
  76. dir === "rtl" && "-scale-x-100"
  77. )}
  78. >
  79. <Image
  80. src={mobileImage}
  81. alt=""
  82. layout="fill"
  83. objectFit="cover"
  84. objectPosition="center bottom"
  85. placeholder="empty"
  86. unoptimized
  87. priority={true}
  88. />
  89. </div>
  90. <div
  91. className={classNames(
  92. "absolute inset-0 -z-10 hidden h-[var(--mobile-hero-height)]",
  93. homepage ? "2xl:block" : "xl:block",
  94. homepage ? "2xl:h-[var(--desktop-hero-height)]" : "xl:h-[var(--desktop-hero-height)]",
  95. dir === "rtl" && "-scale-x-100"
  96. )}
  97. >
  98. <Image
  99. className="desktop-hero"
  100. src={desktopImage}
  101. alt=""
  102. layout="fill"
  103. objectFit="cover"
  104. objectPosition="center bottom"
  105. placeholder="empty"
  106. unoptimized
  107. priority={true}
  108. />
  109. </div>
  110. </section>
  111. )
  112. }
  113. export default Hero