Merge pull request #159 from privacy-scaling-explorations/design-v1/5

update to design v1.5
This commit is contained in:
Kalidou Diagne
2024-03-29 15:58:07 +00:00
committed by GitHub
15 changed files with 502 additions and 559 deletions

View File

@@ -7,6 +7,7 @@ import { AppContent } from "@/components/ui/app-content"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Banner } from "@/components/banner"
import { Divider } from "@/components/divider"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { useTranslation } from "@/app/i18n"
@@ -21,7 +22,7 @@ export default async function AboutPage({ params: { lang } }: any) {
}) ?? []
return (
<div className="bg-white">
<Divider.Section className="bg-white">
<PageHeader
title={t("title")}
subtitle={t("description")}
@@ -55,32 +56,34 @@ export default async function AboutPage({ params: { lang } }: any) {
}
/>
<AppContent className="container flex w-full max-w-[978px] flex-col gap-8 py-10 md:py-16">
<Label.Section
className="text-center"
label={t("our-principles-title")}
/>
<Accordion
type="multiple"
items={[
...principles?.map((principle: any, index: number) => {
return {
label: principle?.title,
value: index.toString(),
children: (
<span className="flex flex-col gap-6 break-words pb-12 font-sans text-lg font-normal leading-[150%]">
{principle.description?.map(
(description: string, index: number) => {
return <p key={index}>{description}</p>
}
)}
</span>
),
}
}),
]}
/>
</AppContent>
<div className="flex justify-center">
<AppContent className="container flex w-full max-w-[978px] flex-col gap-8 py-10 md:py-16">
<Label.Section
className="text-center"
label={t("our-principles-title")}
/>
<Accordion
type="multiple"
items={[
...principles?.map((principle: any, index: number) => {
return {
label: principle?.title,
value: index.toString(),
children: (
<span className="flex flex-col gap-6 break-words pb-12 font-sans text-lg font-normal leading-[150%]">
{principle.description?.map(
(description: string, index: number) => {
return <p key={index}>{description}</p>
}
)}
</span>
),
}
}),
]}
/>
</AppContent>
</div>
<Banner title={t("banner.title")} subtitle={t("banner.subtitle")}>
<Link
@@ -100,6 +103,6 @@ export default async function AboutPage({ params: { lang } }: any) {
</Button>
</Link>
</Banner>
</div>
</Divider.Section>
)
}

View File

