Skip to content

Commit e29ba17

Browse files
authored
Update donation page (#1054)
* add new donation tab box * move GH logo to logos folder * add more logos * remove background from logos * add corporate sponsorship icon * change order * add usehooks lib and styles mobile view
1 parent 5a7e246 commit e29ba17

File tree

10 files changed

+383
-152
lines changed

10 files changed

+383
-152
lines changed

components/DonateTabs.tsx

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@headlessui/react"
2+
import Image from "next/image"
3+
import { FC, PropsWithChildren, ReactNode } from "react"
4+
import { defineMessages, FormattedMessage, useIntl } from "react-intl"
5+
6+
import { DonatePopup } from "../donate/DonatePopup"
7+
import ExternalLinkIcon from "../public/ui/external-link.svg?inline"
8+
import deFlagIcon from "../public/german_flag_icon_round.svg"
9+
import usFlagIcon from "../public/united_states_flag_icon_round.svg"
10+
import gitHubLogo from "../public/logos/github.svg"
11+
import patreonLogo from "../public/logos/patreon.svg"
12+
import stripeLogo from "../public/logos/stripe.svg"
13+
import benevityLogo from "../public/logos/benevity.svg"
14+
import sponsorshipIcon from "../public/icons/corporate-sponsorship.svg"
15+
16+
import LinkButton from "./LinkButton"
17+
import { useMediaQuery } from "usehooks-ts"
18+
import classNames from "classnames"
19+
20+
const cardMessages = defineMessages({
21+
giveButterTitle: {
22+
id: "sponsors.donate_card.givebutter.title",
23+
defaultMessage: "From the United States",
24+
},
25+
giveButterCopy: {
26+
id: "sponsors.donate_card.givebutter.copy",
27+
defaultMessage:
28+
"Make a one-time or recurring donation to Mastodon Inc, our US 501c3 non-profit. Tax deductible for eligible US tax residents.*",
29+
},
30+
giveButterButton: {
31+
id: "sponsors.donate_card.givebutter.button",
32+
defaultMessage: "Donate through GiveButter",
33+
},
34+
giveButterImageAlt: {
35+
id: "sponsors.donate_card.givebutter.image_alt",
36+
defaultMessage: "USA Flag",
37+
},
38+
weAidTitle: {
39+
id: "sponsors.donate_card.weaid.title",
40+
defaultMessage: "From Germany",
41+
},
42+
weAidCopy: {
43+
id: "sponsors.donate_card.weaid.copy",
44+
defaultMessage:
45+
"Make a one-time donation through WE AID gGmbH, our German fiscal host. Tax deductible for eligible German tax residents.*",
46+
},
47+
weAidButton: {
48+
id: "sponsors.donate_card.weaid.button",
49+
defaultMessage: "Donate through WE AID",
50+
},
51+
weAidImageAlt: {
52+
id: "sponsors.donate_card.weaid.image_alt",
53+
defaultMessage: "German Flag",
54+
},
55+
patreonTitle: {
56+
id: "sponsors.donate_card.patreon.title",
57+
defaultMessage: "Patreon",
58+
},
59+
patreonCopy: {
60+
id: "sponsors.donate_card.patreon.copy",
61+
defaultMessage:
62+
"Patreon donors gain access to Mastodon’s Discord for developers, server admins, and social web supporters.",
63+
},
64+
patreonButton: {
65+
id: "sponsors.donate_card.patreon.button",
66+
defaultMessage: "Donate through Patreon",
67+
},
68+
gitHubTitle: {
69+
id: "sponsors.donate_card.github.title",
70+
defaultMessage: "GitHub",
71+
},
72+
gitHubCopy: {
73+
id: "sponsors.donate_card.github.copy",
74+
defaultMessage:
75+
"GitHub Sponsors receive a Mastodon badge to their Org or Personal profile. Plus we don’t pay fees!",
76+
},
77+
gitHubButton: {
78+
id: "sponsors.donate_card.github.button",
79+
defaultMessage: "Donate through GitHub",
80+
},
81+
stripeTitle: {
82+
id: "sponsors.donate_card.stripe.title",
83+
defaultMessage: "Stripe",
84+
},
85+
stripeCopy: {
86+
id: "sponsors.donate_card.stripe.copy",
87+
defaultMessage:
88+
"Make a one-time or recurring direct donation to Mastodon GmbH, from anywhere in the world.",
89+
},
90+
stripeButton: {
91+
id: "sponsors.donate_card.stripe.button",
92+
defaultMessage: "Donate through Stripe",
93+
},
94+
corpSponsorTitle: {
95+
id: "sponsors.donate_card.corporate_sponsor.title",
96+
defaultMessage: "Corporate sponsorship",
97+
},
98+
corpSponsorCopy: {
99+
id: "sponsors.donate_card.corporate_sponsor.copy",
100+
defaultMessage:
101+
"We welcome corporate sponsors! We’ll feature your company’s logo and a link to your website.",
102+
},
103+
corpSponsorButton: {
104+
id: "sponsors.donate_card.corporate_sponsor.button",
105+
defaultMessage: "Become a sponsor",
106+
},
107+
corpMatchTitle: {
108+
id: "sponsors.donate_card.corporate_matching.title",
109+
defaultMessage: "Corporate matching",
110+
},
111+
corpMatchCopy: {
112+
id: "sponsors.donate_card.corporate_matching.copy",
113+
defaultMessage:
114+
"Does your company provide corporate matching? If so, you can use Benevity to donate!",
115+
},
116+
corpMatchButton: {
117+
id: "sponsors.donate_card.corporate_matching.button",
118+
defaultMessage: "Donate on Benevity",
119+
},
120+
logoAlt: {
121+
id: "sponsors.donate_card.logo.alt",
122+
defaultMessage: "{name} Logo",
123+
},
124+
})
125+
126+
export const DonateTabs: FC<{ className?: string }> = ({ className }) => {
127+
const isMobile = useMediaQuery("(max-width: 768px")
128+
if (isMobile) {
129+
return (
130+
<div className={classNames(className, "flex flex-col gap-4")}>
131+
<DonateCards plain />
132+
</div>
133+
)
134+
}
135+
return (
136+
<TabGroup className={className}>
137+
<TabList className="flex mb-4">
138+
<StyledTab>
139+
<FormattedMessage
140+
id="sponsors.donate_header.tax_deductible"
141+
defaultMessage="Tax-deductible donations"
142+
/>
143+
</StyledTab>
144+
<StyledTab>
145+
<FormattedMessage
146+
id="sponsors.donate_header.individual"
147+
defaultMessage="More individual donation options"
148+
/>
149+
</StyledTab>
150+
<StyledTab>
151+
<FormattedMessage
152+
id="sponsors.donate_header.corporate"
153+
defaultMessage="Corporate gifts & matching"
154+
/>
155+
</StyledTab>
156+
</TabList>
157+
<TabPanels className="border border-gray-3 p-8 rounded-2xl">
158+
<DonateCards />
159+
</TabPanels>
160+
</TabGroup>
161+
)
162+
}
163+
164+
const StyledTab: FC<PropsWithChildren> = ({ children }) => (
165+
<Tab className="grow py-2 data-[selected]:pb-[calc(0.5rem-3px)] transition-colors font-semibold box-border border-b border-gray-3 data-[selected]:border-b-4 data-[selected]:border-blurple-500">
166+
{children}
167+
</Tab>
168+
)
169+
170+
const DonateCards: FC<{ plain?: boolean }> = ({ plain }) => {
171+
const intl = useIntl()
172+
return (
173+
<>
174+
<StyledTabPanel
175+
title={
176+
<FormattedMessage
177+
id="sponsors.donate_header.tax_deductible"
178+
defaultMessage="Tax-deductible donations"
179+
/>
180+
}
181+
footer={
182+
<FormattedMessage
183+
id="sponsors.donate_footer.tax_disclaimer"
184+
defaultMessage="*Tax exemptions vary according to the laws of each country. We strongly recommend that you contact a tax consultant in your country if you have any questions about tax exemptions or reductions."
185+
/>
186+
}
187+
plain={plain}
188+
>
189+
<DonateCard
190+
title={intl.formatMessage(cardMessages.giveButterTitle)}
191+
copy={intl.formatMessage(cardMessages.giveButterCopy)}
192+
cta={intl.formatMessage(cardMessages.giveButterButton)}
193+
ctaAction="https://givebutter.com/nAk74p"
194+
imageSrc={usFlagIcon}
195+
imageAlt={intl.formatMessage(cardMessages.giveButterImageAlt)}
196+
/>
197+
<DonateCard
198+
title={intl.formatMessage(cardMessages.weAidTitle)}
199+
copy={intl.formatMessage(cardMessages.weAidCopy)}
200+
cta={intl.formatMessage(cardMessages.weAidButton)}
201+
ctaAction="https://donate.stripe.com/14A4gAfACaLg76zfKB1ZS07"
202+
imageSrc={deFlagIcon}
203+
imageAlt={intl.formatMessage(cardMessages.weAidImageAlt)}
204+
/>
205+
</StyledTabPanel>
206+
<StyledTabPanel
207+
title={
208+
<FormattedMessage
209+
id="sponsors.donate_header.individual_options"
210+
defaultMessage="More individual donation options"
211+
/>
212+
}
213+
plain={plain}
214+
>
215+
<DonateCard
216+
title={intl.formatMessage(cardMessages.stripeTitle)}
217+
copy={intl.formatMessage(cardMessages.stripeCopy)}
218+
cta={intl.formatMessage(cardMessages.stripeButton)}
219+
ctaAction="popup"
220+
imageSrc={stripeLogo}
221+
imageAlt={intl.formatMessage(cardMessages.logoAlt, {
222+
name: "Stripe",
223+
})}
224+
/>
225+
<DonateCard
226+
title={intl.formatMessage(cardMessages.patreonTitle)}
227+
copy={intl.formatMessage(cardMessages.patreonCopy)}
228+
cta={intl.formatMessage(cardMessages.patreonButton)}
229+
ctaAction="https://www.patreon.com/mastodon"
230+
imageSrc={patreonLogo}
231+
imageAlt={intl.formatMessage(cardMessages.logoAlt, {
232+
name: "Patreon",
233+
})}
234+
/>
235+
<DonateCard
236+
title={intl.formatMessage(cardMessages.gitHubTitle)}
237+
copy={intl.formatMessage(cardMessages.gitHubCopy)}
238+
cta={intl.formatMessage(cardMessages.gitHubButton)}
239+
ctaAction="https://github.com/sponsors/mastodon"
240+
imageSrc={gitHubLogo}
241+
imageAlt={intl.formatMessage(cardMessages.logoAlt, {
242+
name: "GitHub",
243+
})}
244+
/>
245+
</StyledTabPanel>
246+
<StyledTabPanel
247+
title={
248+
<FormattedMessage
249+
id="sponsors.donate_header.corporate"
250+
defaultMessage="Corporate gifts & matching"
251+
/>
252+
}
253+
plain={plain}
254+
>
255+
<DonateCard
256+
title={intl.formatMessage(cardMessages.corpSponsorTitle)}
257+
copy={intl.formatMessage(cardMessages.corpSponsorCopy)}
258+
cta={intl.formatMessage(cardMessages.corpSponsorButton)}
259+
ctaAction="https://sponsor.joinmastodon.org/"
260+
imageSrc={sponsorshipIcon}
261+
/>
262+
<DonateCard
263+
title={intl.formatMessage(cardMessages.corpMatchTitle)}
264+
copy={intl.formatMessage(cardMessages.corpMatchCopy)}
265+
cta={intl.formatMessage(cardMessages.corpMatchButton)}
266+
ctaAction="https://causes.benevity.org/causes/276-5575947211653_d7e4"
267+
imageSrc={benevityLogo}
268+
imageAlt={intl.formatMessage(cardMessages.logoAlt, {
269+
name: "Benevity",
270+
})}
271+
/>
272+
</StyledTabPanel>
273+
</>
274+
)
275+
}
276+
277+
const StyledTabPanel: FC<
278+
PropsWithChildren<{ title: ReactNode; footer?: ReactNode; plain?: boolean }>
279+
> = ({ children, title, footer, plain }) => {
280+
const Wrapper = plain ? "div" : TabPanel
281+
return (
282+
<Wrapper
283+
className={classNames(plain && "border border-gray-3 p-4 rounded-2xl")}
284+
>
285+
<h2 className="text-h5 font-semibold mb-8 text-center">{title}</h2>
286+
<div className="flex flex-col sm:flex-row items-center gap-4 justify-center">
287+
{children}
288+
</div>
289+
{footer && (
290+
<div className="mt-8 p-4 bg-gray-4 text-gray-1 rounded-lg">
291+
{footer}
292+
</div>
293+
)}
294+
</Wrapper>
295+
)
296+
}
297+
298+
interface DonateCardProps {
299+
title: string
300+
imageSrc?: string
301+
imageAlt?: string
302+
copy: string
303+
cta: string
304+
ctaAction: string | "popup"
305+
}
306+
307+
const DonateCard = ({
308+
title,
309+
imageSrc,
310+
imageAlt = "",
311+
copy,
312+
cta,
313+
ctaAction,
314+
}: DonateCardProps) => (
315+
<div className="flex flex-col items-center text-center max-w-80">
316+
{imageSrc && (
317+
<Image
318+
src={imageSrc}
319+
className="aspect-square"
320+
width="40"
321+
height="40"
322+
alt={imageAlt}
323+
/>
324+
)}
325+
<h3 className="text-b1 font-semibold mt-5 mb-2">{title}</h3>
326+
<p className="b2 grow mb-8 text-gray-1">{copy}</p>
327+
{ctaAction !== "popup" ? (
328+
<LinkButton size="medium" href={ctaAction} light>
329+
{cta}
330+
<ExternalLinkIcon className="size-5 ml-2 fill-current" />
331+
</LinkButton>
332+
) : (
333+
<DonatePopup size="medium" className="!font-semibold p-4">
334+
{cta}
335+
</DonatePopup>
336+
)}
337+
</div>
338+
)

components/Footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FormattedMessage } from "react-intl"
44
import Image from "next/legacy/image"
55
import footerImage from "../public/illustrations/footer.png"
66
import LogoWhite from "../public/logos/logo-white.svg?inline"
7-
import GitHub from "../public/ui/github.svg?inline"
7+
import GitHub from "../public/logos/github.svg?inline"
88

99
/** Sitewide footer component */
1010
export const Footer = () => (

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"sass": "^1.87.0",
4242
"sharp": "^0.34.1",
4343
"stripe": "^18.1.0",
44+
"usehooks-ts": "^3.1.1",
4445
"zod": "^3.24.4"
4546
},
4647
"devDependencies": {

0 commit comments

Comments
 (0)