update with accordion

This commit is contained in:
Kalidou Diagne
2024-03-14 19:28:17 +00:00
parent f2406e55a5
commit 4d27519713
4 changed files with 348 additions and 219 deletions

View File

@@ -41,6 +41,14 @@ const SectionLabel = ({ label }: { label: string }) => {
)
}
const AccordionLabel = ({ label }: { label: string }) => {
return (
<span className="mx-auto text-center text-base font-bold uppercase tracking-[3.36px] text-tuatara-950">
{label}
</span>
)
}
const ProgramDetail = ({
title,
location,
@@ -94,18 +102,21 @@ const ProgramDetail = ({
const ProgramSections = ["contributionsProgram", "accelerationProgram"] as const
const ChooseProgramItems: DropdownProps["items"] & { href?: string } = [
const ChooseProgramItems: { label: string; value: string; href?: string }[] = [
{
label: "Contributions Program Asia",
value: "contributionsProgramAsia",
href: siteConfig.links.applyContributionProgram,
},
{
label: "Contributions Program LatAm",
value: "contributionsProgramaLatAm",
href: siteConfig.links.applyContributionProgram,
},
{
label: "Acceleration Program",
value: "accelerationProgram",
href: siteConfig.links.applyContributionProgram,
},
]
export default function ProgramsPage({ params: { lang } }: any) {
@@ -177,6 +188,17 @@ export default function ProgramsPage({ params: { lang } }: any) {
""
const selectedProgramLabel = t(selectedProgramKey)
const ApplyButton = () => {
return (
<Button className="w-full uppercase" disabled={!selectedProgram}>
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
)
}
return (
<div className="flex flex-col">
<div className="bg-second-gradient">
@@ -211,12 +233,16 @@ export default function ProgramsPage({ params: { lang } }: any) {
defaultItem="contributionsProgram"
/>
</div>
<Button className="w-full uppercase" disabled={!selectedProgram}>
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
{!selectedProgram ? (
<ApplyButton />
) : (
<Link
target="_blank"
href={siteConfig.links.applyContributionProgram}
>
<ApplyButton />
</Link>
)}
</div>
</div>
</AppContent>
@@ -272,7 +298,7 @@ export default function ProgramsPage({ params: { lang } }: any) {
</Link>
</Card>
</div>
<div className="flex flex-col gap-2 py-10 md:py-16">
<div className="flex flex-col gap-2 pt-8">
{contributionsProgramDescription?.map(
(description, index) => {
return (
@@ -287,56 +313,84 @@ export default function ProgramsPage({ params: { lang } }: any) {
)}
</div>
</div>
<div className="flex flex-col gap-8">
<SectionLabel label={t("common.curriculum")} />
<Card
className="divide-y divide-tuatara-300"
padding="none"
variant="transparent"
>
{curriculum.map(({ title, items }, index) => (
<div
key={index}
className="grid grid-cols-1 divide-tuatara-300 md:grid-cols-[1fr_2.5fr] md:divide-x"
>
<div className="flex items-center justify-center border-b border-tuatara-300 bg-anakiwa-100 p-2 text-center md:border-none">
<span className="text-xs font-bold uppercase tracking-[2.5px] text-tuatara-950">
{t("common.week", {
week: index,
})}
<br />
{title}
</span>
</div>
<div className="py-2">
<ul className="ml-10 list-disc">
{items.map((label: string, index: number) => {
return <li key={index}>{label}</li>
})}
</ul>
</div>
</div>
))}
</Card>
</div>
<div className="flex flex-col gap-8 pt-6">
<SectionLabel label={t("common.faq")} />
<div className="flex flex-col gap-10">
<Accordion
className="!border-anakiwa-300"
size="xs"
items={contributionsProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="font-sans text-base font-semibold text-black">
{question}
</span>
),
value: index.toString(),
children: answer,
}
}
)}
className="!border-none"
iconOnHover={false}
items={[
{
label: (
<AccordionLabel label={t("common.curriculum")} />
),
value: "curriculum",
children: (
<Card
className="mt-10 divide-y divide-tuatara-300"
padding="none"
variant="transparent"
>
{curriculum.map(({ title, items }, index) => (
<div
key={index}
className="grid grid-cols-1 divide-tuatara-300 md:grid-cols-[1fr_2.5fr] md:divide-x"
>
<div className="flex items-center justify-center border-b border-tuatara-300 bg-anakiwa-100 p-2 text-center md:border-none">
<span className="text-xs font-bold uppercase tracking-[2.5px] text-tuatara-950">
{t("common.week", {
week: index,
})}
<br />
{title}
</span>
</div>
<div className="py-2">
<ul className="ml-10 list-disc">
{items.map(
(label: string, index: number) => {
return <li key={index}>{label}</li>
}
)}
</ul>
</div>
</div>
))}
</Card>
),
},
]}
/>
<Accordion
size="xs"
className="!border-none"
iconOnHover={false}
items={[
{
label: <AccordionLabel label={t("common.faq")} />,
value: "faq",
children: (
<div className="pt-10">
<Accordion
className="!border-anakiwa-300"
size="xs"
items={contributionsProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="font-sans text-base font-semibold text-black">
{question}
</span>
),
value: index.toString(),
children: answer,
}
}
)}
/>
</div>
),
},
]}
/>
</div>
</div>
@@ -371,7 +425,7 @@ export default function ProgramsPage({ params: { lang } }: any) {
</div>
</Card>
</div>
<div className="flex flex-col gap-2 py-10 md:py-16">
<div className="flex flex-col gap-2 pt-8">
{accelerationProgramDescription?.map((description, index) => {
return (
<span key={index} className="font-sans text-base text-black">
@@ -380,68 +434,103 @@ export default function ProgramsPage({ params: { lang } }: any) {
)
})}
</div>
<div className="flex flex-col gap-8 pb-10 md:pb-16">
<SectionLabel label={t("common.howToApply")} />
<div id="howToApply" className="flex flex-col gap-8">
<div>
<strong>{t("howToApply.openTasks.title")}</strong>
<ul className="list-decimal">
{howToApply?.openTasks?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
dangerouslySetInnerHTML={{ __html: task }}
></div>
</li>
)
}
)}
</ul>
</div>
<div>
<strong>{t("howToApply.submitIdea.title")}</strong>
<ul className="list-decimal">
{howToApply?.submitIdea?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
dangerouslySetInnerHTML={{ __html: task }}
></div>
</li>
)
}
)}
</ul>
</div>
<span>{t("howToApply.description")}</span>
</div>
</div>
<div className="flex flex-col gap-8">
<SectionLabel label={t("common.faq")} />
<div className="flex flex-col gap-10 pt-14">
<Accordion
className="!border-anakiwa-300"
size="xs"
items={accelerationProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="font-sans text-base font-semibold text-black">
{question}
</span>
),
value: index.toString(),
children: answer,
}
}
)}
className="!border-none"
iconOnHover={false}
items={[
{
label: <AccordionLabel label={t("common.howToApply")} />,
value: "howToApply",
children: (
<div className="mt-10">
<div className="flex flex-col gap-8 pb-10 md:pb-16">
<div id="howToApply" className="flex flex-col gap-8">
<div>
<strong>{t("howToApply.openTasks.title")}</strong>
<ul className="list-decimal">
{howToApply?.openTasks?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
</ul>
</div>
<div>
<strong>
{t("howToApply.submitIdea.title")}
</strong>
<ul className="list-decimal">
{howToApply?.submitIdea?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
</ul>
</div>
<span>{t("howToApply.description")}</span>
</div>
</div>
</div>
),
},
]}
/>
<Accordion
size="xs"
className="!border-none"
iconOnHover={false}
items={[
{
label: <AccordionLabel label={t("common.faq")} />,
value: "faq",
children: (
<div className="mt-10 flex flex-col gap-8">
<Accordion
className="!border-anakiwa-300"
size="xs"
items={accelerationProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="font-sans text-base font-semibold text-black">
{question}
</span>
),
value: index.toString(),
children: answer,
}
}
)}
/>
</div>
),
},
]}
/>
</div>
</div>