@@ -4,11 +4,13 @@ import Image from "next/image"
import Link from "next/link"
import PSELogo from "@/public/icons/archstar.webp"
import { motion } from "framer-motion"
import { Divide } from "lucide-react"
import { siteConfig } from "@/config/site"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Banner } from "@/components/banner"
import { Divider } from "@/components/divider"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { ConnectWithUs } from "@/components/sections/ConnectWithUs"
@@ -23,40 +25,44 @@ export default function IndexPage({ params: { lang } }: any) {
return (
<section className="flex flex-col">
<PageHeader
title={
<motion.h1
initial={{ y: 16, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, cubicBezier: "easeOut" }}
>
<Label.PageTitle label={t("headerTitle")} />
</motion.h1>
}
subtitle={t("headerSubtitle")}
image={
<div className="m-auto flex h-[320px] w-full max-w-[280px] items-center justify-center md:m-0 md:h-full md:w-full lg:max-w-[380px]">
<Image src={PSELogo} alt="pselogo" style={{ objectFit: "cover" }} />
</div>
}
actions={
<Link href={`/projects`} className="group flex items-center gap-2">
<Button className="w-full sm:w-auto">
<div className="flex items-center gap-1">
<span className="text-base font-medium uppercase">
{common("exploreProjectLibrary")}
</span>
<Icons.arrowRight
fill="white"
className="h-5 duration-200 ease-in-out group-hover:translate-x-2"
/>
</div>
</Button>
</Link>
}
/>
<Divider.Section>
<PageHeader
title={
<motion.h1
initial={{ y: 16, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, cubicBezier: "easeOut" }}
>
<Label.PageTitle label={t("headerTitle")} />
</motion.h1>
}
subtitle={t("headerSubtitle")}
image={
<div className="m-auto flex h-[320px] w-full max-w-[280px] items-center justify-center md:m-0 md:h-full md:w-full lg:max-w-[380px]">
<Image
src={PSELogo}
alt="pselogo"
style={{ objectFit: "cover" }}
/>
</div>
}
actions={
<Link href={`/projects`} className="group flex items-center gap-2">
<Button className="w-full sm:w-auto">
<div className="flex items-center gap-1">
<span className="text-base font-medium uppercase">
{common("exploreProjectLibrary")}
</span>
<Icons.arrowRight
fill="white"
className="h-5 duration-200 ease-in-out group-hover:translate-x-2"
/>
</div>
</Button>
</Link>
}
/>
<div className="flex flex-col">
<NewsSection lang={lang} />
<WhatWeDo lang={lang} />
@@ -84,7 +90,7 @@ export default function IndexPage({ params: { lang } }: any) {
</Button>
</Link>
</Banner>
</div>
</Divider.Section>
</section>
)
}

View File

@@ -14,7 +14,9 @@ import { Accordion } from "@/components/ui/accordion"
import { AppContent } from "@/components/ui/app-content"
import { Button } from "@/components/ui/button"
import { Dropdown, DropdownProps } from "@/components/ui/dropdown"
import { Banner } from "@/components/banner"
import { Card } from "@/components/cards/card"
import { Divider } from "@/components/divider"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { useTranslation } from "@/app/i18n/client"
@@ -92,29 +94,13 @@ const ProgramDetail = ({
const ProgramSections = ["coreProgram", "acceleratorProgram"] as const
const ChooseProgramItems: { label: string; value: string; href?: string }[] = [
{
label: "Core Program",
value: "coreProgram",
href: siteConfig.links.coreProgram,
},
{
label: "Accelerator Program",
value: "acceleratorProgram",
href: siteConfig.links.acceleratorProgram,
},
]
export const ProgramPageContent = ({ lang }: any) => {
const { t } = useTranslation(lang, "programs-page")
const { t: common } = useTranslation(lang, "common")
const [activeId, setActiveId] = useState("")
const [isManualScroll, setIsManualScroll] = useState(false)
const [selectedProgram, setSelectedProgram] = useState(
ChooseProgramItems[0].value
)
const SCROLL_OFFSET = -900
const sectionsRef = useRef<NodeListOf<HTMLElement> | null>(null)
const [{ value: defaultProgramValue }] = ChooseProgramItems
const howToApply: any =
t("howToApply", {
@@ -173,276 +159,192 @@ export const ProgramPageContent = ({ lang }: any) => {
setTimeout(() => setIsManualScroll(false), 800)
}, [])
const selectedProgramKey: string =
ChooseProgramItems?.find((item) => item.value === selectedProgram)?.label ??
""
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>
)
}
const selectedProgramUrl = ChooseProgramItems?.find(
(item) => item.value === selectedProgram
)?.href
return (
<div className="flex flex-col">
<Divider.Section className="flex flex-col">
<div className="bg-second-gradient">
{defaultProgramValue && (
<PageHeader
title={t("title")}
subtitle={t("description")}
image={
<Image
width={280}
height={280}
className="mx-auto h-[256px] w-[290px] lg:ml-auto lg:h-[428px] lg:w-[484px]"
src="/images/programs.png"
alt="computer image"
/>
}
actions={
defaultProgramValue && (
<div className="flex flex-col gap-6 md:max-w-xs">
<div className="flex flex-col gap-1">
<span className="text-xs">{common("chooseProgram")}*</span>
<Dropdown
className="border border-tuatara-300 bg-white py-2 pl-6 pr-4"
label={
!selectedProgram
? `${common("chooseProgram")}`
: selectedProgramLabel
}
items={ChooseProgramItems as DropdownProps["items"]}
width={320}
onChange={(value: any) => setSelectedProgram(value)}
defaultItem={defaultProgramValue}
/>
</div>
{!selectedProgram ? (
<ApplyButton />
) : (
<Link target="_blank" href={selectedProgramUrl ?? "#"}>
<ApplyButton />
</Link>
)}
</div>
)
}
/>
)}
<PageHeader
title={t("title")}
subtitle={t("description")}
image={
<Image
width={280}
height={280}
className="mx-auto h-[256px] w-[290px] lg:ml-auto lg:h-[428px] lg:w-[484px]"
src="/images/programs.png"
alt="computer image"
/>
}
/>
</div>
<div className="flex flex-col">
<div className="border-b border-tuatara-300">
<AppContent className="relative mx-auto flex w-full items-start">
<div className="flex w-full flex-col">
<div
id="coreProgram"
data-section="coreProgram"
className="w-ful py-10 md:py-16"
>
<div className="mx-auto flex flex-col md:max-w-2xl">
<div className="flex flex-col gap-8">
<SectionTitle label={t("coreProgram.title")} />
<div className="flex flex-col">
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
<Card className="flex flex-col gap-10">
<ProgramDetail
region="LatAm"
title="Core Program"
deadline="Apr. 30, 2024"
location="Buenos Aires - Cuenca - San Jose"
date="Jul. 22, 2024 - Sep. 15, 2024"
/>
<Link
href={siteConfig.links.coreProgram}
target="_blank"
>
<Button className="w-full uppercase">
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
</Link>
</Card>
<Card className="flex flex-col gap-10">
<ProgramDetail
region="Asia"
title="Core Program"
deadline="Apr. 30, 2024"
location="Seoul - Taipei - Tokyo"
date="Jul. 29, 2024 - Sep. 22, 2024"
/>
<Link
href={siteConfig.links.coreProgram}
target="_blank"
>
<Button className="w-full uppercase">
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
</Link>
</Card>
</div>
<div className="flex flex-col gap-2 pt-8">
{coreProgramDescription?.map((description, index) => {
return (
<span
key={index}
className="font-sans text-base text-tuatara-950"
>
{description}
</span>
)
})}
</div>
</div>
<div className="flex flex-col gap-0 md:mt-4 md:gap-10">
<Accordion
id="curriculum"
size="xs"
className="!border-none"
iconOnHover
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 h-[96px] items-center justify-center border-b border-tuatara-300 bg-anakiwa-100 p-2 text-center md:border-none">
<span className="max-w-[136px] text-xs font-bold uppercase tracking-[2.5px] text-tuatara-950">
{t("common.week", {
week: index,
})}
<br />
{title}
</span>
</div>
<div className="flex items-center 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 className="relative flex w-full flex-col justify-center">
<div className="sticky right-0 top-0 z-10 mx-auto flex w-full max-w-screen-3xl">
<div
id="sidebar"
className="relative ml-auto hidden bg-white p-2 lg:block"
>
<div className="absolute right-0 mt-[80px] flex flex-col gap-4 lg:w-[220px] xl:w-[320px] xl:px-8">
<h6 className="font-display text-lg font-bold text-tuatara-700">
{common("onThisPage")}
</h6>
<ul className="text-normal font-sans text-black">
{ProgramSections.map((id: string) => {
const label = t(`${id}.title`)
if (!label) return null // no label for this section
const active = id === activeId
return (
<li
key={id}
onClick={(e) => {
scrollToId(id)
}}
data-id={id}
className={cn(
"flex h-8 cursor-pointer items-center border-l-2 border-l-anakiwa-200 px-3 duration-200",
{
"border-l-anakiwa-500 text-anakiwa-500 font-medium":
active,
}
)}
>
{label}
</li>
)
})}
</ul>
</div>
</div>
</div>
<div className="relative z-0 flex w-full flex-col divide-y divide-tuatara-300 ">
<div
id="coreProgram"
data-section="coreProgram"
className="w-ful py-10 md:py-16"
>
<div className="mx-auto flex flex-col md:max-w-2xl">
<div className="flex flex-col gap-8">
<SectionTitle label={t("coreProgram.title")} />
<div className="flex flex-col">
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
<Card className="flex flex-col gap-10">
<ProgramDetail
region="LatAm"
title="Core Program"
deadline="Apr. 30, 2024"
location="Buenos Aires - Cuenca - San Jose"
date="Jul. 22, 2024 - Sep. 15, 2024"
/>
<Accordion
size="xs"
className="!border-none"
iconOnHover
items={[
{
label: <AccordionLabel label={t("common.faq")} />,
value: "faq",
children: (
<div className="pt-10">
<Accordion
id="faq"
className="!border-anakiwa-300"
size="xs"
items={coreProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="text-left font-sans text-base font-medium leading-6 text-black">
{question}
</span>
),
value: index.toString(),
children: (
<span
className="font-sans text-sm font-normal text-black"
dangerouslySetInnerHTML={{
__html: answer?.toString() ?? "",
}}
></span>
),
}
}
)}
/>
</div>
),
},
]}
<Link href={siteConfig.links.coreProgram} target="_blank">
<Button className="w-full uppercase">
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
</Link>
</Card>
<Card className="flex flex-col gap-10">
<ProgramDetail
region="Asia"
title="Core Program"
deadline="Apr. 30, 2024"
location="Seoul - Taipei - Tokyo"
date="Jul. 29, 2024 - Sep. 22, 2024"
/>
</div>
<Link href={siteConfig.links.coreProgram} target="_blank">
<Button className="w-full uppercase">
<div className="flex items-center gap-3">
<span>{t("common.applyNow")}</span>
<Icons.arrowRight size={20} />
</div>
</Button>
</Link>
</Card>
</div>
<div className="flex flex-col gap-2 pt-8">
{coreProgramDescription?.map((description, index) => {
return (
<span
key={index}
className="font-sans text-base text-tuatara-950"
>
{description}
</span>
)
})}
</div>
</div>
</div>
</div>
<div
id="sidebar"
className="sticky right-0 top-20 hidden w-[320px] bg-white/30 p-8 lg:block"
>
<div className="flex flex-col gap-4">
<h6 className="font-display text-lg font-bold text-tuatara-700">
{common("onThisPage")}
</h6>
<ul className="text-normal font-sans text-black">
{ProgramSections.map((id: string) => {
const label = t(`${id}.title`)
<div className="flex flex-col gap-0 md:mt-4 md:gap-10">
<div className="flex flex-col">
<AccordionLabel label={t("common.curriculum")} />
<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 h-[96px] items-center justify-center border-b border-tuatara-300 bg-anakiwa-100 p-2 text-center md:border-none">
<span className="max-w-[136px] text-xs font-bold uppercase tracking-[2.5px] text-tuatara-950">
{t("common.week", {
week: index,
})}
<br />
{title}
</span>
</div>
<div className="flex items-center 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>
if (!label) return null // no label for this section
const active = id === activeId
return (
<li
key={id}
onClick={(e) => {
scrollToId(id)
}}
data-id={id}
className={cn(
"flex h-8 cursor-pointer items-center border-l-2 border-l-anakiwa-200 px-3 duration-200",
{
"border-l-anakiwa-500 text-anakiwa-500 font-medium":
active,
<div className="flex flex-col">
<AccordionLabel label={t("common.faq")} />
<div className="pt-10">
<Accordion
id="faq"
className="!border-anakiwa-300"
size="xs"
items={coreProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="text-left font-sans text-base font-medium leading-6 text-black">
{question}
</span>
),
value: index.toString(),
children: (
<span
className="font-sans text-sm font-normal text-black"
dangerouslySetInnerHTML={{
__html: answer?.toString() ?? "",
}}
></span>
),
}
}
)}
>
{label}
</li>
)
})}
</ul>
/>
</div>
</div>
</div>
</div>
</div>
</AppContent>
</div>
<AppContent className="relative mx-auto flex w-full items-start">
</div>
<div className="flex w-full flex-col">
<div
id="acceleratorProgram"
@@ -491,124 +393,115 @@ export const ProgramPageContent = ({ lang }: any) => {
})}
</div>
<div className="flex flex-col gap-0 pt-14 md:gap-10">
<Accordion
id="howToApply"
size="xs"
className="!border-none"
iconOnHover
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>
<span className="text-base font-medium text-tuatara-950">
{t("howToApply.openTasks.title")}
</span>
<ul className="list-decimal">
{howToApply?.openTasks?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
className="text-tuatara-950"
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
</ul>
</div>
<div>
<span className="text-base font-medium text-tuatara-950">
{t("howToApply.submitIdea.title")}
</span>
<ul className="list-decimal">
{howToApply?.submitIdea?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
className="text-tuatara-95"
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
</ul>
</div>
<span className="text-base text-tuatara-950">
{t("howToApply.description")}
</span>
</div>
</div>
</div>
),
},
]}
/>
<Accordion
id="faq"
size="xs"
className="!border-none"
iconOnHover
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={acceleratorProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="font-mediu text-left font-sans text-base text-black">
{question}
</span>
),
value: index.toString(),
children: (
<span className="flex flex-col gap-3 text-base text-tuatara-950">
{answer}
</span>
),
}
<div className="flex flex-col">
<AccordionLabel label={t("common.howToApply")} />
<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>
<span className="text-base font-medium text-tuatara-950">
{t("howToApply.openTasks.title")}
</span>
<ul className="list-decimal">
{howToApply?.openTasks?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
className="text-tuatara-950"
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
/>
</ul>
</div>
),
},
]}
/>
<div>
<span className="text-base font-medium text-tuatara-950">
{t("howToApply.submitIdea.title")}
</span>
<ul className="list-decimal">
{howToApply?.submitIdea?.description?.map(
(task: string, index: number) => {
return (
<li
key={index}
className="ml-8 list-item items-center"
>
<div
className="text-tuatara-95"
dangerouslySetInnerHTML={{
__html: task,
}}
></div>
</li>
)
}
)}
</ul>
</div>
<span className="text-base text-tuatara-950">
{t("howToApply.description")}
</span>
</div>
</div>
</div>
</div>
<div className="flex flex-col">
<AccordionLabel label={t("common.faq")} />
<div className="mt-10 flex flex-col gap-8">
<Accordion
className="!border-anakiwa-300"
size="xs"
items={acceleratorProgramFaq.map(
({ question, answer }, index) => {
return {
label: (
<span className="text-left font-sans text-base font-medium text-black">
{question}
</span>
),
value: index.toString(),
children: (
<span className="flex flex-col gap-3 text-base text-tuatara-950">
{answer}
</span>
),
}
}
)}
/>
</div>
</div>
</div>
</div>
</div>
<div className="lg:w-[320px]"></div>
</AppContent>
</div>
</div>
</div>
<Banner title={common("learnMore")} subtitle={common("learnMoreDiscord")}>
<Link
href={siteConfig.links.discord}
target="_blank"
rel="noreferrer"
passHref
>
<Button>
<div className="flex items-center gap-2">
<Icons.discord fill="white" className="h-4" />
<span className="text-[14px] uppercase">
{common("joinOurDiscord")}
</span>
<Icons.externalUrl fill="white" className="h-5" />
</div>
</Button>
</Link>
</Banner>
</Divider.Section>
)
}

