footer new design

This commit is contained in:
Kalidou Diagne
2024-03-20 12:14:42 +00:00
parent 3acb3b9dd1
commit 49277e00da
21 changed files with 348 additions and 223 deletions

View File

@@ -1,6 +1,7 @@
"use client"
import { useCallback, useEffect, useRef, useState } from "react"
import Image from "next/image"
import Link from "next/link"
import { LangProps } from "@/types/common"
@@ -176,6 +177,16 @@ export default function ResourcePage({ params: { lang } }: LangProps) {
<PageHeader
title={t("title")}
subtitle={t("subtitle")}
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-[343px]">
<Image
width={343}
height={320}
src="/icons/resource-illustration.webp"
alt="illustrations"
/>
</div>
}
actions={
<Link
href={siteConfig.addGithubResource}

View File

@@ -10,8 +10,9 @@
"languages": "Languages {{locale}}",
"blog": "Blog",
"activity": "Activity",
"report": "Report",
"firstGoodIssue": "First Good Issue"
"report": "Reports",
"firstGoodIssue": "First Good Issue",
"openIssues": "Open Issues"
},
"footer": {
"description": "Privacy + Scaling Explorations is a multidisciplinary team supported by the Ethereum Foundation.",

View File

@@ -44,13 +44,16 @@ export function MainNav({ items, lang = fallbackLng }: MainNavProps) {
key={index}
href={item.href}
target={item.external ? "_blank" : undefined}
className={cn("flex items-center border-b-2 uppercase", {
"cursor-not-allowed": item.disabled,
"border-transparent": item.href !== router,
"!border-orange": item.href === router || isActive,
"text-sm font-medium duration-200 ease-in-out hover:border-orange":
true,
})}
className={cn(
"flex cursor-pointer items-center border-b-2 uppercase",
{
"cursor-not-allowed": item.disabled,
"border-transparent": item.href !== router,
"!border-orange": item.href === router || isActive,
"text-sm font-medium duration-200 ease-in-out hover:border-orange":
true,
}
)}
>
{item.title}
</Link>

View File

@@ -15,6 +15,12 @@ import i18next from "i18next"
import { useDebounce } from "react-use"
import { IThemeStatus, IThemesButton, LangProps } from "@/types/common"
import {
ProjectSectionLabelMapping,
ProjectSections,
ProjectStatusLabelMapping,
ProjectStatusList,
} from "@/lib/types"
import { cn, queryStringToObject } from "@/lib/utils"
import { useTranslation } from "@/app/i18n/client"
import { LocaleTypes } from "@/app/i18n/settings"
@@ -30,11 +36,12 @@ import { Modal } from "../ui/modal"
interface FilterWrapperProps {
label: string
children?: ReactNode
className?: string
}
const FilterWrapper = ({ label, children }: FilterWrapperProps) => {
const FilterWrapper = ({ label, children, className }: FilterWrapperProps) => {
return (
<div className="flex flex-col gap-4 py-6">
<div className={cn("flex flex-col gap-4 py-6", className)}>
<span className="text-xl font-bold">{label}</span>
{children}
</div>
@@ -190,83 +197,103 @@ export default function ProjectFiltersBar({ lang }: LangProps["params"]) {
open={showModal}
setOpen={setShowModal}
>
{Object.entries(filters).map(([key, items]) => {
const filterLabel =
FilterLabelMapping(lang)?.[key as ProjectFilter] ?? ""
const type = FilterTypeMapping?.[key as ProjectFilter]
const hasItems = items.length > 0
<div className="flex flex-col divide-y divide-tuatara-200">
{Object.entries(filters).map(([key, items]) => {
const filterLabel =
FilterLabelMapping(lang)?.[key as ProjectFilter] ?? ""
const type = FilterTypeMapping?.[key as ProjectFilter]
const hasItems = items.length > 0
const hasActiveThemeFilters =
(activeFilters?.themes ?? [])?.length > 0
const hasActiveThemeFilters =
(activeFilters?.themes ?? [])?.length > 0
if (key === "themes" && !hasActiveThemeFilters) return null
if (key === "themes" && !hasActiveThemeFilters) return null
return (
hasItems && (
<FilterWrapper key={key} label={filterLabel}>
<div
className={cn("gap-y-2", {
"grid grid-cols-1 gap-2 md:grid-cols-3":
type === "checkbox",
"flex gap-x-4 flex-wrap": type === "button",
})}
>
{items.map((item) => {
const isActive =
activeFilters?.[key as ProjectFilter]?.includes(item)
return (
hasItems && (
<FilterWrapper key={key} label={filterLabel}>
<div
className={cn("gap-y-2", {
"grid grid-cols-1 gap-2 md:grid-cols-3":
type === "checkbox",
"flex gap-x-4 flex-wrap": type === "button",
})}
>
{items.map((item) => {
const isActive =
activeFilters?.[key as ProjectFilter]?.includes(item)
if (type === "checkbox") {
return (
<Checkbox
key={item}
onClick={() =>
toggleFilter({
tag: key as ProjectFilter,
value: item,
searchQuery,
})
}
name={item}
label={item}
checked={isActive}
/>
)
}
if (type === "button") {
const { icon, label } = ThemesButtonMapping(lang)[item]
if (!isActive) return null
return (
<div>
<CategoryTag
variant="selected"
closable
onClose={() => {
if (type === "checkbox") {
return (
<Checkbox
key={item}
onClick={() =>
toggleFilter({
tag: "themes",
tag: key as ProjectFilter,
value: item,
searchQuery,
})
}}
>
<div className="flex items-center gap-2">
{icon}
<span className="font-sans text-sm md:text-base">
{label}
</span>
</div>
</CategoryTag>
</div>
)
}
}
name={item}
label={item}
checked={isActive}
/>
)
}
return null
})}
</div>
</FilterWrapper>
if (type === "button") {
const { icon, label } = ThemesButtonMapping(lang)[item]
if (!isActive) return null
return (
<div>
<CategoryTag
variant="selected"
closable
onClose={() => {
toggleFilter({
tag: "themes",
value: item,
searchQuery,
})
}}
>
<div className="flex items-center gap-2">
{icon}
<span className="font-sans text-sm md:text-base">
{label}
</span>
</div>
</CategoryTag>
</div>
)
}
return null
})}
</div>
</FilterWrapper>
)
)
)
})}
})}
<FilterWrapper
className="hidden"
label={t("filterLabels.fundingSource")}
>
{ProjectSections.map((section) => {
const label = ProjectSectionLabelMapping[section]
return <Checkbox key={section} name={section} label={label} />
})}
</FilterWrapper>
<FilterWrapper
className="hidden"
label={t("filterLabels.projectStatus")}
>
{ProjectStatusList.map((section) => {
const label = ProjectStatusLabelMapping[section]
return <Checkbox key={section} name={section} label={label} />
})}
</FilterWrapper>
</div>
</Modal>
<div className="flex flex-col gap-6">
<span className="text-lg font-medium">{t("whatDoYouWantDoToday")}</span>

View File

@@ -7,7 +7,11 @@ import { useProjectFiltersState } from "@/state/useProjectFiltersState"
import { cva } from "class-variance-authority"
import { LangProps } from "@/types/common"
import { ProjectSection, ProjectSections } from "@/lib/types"
import {
ProjectSection,
ProjectSectionLabelMapping,
ProjectSections,
} from "@/lib/types"
import { cn } from "@/lib/utils"
import { useTranslation } from "@/app/i18n/client"
@@ -35,12 +39,6 @@ const NoResults = ({ lang }: LangProps["params"]) => {
)
}
export const ProjectSectionLabelMapping: Record<ProjectSection, string> = {
pse: "PSE projects",
grant: "Grants",
collaboration: "Collaborations",
}
export const ProjectList = ({ lang }: LangProps["params"]) => {
const { t } = useTranslation(lang, "resources-page")
const SCROLL_OFFSET = -400
@@ -92,7 +90,7 @@ export const ProjectList = ({ lang }: LangProps["params"]) => {
if (noItems) return <NoResults lang={lang} />
return (
<div className="relative grid grid-cols-1 items-start justify-between gap-8 md:gap-10 md:grid-cols-[1fr_200px]">
<div className="relative grid grid-cols-1 items-start justify-between gap-8 md:grid-cols-[1fr_200px] md:gap-10">
<div className="flex flex-col gap-10 md:gap-20">
{ProjectSections.map((section) => {
const sectionProjects =

View File

@@ -13,11 +13,25 @@ import { useTranslation } from "@/app/i18n/client"
import { Icons } from "./icons"
import { AppContent } from "./ui/app-content"
const SocialMedia = ({ label }: { label: string }) => {
const ItemLabel = ({
label,
external = false,
icon,
}: {
label: string
external?: boolean
icon?: React.ReactNode
}) => {
return (
<span className="mt-[0.9px] font-sans text-sm font-normal uppercase leading-[21px] text-white md:block">
{label}
</span>
<div className="group flex items-center gap-2">
{external && (
<Icons.externalUrl className="w-5 duration-200 group-hover:text-orange" />
)}
{icon && <div className="group-hover:text-orange">{icon}</div>}
<span className="mt-[0.9px] font-sans text-sm font-normal uppercase leading-[21px] text-white duration-200 group-hover:text-orange md:block">
{label}
</span>
</div>
)
}
@@ -32,108 +46,144 @@ export function SiteFooter({ lang }: LangProps["params"]) {
return (
<footer className="flex flex-col">
<div className="bg-tuatara-950 py-8 text-left text-[14px] uppercase text-white">
<AppContent className="grid grid-cols-1 justify-between gap-8 bg-tuatara-950 py-2 text-white md:grid-cols-4 lg:px-40">
<LinksWrapper>
{MAIN_NAV.map(
({ title, href, external = false }: NavItem, indexKey) => (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
{title}
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.jobs}
target="_blank"
rel="noreferrer"
className="flex items-center gap-2"
>
<Icons.jobs fill="white" />
{t("menu.jobs")}
<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>
</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.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="bg-tuatara-950 py-8 text-left text-[14px] text-white">
<AppContent className="grid grid-cols-1 justify-between gap-10 bg-tuatara-950 py-2 text-white lg:grid-cols-[400px_1fr] lg:gap-24">
<div className="order-1 flex flex-col items-center gap-4 md:flex-row md:gap-8">
<Image
width={140}
height={140}
src="/logos/pse-logo-circle-white.svg"
alt="logo PSE"
className="h-36 w-36"
/>
<span className="text-center font-sans text-sm leading-[21px] md:text-left">
{t("footer.description")}
</span>
</div>
<div className="order-2 grid grid-cols-1 justify-between gap-10 uppercase lg:grid-cols-4 lg:gap-0">
<LinksWrapper>
{MAIN_NAV.map(
(
{ title, href, external = false, onlyHeader }: NavItem,
indexKey
) =>
!onlyHeader && (
<Link
key={indexKey}
href={href}
target={external ? "_blank" : undefined}
>
<ItemLabel label={title} />
</Link>
)
)}
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.articles}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<ItemLabel label="Blog" external />
</Link>
<Link
href={siteConfig.links.jobs}
target="_blank"
rel="noreferrer"
className="flex items-center gap-2"
>
<ItemLabel label={t("menu.jobs")} external />
</Link>
<Link
href={siteConfig.links.report}
target="_blank"
rel="noreferrer"
className="flex items-center gap-2"
>
<ItemLabel label={t("menu.report")} external />
</Link>
<Link
href={siteConfig.links.firstGoodIssue}
target="_blank"
rel="noreferrer"
className="flex items-center gap-2"
>
<ItemLabel label={t("menu.firstGoodIssue")} external />
</Link>
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.discord}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<ItemLabel
label="Discord"
icon={<Icons.discord className="w-4" />}
/>
</Link>
<Link
href={siteConfig.links.github}
className="flex items-start gap-2"
target="_blank"
rel="noreferrer"
>
<ItemLabel
label="Github"
icon={<Icons.gitHub className="w-4" />}
/>
</Link>
<Link
href={siteConfig.links.twitter}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<ItemLabel
label="Twitter"
icon={
<div className="w-4">
<Icons.twitter className="w-full" />
</div>
}
/>
</Link>
<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>
<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>
<Link
href={siteConfig.links.youtube}
className="flex items-center gap-2"
target="_blank"
rel="noreferrer"
>
<ItemLabel
label="Youtube"
icon={
<div className="w-4">
<Icons.youtube className="w-full" />
</div>
}
/>
</Link>
</LinksWrapper>
<LinksWrapper>
<Link
href={siteConfig.links.privacyPolicy}
target="_blank"
rel="noreferrer"
>
<ItemLabel label={t("footer.privacyPolicy")} />
</Link>
<Link
href={siteConfig.links.termOfUse}
target="_blank"
rel="noreferrer"
>
<ItemLabel label={t("footer.termsOfUse")} />
</Link>
</LinksWrapper>
</div>
</AppContent>
</div>
</footer>

View File

@@ -16,6 +16,10 @@ export const siteConfig = {
jobs: "https://jobs.lever.co/ethereumfoundation/?department=Ethereum%20Foundation&team=Privacy%20and%20Scaling%20Explorations",
termOfUse: "https://ethereum.org/en/terms-of-use/",
privacyPolicy: "https://ethereum.org/en/privacy-policy/",
activity:
"https://pse-team.notion.site/50dcf22c5191485e93406a902ae9e93b?v=453023f8227646dd949abc34a7a4a138&pvs=4",
report: "https://reports.pse.dev/",
firstGoodIssue: "https://pse-gfis.vercel.app",
discordAnnouncementChannel:
"https://discord.com/channels/943612659163602974/969614451089227876",
},

View File

@@ -7,7 +7,7 @@ Channel 4 is a community-driven platform where users can submit and discover con
export const channel4: ProjectInterface = {
id: "channel-4",
section: "pse",
projectStatus: "archived",
projectStatus: "inactive",
image: "channel4.svg",
name: "Channel 4",
tldr: "Content discovery through community contributions, using state channels to reward users for popular posts.",

View File

@@ -8,7 +8,7 @@ export const Coco: ProjectInterface = {
tldr: "Integrating Nova into the EVM involves wrapping Liam Eagen's theoretical ECIP argument in Halo 2",
description:
"With Coco, groups can collaborate to curate feeds of any topic they're interested in. As you scroll through your Coco feed, rather than upvoting or downvoting posts, you'll spend WETH to predict what other group members and the group's moderators will want to see. When you're right, you'll get back your original WETH and more — but if you're wrong, you'll lose what you put in. Through this process, you help Coco filter value from noise to make sure group feeds only consist of posts that the group cares about.",
projectStatus: "archived",
projectStatus: "inactive",
tags: {
keywords: ["prediction market", "scaling"],
},

View File

@@ -7,7 +7,7 @@ CryptKeeper is a browser extension that generates Semaphore and RLN proofs for w
export const cryptkeeper: ProjectInterface = {
id: "cryptkeeper",
section: "pse",
projectStatus: "archived",
projectStatus: "inactive",
image: "cryptkeeper.webp",
name: "CryptKeeper",
tldr: "A browser extension for secure, portable anonymous identity management across applications.",

View File

@@ -7,7 +7,7 @@ EigenTrust is a library designed to manage trust within a distributed network, i
export const eigenTrust: ProjectInterface = {
id: "eigen-trust",
section: "pse",
projectStatus: "archived",
projectStatus: "inactive",
image: "",
name: "EigenTrust",
tldr: "A distributed reputation system with zero-knowledge features.",

View File

@@ -8,7 +8,7 @@ export const Interep: ProjectInterface = {
tldr: "An identity bridge from web2 to web3",
description:
"Interep aims to provide an identity solution for Ethereum users by bridging from an established digital identity source such as Reddit, Twitter, and Github. The product provides an identity layer in the application stack and uses the Semaphore framework to ensure privacy. Interep allows users to establish sybil-resistant decentralized identities on web3 without starting from scratch. By leveraging zero-knowledge proofs, Interep ensures only essential information is disclosed.",
projectStatus: "archived",
projectStatus: "inactive",
tags: {
keywords: ["social", "reputation"],
},

View File

@@ -9,7 +9,7 @@ Using anonymous identifiers (epoch keys), the protocol allows for trustless enga
export const unirepProtocol: ProjectInterface = {
id: "unirep-protocol",
section: "pse",
projectStatus: "archived",
projectStatus: "inactive",
image: "unirep.svg",
name: "UniRep Protocol",
tldr: "A Zero-Knowledge Protocol built to handle anonymous user data.",
@@ -26,22 +26,22 @@ export const unirepProtocol: ProjectInterface = {
types: ["Legos/dev tools, Protocol"],
builtWith: ["semaphore", "circom"],
},
extraLinks: {
extraLinks: {
buildWith: [
{
label: "Getting Started with create-unirep-app",
url: 'https://developer.unirep.io/docs/next/getting-started/create-unirep-app',
url: "https://developer.unirep.io/docs/next/getting-started/create-unirep-app",
},
],
play: [
{
label: "Try it out: UniRep.social (Staging)",
url: 'https://social-staging.unirep.workers.dev',
url: "https://social-staging.unirep.workers.dev",
},
{
label: "Try it out: Trustlist (coming soon) ",
url: 'https://trustlist.pse.dev',
}
url: "https://trustlist.pse.dev",
},
],
},
}

View File

@@ -7,7 +7,7 @@ Zkitter is a decentralized social network that emphasizes privacy by default. It
export const zkitter: ProjectInterface = {
id: "zkitter",
section: "pse",
projectStatus: "archived",
projectStatus: "inactive",
image: "zkitter.webp",
name: "Zkitter",
tldr: "A decentralized social network prioritizing privacy and anonymity",

View File

@@ -8,7 +8,7 @@ export const Zkopru: ProjectInterface = {
tldr: "Optimistic Rollup with zk-SNARKs for private Ethereum transactions.",
description:
"ZKOPRU is one of the initial projects of EF's PSE team. It is a Layer 2 scaling solution for Ethereum, emphasizing private transactions through zk-SNARKs and optimistic rollups. It provides an economical Ethereum privacy wallet, enabling users to transact with ETH, ERC-20s, and NFTs anonymously",
projectStatus: "archived",
projectStatus: "inactive",
links: {
website: "https://zkopru.network/",
github: "https://github.com/zkopru-network",

View File

@@ -1,3 +1,4 @@
import { siteConfig } from "@/config/site"
import { MainNavProps } from "@/components/main-nav"
import { useTranslation } from "@/app/i18n/client"
import { LocaleTypes, fallbackLng, languageList } from "@/app/i18n/settings"
@@ -31,24 +32,7 @@ export function useAppSettings(lang: LocaleTypes) {
title: t("menu.blog"),
href: "https://mirror.xyz/privacy-scaling-explorations.eth",
external: true,
},
{
title: t("menu.activity"),
href: "https://pse-team.notion.site/50dcf22c5191485e93406a902ae9e93b?v=453023f8227646dd949abc34a7a4a138&pvs=4",
external: true,
onlyFooter: true,
},
{
title: t("menu.report"),
href: "https://reports.pse.dev/",
external: true,
onlyFooter: true,
},
{
title: t("menu.firstGoodIssue"),
href: "https://pse-gfis.vercel.app",
external: true,
onlyFooter: true,
onlyHeader: true,
},
]

View File

@@ -2,6 +2,18 @@
export const ProjectSections = ["pse", "grant", "collaboration"] as const
export type ProjectSection = (typeof ProjectSections)[number]
export const ProjectStatusList = ["active", "inactive"] as const
export type ProjectStatusType = (typeof ProjectStatusList)[number]
export const ProjectSectionLabelMapping: Record<ProjectSection, string> = {
pse: "PSE projects",
grant: "Grants",
collaboration: "Collaborations",
}
export const ProjectStatusLabelMapping: Record<ProjectStatusType, string> = {
active: "Active",
inactive: "Not Currently Active",
}
export interface AnnounceInterface {
id: number
type?: number
@@ -50,7 +62,6 @@ export type ActionLinkType = Partial<
Record<ProjectExtraLinkType, Array<ActionLinkTypeLink>>
>
export type ProjectStatusType = "active" | "inactive" | "archived"
export interface ProjectInterface {
id: string
section: ProjectSection

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@@ -0,0 +1,34 @@
<svg width="134" height="133" viewBox="0 0 134 133" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M67.3018 132.651C49.5378 132.651 32.8401 125.802 20.2783 113.367C7.71928 100.93 0.801758 84.3946 0.801758 66.8094C0.801758 49.2241 7.71928 32.6889 20.2783 20.2515C32.8373 7.81403 49.5378 0.967773 67.3018 0.967773C85.0657 0.967773 101.763 7.81681 114.325 20.2515C126.884 32.6861 133.802 49.2213 133.802 66.8094C133.802 84.3974 126.884 100.93 114.325 113.367C101.766 125.802 85.0657 132.651 67.3018 132.651ZM67.3018 4.29255C50.4361 4.29255 34.5806 10.7952 22.6541 22.6037C10.7275 34.4122 4.15978 50.1107 4.15978 66.8094C4.15978 83.508 10.7275 99.2065 22.6541 111.015C34.5806 122.823 50.4361 129.326 67.3018 129.326C84.1674 129.326 100.023 122.823 111.949 111.015C123.876 99.2065 130.444 83.508 130.444 66.8094C130.444 50.1107 123.876 34.4122 111.949 22.6037C100.023 10.7952 84.1674 4.29255 67.3018 4.29255Z" fill="#F6F7F7"/>
<path d="M19.9004 60.1063L11.052 58.2804L11.7208 55.1025C12.1853 52.8999 13.6321 51.8082 15.5433 52.2016L15.7364 52.2404C17.6253 52.6311 18.5208 54.2076 18.059 56.4103L17.8016 57.6376L20.3145 58.1558L19.9032 60.1091L19.9004 60.1063ZM13.1703 56.679L16.0918 57.283L16.3688 55.9614C16.5619 55.0443 16.1002 54.3766 15.2215 54.1965C14.3205 54.0109 13.6405 54.4403 13.4474 55.3574L13.1703 56.679Z" fill="#F6F7F7"/>
<path d="M21.8984 51.6531L13.5677 48.1842L14.9333 44.9675C15.8036 42.9172 17.2755 42.0251 19.1196 42.7925L19.3015 42.8674C20.5132 43.3716 21.0785 44.2665 21.0729 45.4108L24.9122 44.5574L24.0083 46.6881L20.6027 47.3669L20.0319 48.7106L22.6819 49.8134L21.9012 51.6503L21.8984 51.6531ZM15.9211 47.0012L18.5711 48.1039L19.2175 46.58C19.5561 45.7848 19.2595 45.0395 18.4536 44.7071C17.6617 44.3774 16.9061 44.6821 16.5675 45.4773L15.9211 47.0012Z" fill="#F6F7F7"/>
<path d="M25.9923 43.0088L18.3444 38.3763L19.3966 36.6751L27.0445 41.3076L25.9923 43.0088Z" fill="#F6F7F7"/>
<path d="M29.7534 37.5207L21.1429 33.8634L22.4805 32.2925L29.44 35.3817L29.7086 35.0659L25.3544 28.9178L26.6528 27.394L31.869 35.0409L29.7562 37.5234L29.7534 37.5207Z" fill="#F6F7F7"/>
<path d="M33.7804 32.7966L30.47 24.0414L33.0081 22.0216L41.017 27.0365L39.3883 28.3304L37.4295 27.0642L34.5108 29.3887L35.3475 31.5471L33.7776 32.7966H33.7804ZM35.9547 26.1194L32.9381 24.1688L32.5827 24.4515L33.8784 27.7735L35.9547 26.1194Z" fill="#F6F7F7"/>
<path d="M39.7914 22.7254L39.6683 22.4872C38.6609 20.5255 38.8568 17.7937 41.6244 16.4001C43.8043 15.3029 45.917 15.8487 47.0867 17.6468L45.279 18.5556C44.641 17.6912 43.558 17.5111 42.475 18.0569C41.0507 18.7745 40.7765 20.1958 41.5488 21.7031C42.3127 23.1881 43.6504 23.8088 45.1167 23.0718C46.222 22.5149 46.7649 21.5313 46.4459 20.5061L48.2425 19.6029C48.942 21.4482 48.2592 23.5788 45.9702 24.7314C43.0795 26.186 40.7065 24.518 39.7886 22.7282L39.7914 22.7254Z" fill="#F6F7F7"/>
<path d="M53.5955 21.4727L52.6832 18.2283L52.2579 18.3447L48.245 13.7343L50.2319 13.1857L53.0834 16.5659L53.4611 16.4606L53.9593 12.1578L55.8397 11.6397L55.0142 17.5855L54.5889 17.7019L55.5011 20.9463L53.5955 21.4727Z" fill="#F6F7F7"/>
<path d="M65.1081 18.4167L65.0465 16.1559L62.875 16.2141L62.833 14.6348L65.0045 14.5766L64.943 12.3047L66.6863 12.2576L66.7479 14.5295L68.9334 14.4713L68.9754 16.0506L66.7899 16.1088L66.8514 18.3696L65.1081 18.4167Z" fill="#F6F7F7"/>
<path d="M74.6699 17.1755L76.5756 17.5939C76.4273 18.2588 76.8107 18.9543 78.0475 19.2258C79.1389 19.4641 79.8301 19.1316 79.9784 18.4666C80.1043 17.9097 79.7209 17.4886 78.6744 17.1589L78.0279 16.9539C76.3097 16.4275 75.4115 15.2084 75.7585 13.6651C76.1306 12.0027 77.6334 11.2491 79.5866 11.6786C81.649 12.1302 82.6312 13.5294 82.2506 15.2278L80.331 14.8066C80.4709 14.1777 80.1295 13.5155 79.2172 13.316C78.3413 13.1248 77.8013 13.5155 77.6725 14.0863C77.5606 14.585 77.7929 15.0588 78.5848 15.2943L79.2424 15.5021C81.1117 16.0867 82.2534 17.2836 81.8925 18.8878C81.5175 20.5613 79.8944 21.3509 77.6753 20.8633C75.2883 20.3396 74.2865 18.8601 74.6643 17.1755H74.6699Z" fill="#F6F7F7"/>
<path d="M84.5424 17.8736L84.6516 17.6298C85.5582 15.621 87.8249 14.0529 90.6624 15.308C92.8927 16.2943 93.7938 18.2642 93.1194 20.2951L91.2697 19.4778C91.5495 18.4416 91.0066 17.4968 89.8957 17.0064C88.4377 16.3608 87.1477 17.0424 86.4537 18.5856C85.7681 20.1067 86.1207 21.528 87.6234 22.193C88.7567 22.6945 89.8677 22.4922 90.4721 21.6029L92.3107 22.4174C91.3033 24.1158 89.1989 24.9304 86.8567 23.8942C83.896 22.5864 83.7141 19.7077 84.5424 17.8763V17.8736Z" fill="#F6F7F7"/>
<path d="M91.7817 25.9226L99.4715 20.4949L102.096 22.4011L99.2701 31.3586L97.5854 30.1367L98.3158 27.9368L95.2936 25.7425L93.4047 27.1001L91.7789 25.9198L91.7817 25.9226ZM98.8587 26.28L99.9836 22.8887L99.6171 22.6228L96.7096 24.7201L98.8587 26.28Z" fill="#F6F7F7"/>
<path d="M100.459 32.6717L106.993 26.5929L108.373 28.0475L103.129 32.9294L105.535 35.4645L104.245 36.6642L100.459 32.6773V32.6717Z" fill="#F6F7F7"/>
<path d="M105.457 38.3209L112.722 33.1204L113.903 34.7357L106.638 39.9362L105.457 38.3209Z" fill="#F6F7F7"/>
<path d="M108.258 42.0618L116.303 38.1413L117.761 41.0754L112.674 47.2817L112.75 47.434L119.329 44.2284L120.162 45.9102L112.117 49.8307L110.648 46.8744L115.735 40.6681L115.66 40.5158L109.081 43.7214L108.255 42.0618H108.258Z" fill="#F6F7F7"/>
<path d="M117.107 50.7727L117.37 50.7117C119.572 50.2103 122.18 51.1883 122.849 54.0698C123.392 56.4054 122.354 58.3504 120.375 58.9987L119.925 57.0565C120.846 56.6852 121.29 55.6601 121.016 54.4881C120.664 52.9726 119.309 52.3437 117.681 52.7149C115.968 53.1056 115.064 54.308 115.448 55.9566C115.652 56.8349 116.142 57.4832 116.766 57.7769L117.496 57.6106L116.97 55.347L118.383 55.0256L119.488 59.7884L118.075 60.1098L117.91 59.3977L116.427 59.7357C115.047 59.2758 114.065 58.0789 113.665 56.3583C112.946 53.2524 114.941 51.2659 117.107 50.7727Z" fill="#F6F7F7"/>
<path d="M92.0057 68.6461C92.0057 69.4995 91.3957 70.2115 90.5814 70.375C90.4666 70.3999 90.3463 70.411 90.2232 70.411H84.2767C83.2917 70.411 82.4941 71.2007 82.4941 72.1759V78.0636C82.4941 78.6731 82.1835 79.2106 81.7078 79.5265C81.5175 79.6539 81.302 79.7453 81.0698 79.7924C80.955 79.8146 80.8347 79.8285 80.7116 79.8285H74.7651C73.7801 79.8285 72.9825 80.6181 72.9825 81.5934V87.481C72.9825 88.4562 72.185 89.2459 71.2 89.2459H65.2535C64.2685 89.2459 63.4709 88.4562 63.4709 87.481V81.5934C63.4709 80.6181 64.2685 79.8285 65.2535 79.8285H71.2C72.185 79.8285 72.9825 79.0388 72.9825 78.0636V72.1759C72.9825 71.2007 73.7801 70.411 74.7651 70.411H80.7116C81.6966 70.411 82.4941 69.6214 82.4941 68.6461V60.9936C82.4941 55.8042 78.2546 51.5956 73.0161 51.5762C67.7804 51.5956 63.5381 55.8042 63.5381 60.9936V68.6461C63.5381 69.6214 62.7406 70.411 61.7556 70.411H55.8091C54.824 70.411 54.0265 71.2007 54.0265 72.1759V87.481C54.0265 88.4562 53.229 89.2459 52.244 89.2459H46.2975C45.3124 89.2459 44.5149 88.4562 44.5149 87.481V72.1759C44.5149 71.2007 45.3124 70.411 46.2975 70.411H52.244C53.229 70.411 54.0265 69.6214 54.0265 68.6461V60.9604C54.0265 50.576 62.5279 42.1588 73.0161 42.1588C83.5043 42.1588 92.0057 50.576 92.0057 60.9604V68.6461Z" fill="#F6F7F7"/>
<path d="M67.3016 108.233C44.232 108.233 25.4634 89.6504 25.4634 66.8092C25.4634 43.968 44.232 25.3853 67.3016 25.3853C90.3712 25.3853 109.14 43.968 109.14 66.8092C109.14 89.6504 90.3712 108.233 67.3016 108.233ZM67.3016 27.0477C45.1582 27.0477 27.1425 44.8851 27.1425 66.8092C27.1425 88.7333 45.1582 106.571 67.3016 106.571C89.4449 106.571 107.461 88.7333 107.461 66.8092C107.461 44.8851 89.4449 27.0477 67.3016 27.0477Z" fill="#F6F7F7"/>
<path d="M17.785 94.7571L25.3574 89.9999L28.332 94.6407L26.9217 95.5273L24.9992 92.5295L23.3929 93.538L25.2091 96.3724L23.7987 97.259L21.9826 94.4246L20.2504 95.5135L22.2176 98.5834L20.8073 99.47L17.7878 94.7571H17.785Z" fill="#F6F7F7"/>
<path d="M22.3548 101.664L27.848 100.727L29.1464 95.8622L30.638 97.4774L29.7481 100.622L29.9384 100.83L33.1649 100.215L34.6144 101.786L29.5242 102.653L28.1866 107.984L26.6867 106.36L27.6493 102.753L27.4506 102.537L23.8016 103.235L22.352 101.664H22.3548Z" fill="#F6F7F7"/>
<path d="M30.5625 109.97L36.008 102.83L38.6245 104.787C40.4378 106.141 40.8156 107.904 39.6403 109.447L39.5228 109.602C38.3615 111.126 36.5369 111.256 34.7264 109.901L33.7162 109.148L32.1687 111.176L30.5625 109.973V109.97ZM36.5649 105.41L34.7656 107.768L35.8541 108.58C36.6097 109.145 37.4156 109.015 37.9557 108.308C38.5098 107.579 38.409 106.787 37.6535 106.222L36.5649 105.41Z" fill="#F6F7F7"/>
<path d="M38.8202 115.681L42.9758 107.815L44.7611 108.741L41.4255 115.055L44.5372 116.668L43.7173 118.219L38.8202 115.684V115.681Z" fill="#F6F7F7"/>
<path d="M47.4 115.216L47.4784 114.961C48.1248 112.855 50.3691 111.077 53.3885 111.988C56.3967 112.894 57.281 115.615 56.6318 117.721L56.5534 117.975C55.9658 119.884 53.7299 121.893 50.6293 120.957C47.5259 120.02 46.8124 117.125 47.4 115.216ZM54.6393 117.272C55.1263 115.69 54.463 114.257 52.84 113.767C51.2198 113.279 49.8737 114.105 49.3868 115.687C48.9279 117.178 49.5547 118.688 51.1778 119.175C52.798 119.663 54.1832 118.76 54.6393 117.269V117.272Z" fill="#F6F7F7"/>
<path d="M58.9068 122.668L59.6792 113.75L63.1911 114.049C65.4298 114.24 66.7394 115.351 66.5687 117.326L66.5519 117.52C66.44 118.817 65.7544 119.626 64.6519 119.97L66.6527 123.325L64.3272 123.128L62.6286 120.128L61.1595 120.003L60.9133 122.837L58.9068 122.666V122.668ZM61.5401 115.606L61.2938 118.44L62.9589 118.582C63.8263 118.656 64.4504 118.147 64.5259 117.288C64.5987 116.44 64.0726 115.822 63.2051 115.747L61.5401 115.606Z" fill="#F6F7F7"/>
<path d="M69.0452 123.331L70.9956 114.182L74.2305 113.825L78.2741 122.311L76.1978 122.541L75.2323 120.433L71.5077 120.843L71.046 123.109L69.0452 123.328V123.331ZM74.4991 118.851L73.0104 115.601L72.5599 115.651L71.8519 119.142L74.5019 118.851H74.4991Z" fill="#F6F7F7"/>
<path d="M82.2031 121.23L80.1966 114.373L77.7789 115.066L77.2892 113.395L84.0724 111.45L84.5621 113.121L82.1303 113.816L84.1367 120.673L82.2031 121.227V121.23Z" fill="#F6F7F7"/>
<path d="M89.3334 118.804L85.7151 110.68L87.5592 109.874L91.1775 117.998L89.3334 118.804Z" fill="#F6F7F7"/>
<path d="M91.9439 113.024L91.7956 112.8C90.5811 110.954 90.6454 108.112 93.2927 106.408C95.9259 104.709 98.6012 105.784 99.8128 107.63L99.9612 107.854C101.061 109.525 101.178 112.512 98.4612 114.263C95.744 116.014 93.0436 114.695 91.9439 113.024ZM98.1842 108.854C97.2719 107.469 95.7384 107.051 94.3169 107.968C92.8981 108.885 92.6714 110.436 93.5837 111.822C94.4428 113.127 96.0127 113.623 97.4342 112.705C98.8558 111.788 99.0433 110.159 98.1842 108.854Z" fill="#F6F7F7"/>
<path d="M105.219 109.07L98.7691 102.903L101.064 100.551L108.684 103.188L108.804 103.066L103.529 98.0238L104.844 96.6772L111.295 102.842L108.983 105.214L101.363 102.576L101.243 102.698L106.518 107.74L105.222 109.07H105.219Z" fill="#F6F7F7"/>
<path d="M111.071 98.6364L112.117 97.0045C112.697 97.3702 113.489 97.2483 114.169 96.1899C114.767 95.2562 114.686 94.4998 114.104 94.1341C113.617 93.8266 113.086 94.0427 112.417 94.9044L112.003 95.4363C110.917 96.8577 109.453 97.276 108.107 96.4282C106.655 95.5167 106.451 93.8598 107.525 92.1864C108.659 90.4215 110.321 89.9837 111.804 90.9146L110.752 92.5576C110.203 92.2113 109.459 92.3055 108.958 93.0868C108.477 93.8349 108.664 94.4721 109.162 94.7852C109.599 95.0595 110.128 95.0041 110.62 94.3475L111.04 93.8044C112.232 92.2639 113.757 91.6101 115.156 92.4884C116.617 93.4082 116.816 95.187 115.596 97.0876C114.286 99.1296 112.54 99.559 111.068 98.6336L111.071 98.6364Z" fill="#F6F7F7"/>
<path d="M116.75 75.0252L116.213 77.6313C116.124 78.0616 116.404 78.4816 116.839 78.5694L119.471 79.1015C119.906 79.1894 120.33 78.9118 120.419 78.4815L120.956 75.8755C121.045 75.4452 120.764 75.0252 120.33 74.9373L117.698 74.4052C117.263 74.3173 116.839 74.5949 116.75 75.0252Z" fill="#F6F7F7"/>
<path d="M16.9088 74.4046L14.2766 74.9367C13.8421 75.0246 13.5617 75.4446 13.6504 75.8749L14.1878 78.481C14.2766 78.9112 14.7008 79.1889 15.1354 79.101L17.7675 78.5689C18.2021 78.481 18.4825 78.061 18.3937 77.6307L17.8563 75.0247C17.7676 74.5944 17.3433 74.3168 16.9088 74.4046Z" fill="#F6F7F7"/>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -47,6 +47,7 @@ export const FilterTypeMapping: Partial<
keywords: "checkbox",
builtWith: "checkbox",
themes: "button",
fundingSource: "checkbox",
}
interface ProjectStateProps {
sortBy: ProjectSortBy

View File

@@ -4,4 +4,5 @@ export interface NavItem {
disabled?: boolean
external?: boolean
onlyFooter?: boolean
onlyHeader?: boolean
}