commit 52250d3192fc882ed92078c7a93a002e314ae4ed
parent ac86a41c0786c8cea6f930faf2875380a1f6f91c
Author: Daniel D’Aquino <daniel@daquino.me>
Date: Sat, 30 Dec 2023 00:35:39 -0800
Add basic FAQ section
Diffstat:
8 files changed, 333 insertions(+), 0 deletions(-)
diff --git a/content/compiled-locales/en.json b/content/compiled-locales/en.json
@@ -299,6 +299,96 @@
"value": "shortName"
}
],
+ "purple.benefits.benefit1.description": [
+ {
+ "type": 0,
+ "value": "Support Damus development to help build the future of decentralized communication on the web."
+ }
+ ],
+ "purple.benefits.benefit1.name": [
+ {
+ "type": 0,
+ "value": "Help Build The Future"
+ }
+ ],
+ "purple.benefits.benefit2.description": [
+ {
+ "type": 0,
+ "value": "Be the first to access upcoming premium features: Automatic translations, longer note storage, and more"
+ }
+ ],
+ "purple.benefits.benefit2.name": [
+ {
+ "type": 0,
+ "value": "Exclusive features"
+ }
+ ],
+ "purple.benefits.benefit3.description": [
+ {
+ "type": 0,
+ "value": "Get a special badge on your profile to show everyone your contribution to Freedom tech"
+ }
+ ],
+ "purple.benefits.benefit3.name": [
+ {
+ "type": 0,
+ "value": "Supporter Badge"
+ }
+ ],
+ "purple.benefits.description": [
+ {
+ "type": 0,
+ "value": "Help us stay independent in our mission for Freedom tech with our Purple subscription, and look cool doing it!"
+ }
+ ],
+ "purple.benefits.headline": [
+ {
+ "type": 0,
+ "value": "Get more from Damus."
+ }
+ ],
+ "purple.faq.answer.1.a": [
+ {
+ "type": 0,
+ "value": "Oh yeah! You can pay with Lightning if you register on the website. For the iOS app, you can pay with Apple Pay."
+ }
+ ],
+ "purple.faq.answer.2.a": [
+ {
+ "type": 0,
+ "value": "Unfortunately not. Apple doesn’t allow apps to accept Lightning payments. but you can register on the website and pay with Lightning there."
+ }
+ ],
+ "purple.faq.headline": [
+ {
+ "type": 0,
+ "value": "Frequent Questions"
+ }
+ ],
+ "purple.faq.question.1.q": [
+ {
+ "type": 0,
+ "value": "Can I pay with Lightning?"
+ }
+ ],
+ "purple.faq.question.2.q": [
+ {
+ "type": 0,
+ "value": "But can I pay with lightning via the app?"
+ }
+ ],
+ "purple.hero.learn-more": [
+ {
+ "type": 0,
+ "value": "Learn more"
+ }
+ ],
+ "purple.hero.subscribe": [
+ {
+ "type": 0,
+ "value": "Subscribe"
+ }
+ ],
"roles.brand-ambassador": [
{
"type": 0,
diff --git a/content/locales/en.json b/content/locales/en.json
@@ -143,6 +143,51 @@
"meet_the_team.view_profile": {
"string": "Follow {shortName}"
},
+ "purple.benefits.benefit1.description": {
+ "string": "Support Damus development to help build the future of decentralized communication on the web."
+ },
+ "purple.benefits.benefit1.name": {
+ "string": "Help Build The Future"
+ },
+ "purple.benefits.benefit2.description": {
+ "string": "Be the first to access upcoming premium features: Automatic translations, longer note storage, and more"
+ },
+ "purple.benefits.benefit2.name": {
+ "string": "Exclusive features"
+ },
+ "purple.benefits.benefit3.description": {
+ "string": "Get a special badge on your profile to show everyone your contribution to Freedom tech"
+ },
+ "purple.benefits.benefit3.name": {
+ "string": "Supporter Badge"
+ },
+ "purple.benefits.description": {
+ "string": "Help us stay independent in our mission for Freedom tech with our Purple subscription, and look cool doing it!"
+ },
+ "purple.benefits.headline": {
+ "string": "Get more from Damus."
+ },
+ "purple.faq.answer.1.a": {
+ "string": "Oh yeah! You can pay with Lightning if you register on the website. For the iOS app, you can pay with Apple Pay."
+ },
+ "purple.faq.answer.2.a": {
+ "string": "Unfortunately not. Apple doesn’t allow apps to accept Lightning payments. but you can register on the website and pay with Lightning there."
+ },
+ "purple.faq.headline": {
+ "string": "Frequent Questions"
+ },
+ "purple.faq.question.1.q": {
+ "string": "Can I pay with Lightning?"
+ },
+ "purple.faq.question.2.q": {
+ "string": "But can I pay with lightning via the app?"
+ },
+ "purple.hero.learn-more": {
+ "string": "Learn more"
+ },
+ "purple.hero.subscribe": {
+ "string": "Subscribe"
+ },
"roles.brand-ambassador": {
"string": "Brand Ambassador"
},
diff --git a/package-lock.json b/package-lock.json
@@ -8,6 +8,7 @@
"name": "damus-website",
"version": "0.1.0",
"dependencies": {
+ "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-slot": "^1.0.2",
"class-variance-authority": "^0.7.0",
@@ -507,6 +508,67 @@
"@babel/runtime": "^7.13.10"
}
},
+ "node_modules/@radix-ui/react-accordion": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz",
+ "integrity": "sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-collapsible": "1.0.3",
+ "@radix-ui/react-collection": "1.0.3",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-direction": "1.0.1",
+ "@radix-ui/react-id": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-controllable-state": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz",
+ "integrity": "sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/primitive": "1.0.1",
+ "@radix-ui/react-compose-refs": "1.0.1",
+ "@radix-ui/react-context": "1.0.1",
+ "@radix-ui/react-id": "1.0.1",
+ "@radix-ui/react-presence": "1.0.1",
+ "@radix-ui/react-primitive": "1.0.3",
+ "@radix-ui/react-use-controllable-state": "1.0.1",
+ "@radix-ui/react-use-layout-effect": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-collection": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz",
diff --git a/package.json b/package.json
@@ -13,6 +13,7 @@
"i18n": "npm run extract:i18n && npm run compile:i18n"
},
"dependencies": {
+ "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-navigation-menu": "^1.1.4",
"@radix-ui/react-slot": "^1.0.2",
"class-variance-authority": "^0.7.0",
diff --git a/src/components/pages/purple.tsx b/src/components/pages/purple.tsx
@@ -13,6 +13,7 @@ import { Contribute } from '@/components/sections/Contribute';
import { FinalCTA } from '@/components/sections/FinalCTA';
import { Benefits } from '@/components/sections/Benefits';
import { PurpleBenefits } from '../sections/PurpleBenefits';
+import { PurpleFAQ } from '../sections/PurpleFAQ';
const inter = Inter({ subsets: ['latin'] })
@@ -28,6 +29,7 @@ export function Purple() {
<main style={{ scrollBehavior: "smooth" }}>
<PurpleHero />
<PurpleBenefits/>
+ <PurpleFAQ/>
<FinalCTA />
<Footer />
</main>
diff --git a/src/components/sections/PurpleFAQ.tsx b/src/components/sections/PurpleFAQ.tsx
@@ -0,0 +1,61 @@
+import { FormattedMessage, useIntl } from "react-intl";
+import { motion } from "framer-motion";
+import { RoundedContainerWithGradientBorder } from "../ui/RoundedContainerWithGradientBorder";
+import { cn } from "@/lib/utils";
+import { Award, Badge, Heart, Joystick, KeyRound, Scale, Stars, Wallet } from "lucide-react";
+import { MeshGradient3 } from "../effects/MeshGradient.3";
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/components/ui/Accordion"
+
+const faq = [
+ {
+ questionIntlString: "purple.faq.1.q",
+ answerIntlString: "purple.faq.1.a",
+ },
+ {
+ questionIntlString: "purple.faq.2.q",
+ answerIntlString: "purple.faq.2.a",
+ }
+]
+
+
+export function PurpleFAQ({ className }: { className?: string }) {
+ const intl = useIntl()
+
+ // This type of structure is necessary in this case to make strings get picked up by `npm run i18n`
+ const faqIntlStrings: Record<string, string> = {
+ "purple.faq.1.q": intl.formatMessage({ id: "purple.faq.question.1.q", defaultMessage: "Can I pay with Lightning?" }),
+ "purple.faq.1.a": intl.formatMessage({ id: "purple.faq.answer.1.a", defaultMessage: "Oh yeah! You can pay with Lightning if you register on the website. For the iOS app, you can pay with Apple Pay." }),
+ "purple.faq.2.q": intl.formatMessage({ id: "purple.faq.question.2.q", defaultMessage: "But can I pay with lightning via the app?" }),
+ "purple.faq.2.a": intl.formatMessage({ id: "purple.faq.answer.2.a", defaultMessage: "Unfortunately not. Apple doesn’t allow apps to accept Lightning payments. but you can register on the website and pay with Lightning there." }),
+ }
+
+ return (<>
+ <div className={cn("bg-black overflow-hidden relative", className)}>
+ <MeshGradient3 className="absolute top-0 left-0 pointer-events-none translate-y-3/4 overflow-visible scale-150" />
+ <div className="container mx-auto px-6 pb-32 pt-20">
+ <div className="flex flex-col items-center justify-center mt-32 lg:mt-16">
+ <div className="relative mb-32 flex flex-col items-center">
+ <motion.h2 className="text-4xl md:text-8xl text-center text-transparent bg-clip-text bg-gradient-to-r from-damuspink-500 from-30% to-damuspink-600 to-100% font-semibold pb-8 break-keep">
+ {intl.formatMessage({ id: "purple.faq.headline", defaultMessage: "Frequent Questions" })}
+ </motion.h2>
+ </div>
+ </div>
+ <Accordion type="single" collapsible className="w-full text-white max-w-3xl mx-auto">
+ {faq.map((item, index) => (
+ <AccordionItem value={`item-${index}`} key={index}>
+ <AccordionTrigger>{faqIntlStrings[item.questionIntlString]}</AccordionTrigger>
+ <AccordionContent>
+ {faqIntlStrings[item.answerIntlString]}
+ </AccordionContent>
+ </AccordionItem>
+ ))}
+ </Accordion>
+ </div>
+ </div>
+ </>)
+}
diff --git a/src/components/ui/Accordion.tsx b/src/components/ui/Accordion.tsx
@@ -0,0 +1,58 @@
+"use client"
+
+import * as React from "react"
+import * as AccordionPrimitive from "@radix-ui/react-accordion"
+import { ChevronDownIcon } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Accordion = AccordionPrimitive.Root
+
+const AccordionItem = React.forwardRef<
+ React.ElementRef<typeof AccordionPrimitive.Item>,
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
+>(({ className, ...props }, ref) => (
+ <AccordionPrimitive.Item
+ ref={ref}
+ className={cn("border-b", className)}
+ {...props}
+ />
+))
+AccordionItem.displayName = "AccordionItem"
+
+const AccordionTrigger = React.forwardRef<
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
+>(({ className, children, ...props }, ref) => (
+ <AccordionPrimitive.Header className="flex">
+ <AccordionPrimitive.Trigger
+ ref={ref}
+ className={cn(
+ "flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
+ className
+ )}
+ {...props}
+ >
+ {children}
+ <ChevronDownIcon className="h-4 w-4 shrink-0 text-white/70 transition-transform duration-200" />
+ </AccordionPrimitive.Trigger>
+ </AccordionPrimitive.Header>
+))
+AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
+
+const AccordionContent = React.forwardRef<
+ React.ElementRef<typeof AccordionPrimitive.Content>,
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
+>(({ className, children, ...props }, ref) => (
+ <AccordionPrimitive.Content
+ ref={ref}
+ className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
+ {...props}
+ >
+ <div className={cn("pb-4 pt-0", className)}>{children}</div>
+ </AccordionPrimitive.Content>
+))
+AccordionContent.displayName = AccordionPrimitive.Content.displayName
+
+export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
+
diff --git a/tailwind.config.ts b/tailwind.config.ts
@@ -14,6 +14,20 @@ const config: Config = {
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
},
colors: {
...colors,