View File

@@ -2,11 +2,12 @@
import Link from "next/link"
import { LangProps } from "@/types/common"
import { NavItem } from "@/types/nav"
import { useTranslation } from "@/app/i18n/client"
import { siteConfig } from "@/config/site"
import { useAppSettings } from "@/hooks/useAppSettings"
import { useTranslation } from "@/app/i18n/client"
import { cn } from "@/lib/utils"
import { LangProps } from "@/types/common"
import { NavItem } from "@/types/nav"
import { Icons } from "./icons"
import { AppContent } from "./ui/app-content"
@@ -19,8 +20,14 @@ const SocialMedia = ({ label }: { label: string }) => {
)
}
const LinksWrapper = ({ children }: { children: React.ReactNode }) => {
return <div className="flex flex-col gap-4">{children}</div>
const LinksWrapper = ({
children,
className,
}: {
children: React.ReactNode
className?: string
}) => {
return <div className={cn("flex flex-col gap-4", className)}>{children}</div>
}
export function SiteFooter({ lang }: LangProps["params"]) {
@@ -31,103 +38,107 @@ export function SiteFooter({ lang }: LangProps["params"]) {
return (
<footer className="flex flex-col">
<div className="bg-tuatara-950 py-8 text-left text-[14px] text-white">
<AppContent className="grid grid-cols-1 justify-between gap-8 bg-tuatara-950 py-2 text-white md:grid-cols-[2fr_3fr]">
<div className="order-2 flex flex-col items-center gap-4 md:order-1 md:flex-row">
<Icons.logoWhite size={134} />
<AppContent className="grid grid-cols-1 justify-between gap-8 bg-tuatara-950 py-2 text-white lg:grid-cols-[2fr_3fr]">
<div className="order-2 mx-auto flex max-w-sm flex-col items-center gap-4 md:w-full md:flex-row lg:order-1">
<div className=" w-[134px]">
<Icons.logoWhite className="h-[134px] w-[134px]" size={134} />
</div>
<span className="text-center text-sm text-white md:text-left">
{t("footer.description")}
</span>
</div>
<div className="order-1 grid grid-cols-1 gap-8 uppercase md:order-2 md:grid-cols-4">
<LinksWrapper>
{MAIN_NAV.filter((item) => item.order === 1).map(
({ title, href, external = false }: NavItem, indexKey) => (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
{title}
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
{MAIN_NAV.filter((item) => item.order === 2).map(
({ title, href, external = false }: NavItem, indexKey) => (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
<div className="flex items-center gap-2">
<span> {title}</span>
<Icons.externalUrl className="w-5" />
</div>
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.twitter}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.twitter className="w-full" color="white" />
</div>
<SocialMedia label="Twitter" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.discord}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<Icons.discord className="w-4" />
<SocialMedia label="Discord" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.github}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<Icons.gitHub className="w-4" color="white" />
<SocialMedia label="Github" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.articles}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.mirror className="w-full" color="white" />
</div>
<div className="order-1 grid grid-cols-1 gap-8 uppercase lg:order-2 lg:grid-cols-4">
<div className="grid grid-cols-1 gap-8 lg:col-span-3 lg:grid-cols-3">
<LinksWrapper>
{MAIN_NAV.filter((item) => item.order === 1).map(
({ title, href, external = false }: NavItem, indexKey) => (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
{title}
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
{MAIN_NAV.filter((item) => item.order === 2).map(
({ title, href, external = false }: NavItem, indexKey) => (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
<div className="flex items-center gap-2">
<span> {title}</span>
<Icons.externalUrl className="w-5" />
</div>
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.twitter}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.twitter className="w-full" color="white" />
</div>
<SocialMedia label="Twitter" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.discord}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<Icons.discord className="w-4" />
<SocialMedia label="Discord" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.github}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<Icons.gitHub className="w-4" color="white" />
<SocialMedia label="Github" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.articles}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.mirror className="w-full" color="white" />
</div>
<SocialMedia label="Mirror" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.youtube}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.youtube className="w-full" color="white" />
</div>
<SocialMedia label="Youtube" />
<Icons.externalUrl className="w-5" />
</Link>
</LinksWrapper>
<LinksWrapper>
<SocialMedia label="Mirror" />
<Icons.externalUrl className="w-5" />
</Link>
<Link
href={siteConfig.links.youtube}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<div className="w-4">
<Icons.youtube className="w-full" color="white" />
</div>
<SocialMedia label="Youtube" />
<Icons.externalUrl className="w-5" />
</Link>
</LinksWrapper>
</div>
<LinksWrapper className="hidden md:block lg:col-span-1">
<Link
href={siteConfig.links.privacyPolicy}
target="_blank"
@@ -144,6 +155,22 @@ export function SiteFooter({ lang }: LangProps["params"]) {
</Link>
</LinksWrapper>
</div>
<LinksWrapper className="order-3 mx-auto flex flex-row uppercase md:hidden lg:col-span-1">
<Link
href={siteConfig.links.privacyPolicy}
target="_blank"
rel="noreferrer"
>
<span>{t("footer.privacyPolicy")}</span>
</Link>
<Link
href={siteConfig.links.termOfUse}
target="_blank"
rel="noreferrer"
>
<span>{t("footer.termsOfUse")}</span>
</Link>
</LinksWrapper>
</AppContent>
</div>
</footer>

View File

@@ -21,6 +21,7 @@ interface AccordionProps extends RadixAccordion.AccordionImplProps {
defaultValue?: string
items: AccordionItemProps[]
className?: string
iconOnHover?: boolean
}
const AccordionSizeMapping: Record<AccordionPadding, string> = {
@@ -34,6 +35,7 @@ const Accordion = ({
items,
size = "sm",
className,
iconOnHover = true,
}: AccordionProps) => {
return (
<RadixAccordion.Root
@@ -52,7 +54,7 @@ const Accordion = ({
<RadixAccordion.Trigger className="w-full">
<div
className={cn(
"flex w-full items-center justify-between border-t border-t-black ring-0 focus:outline-none",
"relative flex w-full items-center justify-between border-t border-t-black ring-0 focus:outline-none",
className,
{
[AccordionSizeMapping.xs]: size === "xs",
@@ -68,7 +70,12 @@ const Accordion = ({
label
)}
<div
className={`duration-50 group-hover:visible group-data-[state=open]:hidden md:invisible`}
className={cn(
"duration-50 absolute right-0 group-data-[state=open]:hidden",
{
"group-hover:visible md:invisible": iconOnHover,
}
)}
>
<Icons.plus
className={cn({
@@ -77,7 +84,9 @@ const Accordion = ({
})}
/>
</div>
<div className={`hidden group-data-[state=open]:block`}>
<div
className={`absolute right-0 hidden group-data-[state=open]:block`}
>
<Icons.minus
className={cn({
"w-4 md:w-6": size === "xs",

View File

@@ -20,8 +20,12 @@ export const siteConfig = {
"https://discord.com/channels/943612659163602974/969614451089227876",
accelerationGithub:
"https://github.com/privacy-scaling-explorations/acceleration-program",
latAmContributionProgram: "",
asiaContributionProgram: "",
latAmContributionProgram:
"https://docs.google.com/forms/d/e/1FAIpQLSendzYY0z_z7fZ37g3jmydvzS9I7OWKbY2JrqAnyNqeaBHvMQ/viewform",
asiaContributionProgram:
"https://docs.google.com/forms/d/e/1FAIpQLSendzYY0z_z7fZ37g3jmydvzS9I7OWKbY2JrqAnyNqeaBHvMQ/viewform",
applyContributionProgram:
"https://docs.google.com/forms/d/e/1FAIpQLSendzYY0z_z7fZ37g3jmydvzS9I7OWKbY2JrqAnyNqeaBHvMQ/viewform",
},
addGithubResource:
"https://github.com/privacy-scaling-explorations/website-v2/blob/main/app/%5Blang%5D/content/resources.md",