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