View File

@@ -17,5 +17,9 @@ export const metadata: Metadata = {
}
export default function ProgramsPage({ params: { lang } }: any) {
return <ProgramPageContent lang={lang} />
return (
<div className="flex flex-col">
<ProgramPageContent lang={lang} />
</div>
)
}

View File

@@ -5,9 +5,11 @@ import { projects } from "@/data/projects"
import GithubVector from "@/public/social-medias/github-fill.svg"
import GlobalVector from "@/public/social-medias/global-line.svg"
import TwitterVector from "@/public/social-medias/twitter-fill.svg"
import { Divide } from "lucide-react"
import { ProjectInterface } from "@/lib/types"
import { Markdown } from "@/components/ui/markdown"
import { Divider } from "@/components/divider"
import { Icons } from "@/components/icons"
import DiscoverMoreProjects from "@/components/project/discover-more-projects"
import { ProjectTags } from "@/components/project/project-detail-tags"
@@ -63,91 +65,103 @@ export default async function ProjectDetailPage({ params }: PageProps) {
const hasSocialLinks = Object.keys(currProject?.links ?? {}).length > 0
return (
<section className="flex flex-col items-center bg-project-page-gradient">
<div className="flex w-full flex-col items-center justify-center gap-5 px-6 py-8 md:px-0 md:py-16">
<div className=" w-full md:max-w-[644px]">
<div className="flex flex-col">
<div className="flex flex-col gap-6 text-left">
<Link
className="flex items-center gap-2 text-tuatara-950/80 hover:text-tuatara-950"
href={`/${lang}/projects`}
>
<Icons.arrowLeft />
<span className="font-sans text-base">
{t("projectLibrary")}
</span>
</Link>
<div className="flex flex-col gap-2">
<h1 className="py-2 text-3xl font-bold leading-[110%] md:text-5xl">
{currProject.name}
</h1>
<p className="py-2 leading-[150%] text-slate-600">
{currProject.tldr}
</p>
<section className="bg-project-page-gradient">
<Divider.Section className="flex flex-col items-center">
<div className="flex w-full flex-col items-center justify-center gap-5 px-6 py-8 md:px-0 md:py-16">
<div className=" w-full md:max-w-[644px]">
<div className="flex flex-col">
<div className="flex flex-col gap-6 text-left">
<Link
className="flex items-center gap-2 text-tuatara-950/80 hover:text-tuatara-950"
href={`/${lang}/projects`}
>
<Icons.arrowLeft />
<span className="font-sans text-base">
{t("projectLibrary")}
</span>
</Link>
<div className="flex flex-col gap-2">
<h1 className="py-2 text-3xl font-bold leading-[110%] md:text-5xl">
{currProject.name}
</h1>
<p className="py-2 leading-[150%] text-slate-600">
{currProject.tldr}
</p>
</div>
</div>
</div>
{hasSocialLinks && (
<div className="flex flex-wrap items-center justify-start gap-6 pt-4">
{github && (
<Link href={github} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image src={GithubVector} alt="" width={16} height={16} />
<p className="text-slate-600">Github</p>
</div>
</Link>
)}
{website && (
<Link href={website} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image src={GlobalVector} alt="" width={16} height={16} />
<p className="text-slate-600">Website</p>
</div>
</Link>
)}
{twitter && (
<Link href={twitter} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image
src={TwitterVector}
alt=""
width={16}
height={16}
/>
<p className="text-slate-600">Twitter</p>
</div>
</Link>
)}
</div>
)}
<div className="mt-10 hidden h-[1px] w-full bg-anakiwa-300 md:block"></div>
</div>
<div className="mt-6 flex w-full flex-col gap-6 md:mt-[50px]">
<div className="relative flex items-center justify-center overflow-hidden rounded-lg">
<Image
src={`/project-banners/${
currProject.image ? currProject.image : "fallback.webp"
}`}
alt={`${currProject.name} banner`}
width={1200}
height={630}
className="w-full rounded-t-lg object-cover"
/>
{!currProject?.image && (
<span className="absolute left-1/2 top-1/2 w-full -translate-x-1/2 -translate-y-1/2 px-5 text-center text-3xl font-bold text-black">
{currProject?.imageAlt || currProject?.name}
</span>
{hasSocialLinks && (
<div className="flex flex-wrap items-center justify-start gap-6 pt-4">
{github && (
<Link href={github} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image
src={GithubVector}
alt=""
width={16}
height={16}
/>
<p className="text-slate-600">Github</p>
</div>
</Link>
)}
{website && (
<Link href={website} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image
src={GlobalVector}
alt=""
width={16}
height={16}
/>
<p className="text-slate-600">Website</p>
</div>
</Link>
)}
{twitter && (
<Link href={twitter} target="_blank" rel="noreferrer">
<div className="flex items-center gap-2">
<Image
src={TwitterVector}
alt=""
width={16}
height={16}
/>
<p className="text-slate-600">Twitter</p>
</div>
</Link>
)}
</div>
)}
<div className="mt-10 hidden h-[1px] w-full bg-anakiwa-300 md:block"></div>
</div>
<ProjectTags project={currProject} lang={lang} />
<div className="flex w-full flex-col gap-5 text-base font-normal leading-relaxed">
<Markdown>{currProject.description}</Markdown>
<div className="mt-6 flex w-full flex-col gap-6 md:mt-[50px]">
<div className="relative flex items-center justify-center overflow-hidden rounded-lg">
<Image
src={`/project-banners/${
currProject.image ? currProject.image : "fallback.webp"
}`}
alt={`${currProject.name} banner`}
width={1200}
height={630}
className="w-full rounded-t-lg object-cover"
/>
{!currProject?.image && (
<span className="absolute left-1/2 top-1/2 w-full -translate-x-1/2 -translate-y-1/2 px-5 text-center text-3xl font-bold text-black">
{currProject?.imageAlt || currProject?.name}
</span>
)}
</div>
<ProjectTags project={currProject} lang={lang} />
<div className="flex w-full flex-col gap-5 text-base font-normal leading-relaxed">
<Markdown>{currProject.description}</Markdown>
</div>
<ProjectExtraLinks project={currProject} lang={lang} />
</div>
<ProjectExtraLinks project={currProject} lang={lang} />
</div>
</div>
</div>
<DiscoverMoreProjects project={currProject} lang={lang} />
<DiscoverMoreProjects project={currProject} lang={lang} />
</Divider.Section>
</section>
)
}

View File

@@ -6,6 +6,7 @@ import ProjectFiltersBar from "@/components/project/project-filters-bar"
import { ProjectList } from "@/components/project/project-list"
import { ProjectResultBar } from "@/components/project/project-result-bar"
import { useTranslation } from "@/app/i18n"
import { Divider } from "@/components/divider"
export const metadata: Metadata = {
title: "Project Library",
@@ -17,7 +18,7 @@ export default async function ProjectsPage({ params: { lang } }: any) {
const { t } = await useTranslation(lang, "projects-page")
return (
<>
<Divider.Section>
<PageHeader
title={t("title")}
subtitle={t("subtitle")}
@@ -44,6 +45,6 @@ export default async function ProjectsPage({ params: { lang } }: any) {
<ProjectList lang={lang} />
</div>
</div>
</>
</Divider.Section>
)
}

View File

@@ -11,6 +11,7 @@ import { AppContent } from "@/components/ui/app-content"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Banner } from "@/components/banner"
import { Divider } from "@/components/divider"
import { Icons } from "@/components/icons"
import { PageHeader } from "@/components/page-header"
import { useTranslation } from "@/app/i18n/client"
@@ -173,7 +174,7 @@ export default function ResourcePage({ params: { lang } }: LangProps) {
const { t: common } = useTranslation(lang, "common")
return (
<main className="bg-white">
<Divider.Section className="bg-white">
<PageHeader
title={t("title")}
subtitle={t("subtitle")}
@@ -206,27 +207,29 @@ export default function ResourcePage({ params: { lang } }: LangProps) {
</Link>
}
/>
<AppContent className="grid grid-cols-1 gap-6 py-10 md:grid-cols-[3fr_1fr] md:pb-20 lg:grid-cols-[4fr_1fr]">
<div className="flex flex-col gap-6">
<article className="flex flex-col space-y-8 ">
<ResourcesContent
components={{
ResourceItem: (props: ResourceItemProps) => (
<ResourceItem {...props} />
),
ResourceCard: (props: ResourceCardProps) => (
<ResourceCard {...props} />
),
}}
/>
</article>
</div>
<section className="relative hidden md:block ">
<div className="sticky right-0 top-16 ml-auto">
<ResourceNav lang={lang} />
<div className="flex justify-center">
<AppContent className="grid grid-cols-1 gap-6 py-10 md:grid-cols-[3fr_1fr] md:pb-20 lg:grid-cols-[4fr_1fr]">
<div className="flex flex-col gap-6">
<article className="flex flex-col space-y-8 ">
<ResourcesContent
components={{
ResourceItem: (props: ResourceItemProps) => (
<ResourceItem {...props} />
),
ResourceCard: (props: ResourceCardProps) => (
<ResourceCard {...props} />
),
}}
/>
</article>
</div>
</section>
</AppContent>
<section className="relative hidden md:block ">
<div className="sticky right-0 top-16 ml-auto">
<ResourceNav lang={lang} />
</div>
</section>
</AppContent>
</div>
<Banner
title={
<h3 className="py-2 font-display text-[18px] font-bold text-tuatara-950 md:text-3xl">
@@ -254,6 +257,6 @@ export default function ResourcePage({ params: { lang } }: LangProps) {
</Button>
</Link>
</Banner>
</main>
</Divider.Section>
)
}

View File

@@ -55,6 +55,7 @@
"sortBy": "Sort by: {{option}}",
"tryItOut": "Try it out!",
"learnMore": "Learn more",
"learnMoreDiscord": "Join our Discord to learn more about our programs and other educational opportunities!",
"buildWithThisTool": "Build with this tool",
"deepDiveResearch": "Dive deeper into the research",
"searchProjectPlaceholder": "Search project title or keyword",

View File

@@ -1,6 +1,6 @@
{
"title": "Join our programs",
"description": "Want to explore the world of programmable cryptography and learn how to make substantial contributions to open-source projects? Join our free programs to kickstart your journey!",
"title": "Get started with programmable cryptography",
"description": "PSE offers free educational programs to help you dive deep into Zero Knowledge Proofs, Fully Homomorphic Encryption, Multi-Party Computation and the latest in programmable cryptography. Whether youre looking to learn the basics or start making open-source contributions, we have resources for your learning journey!",
"common": {
"faq": "FAQ",
"curriculum": "Curriculum",

View File

@@ -10,7 +10,7 @@ type BannerProps = {
const Banner = ({ title, subtitle, children }: BannerProps) => {
return (
<section className="relative border-t border-tuatara-600 bg-cover-gradient text-center">
<section className="relative bg-cover-gradient text-center">
<div className="py-16">
<AppContent className="flex flex-col gap-6">
<div className="flex flex-col items-center text-center">

18
components/divider.tsx Normal file
View File

@@ -0,0 +1,18 @@
import { HTMLAttributes } from "react"
import { cn } from "@/lib/utils"
const Section = ({ children, className }: HTMLAttributes<HTMLDivElement>) => {
return (
<div className={cn("divide-y divide-tuatara-300", className)}>
{children}
</div>
)
}
const Divider = {
displayName: "Divider",
Section,
}
export { Divider }

View File

@@ -23,7 +23,7 @@ const PageHeader = ({
image,
}: PageHeaderProps) => {
return (
<div className="bg-cover-gradient">
<div className="flex h-full w-full items-center bg-cover-gradient md:h-[600px]">
<AppContent className="relative flex w-full flex-col gap-10 py-10 md:gap-14 md:py-20">
<div className="flex flex-col items-start justify-between gap-10 md:flex-row md:gap-28">
<div className="flex w-full flex-col justify-center gap-6 md:max-w-[700px] md:gap-8 lg:gap-14">

View File

@@ -34,7 +34,7 @@ export const WhatWeDo = ({ lang }: LangProps["params"]) => {
]
return (
<div className="border-t border-tuatara-600 bg-cover-gradient">
<div className="bg-cover-gradient">
<AppContent className="mx-auto max-w-[978px]">
<section className="flex flex-col gap-16 py-16 md:pb-24">
<div className="flex flex-col text-center">

View File

@@ -18,7 +18,7 @@ export function SiteHeader({ lang }: SiteHeaderProps) {
const { MAIN_NAV, activeLanguageLabel } = useAppSettings(lang)
return (
<header className="sticky top-0 z-40 w-full bg-white shadow-sm">
<header className="sticky top-0 z-40 w-full border-b border-tuatara-300 bg-white shadow-sm">
<AppContent>
<div className="flex h-16 items-center justify-between space-x-4 sm:space-x-0">
<MainNav items={MAIN_NAV} lang={lang} />

View File

@@ -23,7 +23,7 @@ export const siteConfig = {
discordAnnouncementChannel:
"https://discord.com/channels/943612659163602974/969614451089227876",
acceleratorProgram:
"https://github.com/privacy-scaling-explorations/acceleration-program/issues/new?assignees=&labels=&projects=&template=propose-your-open-task.md&title=",
"https://github.com/privacy-scaling-explorations/acceleration-program",
coreProgram:
"https://docs.google.com/forms/d/e/1FAIpQLSendzYY0z_z7fZ37g3jmydvzS9I7OWKbY2JrqAnyNqeaBHvMQ/viewform",
},