From e5b815ed9ea5f0928c0457e7ccc8796696cdbfda Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:03:20 +0530 Subject: [PATCH 01/27] revamp(1/7): design tokens & POH NEW palette Tailwind palette aligned to the design-system swatches, globals.css utility layer (btn-primary, status pills, cards, toasts) with a btn-main compatibility alias until all pages migrate, dark theme enabled globally, AppKit dark theme, eslint/next config. --- .eslintrc.js | 10 +- next.config.js | 10 +- src/app/globals.css | 393 ++++++++++++++++++++++++++-- src/app/layout.tsx | 2 +- src/config/chains.ts | 3 + src/context/AppKitProvider.tsx | 7 + src/contracts/apis/APIArbitrator.ts | 2 +- src/contracts/apis/APIPoH.ts | 2 +- src/contracts/config.ts | 2 +- tailwind.config.cjs | 87 +++--- 10 files changed, 449 insertions(+), 69 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index eaed1fbe..1139f788 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,11 +10,11 @@ module.exports = { rules: { "react/no-unescaped-entities": 0, "react/display-name": "off", - "react-hooks/exhaustive-deps": "warn", - "no-var": "warn", - "prefer-const": "warn", - eqeqeq: ["warn", "always", { null: "ignore" }], - "object-shorthand": ["warn", "always"], + "react-hooks/exhaustive-deps": "error", + "no-var": "error", + "prefer-const": "error", + eqeqeq: ["error", "always", { null: "ignore" }], + "object-shorthand": ["error", "always"], "no-restricted-syntax": [ "warn", { diff --git a/next.config.js b/next.config.js index 6c703384..f15ce152 100644 --- a/next.config.js +++ b/next.config.js @@ -1,3 +1,11 @@ +const ipfsGatewayHostname = process.env.REACT_APP_IPFS_GATEWAY; + +if (!ipfsGatewayHostname) { + throw new Error( + "Missing required environment variable: REACT_APP_IPFS_GATEWAY", + ); +} + /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { @@ -67,7 +75,7 @@ const nextConfig = { remotePatterns: [ { protocol: "https", - hostname: process.env.REACT_APP_IPFS_GATEWAY, + hostname: ipfsGatewayHostname, port: "", pathname: "/ipfs/**", }, diff --git a/src/app/globals.css b/src/app/globals.css index 100f5217..16dc47f1 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,6 +3,12 @@ @layer base { html { @apply text-black; + background: #1e2129; + overscroll-behavior: none; + } + + body { + overflow-x: hidden; } button { @@ -28,31 +34,40 @@ } .divider { - @apply h-0.5 w-full rounded; + @apply h-px w-full rounded-full bg-[#3A3E48]; } .checkbox { - @apply border-orange bg-lightOrange h-6 w-6 rounded-sm border; + @apply border-orange h-6 w-6 rounded-md border bg-peach/15; } .radio { - @apply border-orange bg-lightOrange h-6 w-6 rounded-full border; + @apply border-orange h-6 w-6 rounded-full border bg-peach/15; } .bordered { - @apply gradient rounded p-px; + @apply rounded bg-peach p-px; } + .btn-primary, .btn-main { - @apply centered gradient w-full rounded-sm p-2 font-medium uppercase text-white disabled:opacity-40 md:w-auto; + @apply centered min-h-[44px] w-full rounded-btn px-5 py-2.5 font-medium normal-case text-white transition duration-200 ease-premium disabled:opacity-40 md:w-auto; + } + + .btn-secondary { + @apply centered min-h-[44px] w-full rounded-btn border px-5 py-2.5 font-semibold normal-case transition duration-200 ease-premium disabled:opacity-40 md:w-auto; + background: #2f333d; + border-color: rgba(255, 138, 102, 0.32); + color: #ffb08a; } - .btn-sec { - @apply centered border-theme text-orange w-full rounded-sm border-2 p-2 font-semibold uppercase disabled:opacity-40 md:w-auto; + .btn-secondary:hover { + background: rgba(255, 138, 102, 0.08); + border-color: rgba(255, 176, 138, 0.48); } .backdrop { - @apply fixed left-0 top-0 z-10 flex h-screen w-full items-center justify-center bg-slate-800/30 backdrop-blur; + @apply fixed left-0 top-0 z-10 flex h-screen w-full items-center justify-center bg-black/50 backdrop-blur-sm; } .modal-backdrop { @@ -94,8 +109,301 @@ @apply mx-auto mb-16 mt-8 w-11/12 sm:mt-12 sm:w-5/6 lg:w-4/5; } + .request-grid { + @apply grid grid-cols-1 gap-4; + } + + @media (min-width: 640px) { + .request-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } + + @media (min-width: 1024px) { + .request-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + } + + @media (min-width: 1200px) { + .request-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + } + + @media (min-width: 1280px) { + .request-grid { + gap: 1.25rem; + } + } + + .request-card-media { + inset: -16px 0; + height: calc(100% + 32px); + transform: translate3d( + var(--request-card-hover-x, 0px), + var(--request-card-hover-y, 0px), + 0 + ) + scale(1.02); + transform-origin: center; + will-change: transform; + } + + .request-card-parallax:hover .request-card-media { + transform: translate3d( + var(--request-card-hover-x, 0px), + var(--request-card-hover-y, 0px), + 0 + ) + scale(1.03); + } + + .request-card-shell { + border-color: rgba(255, 255, 255, 0.08); + box-shadow: + 0 20px 50px rgba(0, 0, 0, 0.28), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + } + + .request-card-shell:hover { + border-color: rgba(255, 138, 102, 0.32); + box-shadow: + 0 28px 70px rgba(0, 0, 0, 0.34), + 0 0 0 1px rgba(255, 138, 102, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.06); + } + + .request-card-overlay { + background: linear-gradient( + 180deg, + rgba(0, 0, 0, 0.06) 0%, + rgba(0, 0, 0, 0.18) 45%, + rgba(0, 0, 0, 0.76) 100% + ); + } + + .flat-control { + background: #272a33; + border: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.04), + 0 12px 30px rgba(0, 0, 0, 0.22); + } + + .flat-control:focus-within, + .flat-control:focus { + border-color: rgba(255, 138, 102, 0.45); + box-shadow: + 0 0 0 3px rgba(255, 138, 102, 0.1), + 0 12px 30px rgba(0, 0, 0, 0.24); + } + + .status-pill { + @apply inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs font-semibold; + background: rgba(47, 51, 61, 0.82); + border-color: rgba(255, 255, 255, 0.08); + color: #b8b1c2; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04); + } + + .status-pill::before { + content: ""; + width: 7px; + height: 7px; + border-radius: 999px; + background: currentColor; + box-shadow: 0 0 12px currentColor; + } + + .status-pill-success { + border-color: rgba(116, 226, 173, 0.22); + background: rgba(116, 226, 173, 0.08); + color: #74e2ad; + } + + .status-pill-warning { + border-color: rgba(255, 138, 102, 0.28); + background: rgba(255, 138, 102, 0.08); + color: #ffb08a; + } + + .status-pill-danger { + border-color: rgba(255, 127, 143, 0.22); + background: rgba(255, 127, 143, 0.08); + color: #ff7f8f; + } + + .status-pill-muted { + border-color: rgba(255, 255, 255, 0.08); + background: rgba(39, 42, 51, 0.72); + color: #8a8494; + } + .paper { - @apply bg-whiteBackground border-stroke text-primaryText rounded border shadow; + @apply text-primaryText rounded-card border; + background: linear-gradient(180deg, #2f333d 0%, #292d35 100%); + border-color: rgba(255, 255, 255, 0.08); + box-shadow: + 0 20px 50px rgba(0, 0, 0, 0.28), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + transition: + border-color 180ms ease-out, + box-shadow 180ms ease-out, + transform 180ms ease-out; + } + + .interactive-surface:hover { + transform: translateY(-3px); + border-color: rgba(255, 138, 102, 0.32); + box-shadow: + 0 28px 70px rgba(0, 0, 0, 0.34), + 0 0 0 1px rgba(255, 138, 102, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.06); + } + + .reward-surface { + @apply rounded-card border; + background: linear-gradient( + 180deg, + theme("colors.dark.grey") 0%, + theme("colors.dark.whiteBackground") 100% + ); + border-color: rgba(255, 255, 255, 0.08); + box-shadow: + 0 20px 50px rgba(0, 0, 0, 0.28), + inset 0 1px 0 rgba(255, 255, 255, 0.04); + transition: + border-color 180ms ease-out, + box-shadow 180ms ease-out, + transform 180ms ease-out; + } + + .reward-surface:hover { + transform: translateY(-3px); + border-color: rgba(255, 138, 102, 0.32); + box-shadow: + 0 28px 70px rgba(0, 0, 0, 0.34), + 0 0 0 1px rgba(255, 138, 102, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.06); + } + + .pill-tag { + @apply inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-semibold; + background: rgba(255, 138, 102, 0.12); + color: theme("colors.peach"); + border: 1px solid rgba(255, 138, 102, 0.22); + } + + .poh-toast-container { + --toastify-toast-width: min(480px, calc(100vw - 32px)); + width: var(--toastify-toast-width); + padding: 0; + } + + .poh-toast { + --toast-accent: #7bc7ff; + display: grid; + grid-template-columns: 8px 34px minmax(0, 1fr) 24px; + column-gap: 16px; + align-items: center; + position: relative; + min-height: 76px; + margin-bottom: 12px; + padding: 12px 14px 12px 18px; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 18px; + background: rgba(32, 35, 43, 0.9); + box-shadow: + 0 18px 48px rgba(0, 0, 0, 0.32), + inset 0 1px 0 rgba(255, 255, 255, 0.05); + color: #f7f3ef; + backdrop-filter: blur(18px); + } + + .poh-toast::before { + content: ""; + position: absolute; + left: 18px; + top: 50%; + width: 8px; + height: 38px; + border-radius: 999px; + background: var(--toast-accent); + box-shadow: 0 0 18px + color-mix(in srgb, var(--toast-accent) 34%, transparent); + transform: translateY(-50%); + } + + .poh-toast.Toastify__toast--error { + --toast-accent: #ff6b6b; + } + + .poh-toast.Toastify__toast--warning { + --toast-accent: #ffb86b; + } + + .poh-toast.Toastify__toast--info { + --toast-accent: #7bc7ff; + } + + .poh-toast.Toastify__toast--success { + --toast-accent: #70d79f; + } + + .poh-toast-body { + align-items: center; + gap: 14px; + grid-column: 2 / 4; + margin: 0; + padding: 0; + color: #f7f3ef; + font-size: 14px; + line-height: 1.55; + } + + .poh-toast .Toastify__toast-icon { + width: 34px; + height: 34px; + margin-inline-end: 0; + padding: 7px; + border: 1px solid color-mix(in srgb, var(--toast-accent) 36%, transparent); + border-radius: 999px; + background: color-mix(in srgb, var(--toast-accent) 14%, transparent); + color: var(--toast-accent); + flex-shrink: 0; + } + + .poh-toast .Toastify__toast-icon svg { + fill: currentColor; + } + + .poh-toast .Toastify__close-button { + position: static; + align-self: center; + justify-self: center; + display: grid; + width: 24px; + height: 24px; + place-items: center; + border-radius: 999px; + color: #8a8494; + opacity: 1; + transform: none; + transition: + background 180ms ease-out, + color 180ms ease-out; + } + + .poh-toast .Toastify__close-button svg { + width: 14px; + height: 14px; + } + + .poh-toast .Toastify__close-button:hover { + background: rgba(255, 255, 255, 0.08); + color: #f7f3ef; } /* Custom classes for success states to ensure dark mode compatibility */ @@ -167,7 +475,7 @@ } .dark .header-background { - background: theme("colors.dark.whiteBackground"); + background: #20232b; } .border-theme { @@ -194,6 +502,10 @@ border-color: theme("colors.dark.orange"); } + .border-peach { + border-color: theme("colors.peach"); + } + .text-primaryText { color: theme("colors.light.primaryText"); } @@ -210,6 +522,14 @@ color: theme("colors.dark.secondaryText"); } + .text-mutedText { + color: theme("colors.light.secondaryText"); + } + + .dark .text-mutedText { + color: theme("colors.dark.mutedText"); + } + .text-orange { color: theme("colors.light.orange"); } @@ -218,6 +538,10 @@ color: theme("colors.dark.orange"); } + .text-peach { + color: theme("colors.peach"); + } + .text-purple { color: theme("colors.light.purple"); } @@ -338,6 +662,16 @@ fill: theme("colors.dark.purple"); } + .fill-status-registered { + fill: theme("colors.light.status.registered"); + color: theme("colors.light.status.registered"); + } + + .dark .fill-status-registered { + fill: theme("colors.dark.status.registered"); + color: theme("colors.dark.status.registered"); + } + .bg-whiteBackground { background-color: theme("colors.light.whiteBackground"); } @@ -369,7 +703,7 @@ } .dark .bg-primaryBackground { - background-color: theme("colors.dark.primaryBackground"); + background: linear-gradient(180deg, #20232b 0%, #1e2129 100%); } .bg-orange { @@ -380,6 +714,10 @@ background-color: theme("colors.dark.orange"); } + .bg-peach { + background-color: theme("colors.peach"); + } + .bg-lightOrange { background-color: theme("colors.light.lightOrange"); } @@ -497,12 +835,20 @@ background-color: theme("colors.dark.status.rejected"); } + .btn-primary, .btn-main { - background-color: #ff9966; + background: linear-gradient(90deg, #ff7a5f 0%, #ff9a6a 100%); + box-shadow: 0 10px 24px rgba(255, 122, 95, 0.1); + } + + .dark .btn-primary, + .dark .btn-main { + background: linear-gradient(90deg, #ff7a5f 0%, #ff9a6a 100%); + box-shadow: 0 10px 24px rgba(255, 122, 95, 0.1); } .divider { - @apply h-0.5 w-full rounded; + @apply h-px w-full rounded-full bg-[#3A3E48]; } .slider-thumb::-webkit-slider-thumb { @@ -522,16 +868,11 @@ } .gradient { - background: linear-gradient( - 150deg, - #ff9966 33%, - #ff9571, - #ff917c, - #ff8e87, - #ff8d93, - #ff8c9e, - #ff8ca9 95% - ); + background: theme("colors.light.orange"); + } + + .dark .gradient { + background: theme("colors.dark.orange"); } .scrollbar::-webkit-scrollbar { @@ -556,7 +897,7 @@ } .scrollbar::-webkit-scrollbar-thumb { - @apply rounded-full bg-[#ff8ca9]; + @apply rounded-full bg-[#FF9A6A]; } .dark .scrollbar::-webkit-scrollbar { @@ -564,11 +905,11 @@ } .dark .scrollbar::-webkit-scrollbar-track { - @apply rounded-full bg-slate-700; + @apply rounded-full bg-[#20232B]; } .dark .scrollbar::-webkit-scrollbar-thumb { - @apply rounded-full bg-slate-500; + @apply rounded-full bg-[#3A3E48]; } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6e80add2..b784099f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -38,7 +38,7 @@ export default async function RootLayout({ children }: RootLayoutProps) { }); return ( - + `https://${getExplorerUrl(chain.id)}/address/${address}`; +export const explorerTxLink = (txHash: string, chainId: number) => + `https://${getExplorerUrl(chainId)}/tx/${txHash}`; + export const supportedChains = configSetSelection.chainSet === ChainSet.MAINNETS ? supportedChainsMain diff --git a/src/context/AppKitProvider.tsx b/src/context/AppKitProvider.tsx index 68fbbfc2..86536303 100644 --- a/src/context/AppKitProvider.tsx +++ b/src/context/AppKitProvider.tsx @@ -40,6 +40,13 @@ createAppKit({ defaultNetwork: gnosis, projectId, metadata, + themeMode: "dark", + themeVariables: { + "--w3m-accent": "#FF8A66", + "--w3m-color-mix": "#20232B", + "--w3m-color-mix-strength": 12, + "--w3m-border-radius-master": "3px", + }, features: { analytics: true, }, diff --git a/src/contracts/apis/APIArbitrator.ts b/src/contracts/apis/APIArbitrator.ts index 0d9cce2d..73ba862d 100644 --- a/src/contracts/apis/APIArbitrator.ts +++ b/src/contracts/apis/APIArbitrator.ts @@ -56,7 +56,7 @@ export class APIArbitrator { address: this.address, abi: KlerosLiquid.abi, functionName: func, - args: args, + args, }) .catch(() => { throw new Error({ diff --git a/src/contracts/apis/APIPoH.ts b/src/contracts/apis/APIPoH.ts index a5ec2da0..ad58904f 100644 --- a/src/contracts/apis/APIPoH.ts +++ b/src/contracts/apis/APIPoH.ts @@ -48,7 +48,7 @@ export class APIPoH { address: this.address, abi: getContractInfo("ProofOfHumanity", this.chainId).abi, functionName: func, - args: args, + args, }) .catch(() => { throw new Error({ diff --git a/src/contracts/config.ts b/src/contracts/config.ts index 4fed8ea3..59ee2883 100644 --- a/src/contracts/config.ts +++ b/src/contracts/config.ts @@ -9,7 +9,7 @@ export const configSets = { }; export const configSetSelection = - process.env.DEPLOYED_APP == + process.env.DEPLOYED_APP === "https://testnets--proof-of-humanity-v2.netlify.app" ? configSets.testnet : configSets.main; diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 59a14372..412401f2 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -36,37 +36,58 @@ module.exports = { purple: "#BE75FF", }, dark: { - whiteBackground: "#2D0050", - primaryBackground: "#1B003F", - stroke: "#42498F", - theme: "#1b003f", - primaryText: "#DAF0FF", - secondaryText: "#BECCE5", - orange: "#FFBE66", - lightOrange: "#480c54", - grey: "#666666", + whiteBackground: "#292D35", + primaryBackground: "#1E2129", + stroke: "#3A3E48", + theme: "#FF8A66", + primaryText: "#F7F3EF", + secondaryText: "#B8B1C2", + mutedText: "#8A8494", + orange: "#FF8A66", + lightOrange: "#2F333D", + grey: "#2F333D", status: { vouching: "#D09BFF", registered: "#79FFDC", - removed: "#FF8DBD", - revocation: "#FF9966", + removed: "#FF8A66", + revocation: "#FF8A66", claim: "#8CEAFF", - challenged: "#FFBE66", - withdrawn: "#BECCE5", - expired: "#DAF0FF", - transferred: "#8BC34A", - transferring: "#795548", - rejected: "#F25F5F", + challenged: "#FFE16B", + withdrawn: "#F7F3EF", + expired: "#F7F3EF", + transferred: "#9BD157", + transferring: "#A6816E", + rejected: "#F60C6E", }, purple: "#D09BFF", }, + peach: "#FFB08A", + pink: "#FF9A6A", + }, + borderRadius: { + card: "28px", + input: "20px", + btn: "16px", + }, + boxShadow: { + soft: "0 20px 50px rgba(0,0,0,0.28)", + "soft-inset": + "0 20px 50px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.045)", + inset: "inset 0 2px 6px rgba(0,0,0,0.35)", + }, + transitionTimingFunction: { + premium: "cubic-bezier(0.22, 0.61, 0.36, 1)", }, animation: { flip: "flip 5s linear infinite", - slideInFromRight: "slideInFromRight 0.3s ease-out forwards", - slideInFromLeft: "slideInFromLeft 0.3s ease-out forwards", - slideOutLeft: "slideOutLeft 0.25s ease-in forwards", - slideOutRight: "slideOutRight 0.25s ease-in forwards", + wizardInRight: + "wizardInRight 0.35s cubic-bezier(0.22, 0.61, 0.36, 1) forwards", + wizardInLeft: + "wizardInLeft 0.35s cubic-bezier(0.22, 0.61, 0.36, 1) forwards", + wizardOutLeft: + "wizardOutLeft 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) forwards", + wizardOutRight: + "wizardOutRight 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) forwards", fadeOut: "fadeOut 0.4s ease-out forwards", fadeIn: "fadeIn 0.3s ease-out forwards", }, @@ -75,21 +96,21 @@ module.exports = { "0%, 100%": { transform: "rotateY(0deg)" }, "50%": { transform: "rotateY(360deg)" }, }, - slideInFromRight: { - "0%": { opacity: "0", transform: "translateX(20px)" }, - "100%": { opacity: "1", transform: "translateX(0)" }, + wizardInRight: { + "0%": { opacity: "0", transform: "translateX(12px) scale(0.995)" }, + "100%": { opacity: "1", transform: "translateX(0) scale(1)" }, }, - slideInFromLeft: { - "0%": { opacity: "0", transform: "translateX(-20px)" }, - "100%": { opacity: "1", transform: "translateX(0)" }, + wizardInLeft: { + "0%": { opacity: "0", transform: "translateX(-12px) scale(0.995)" }, + "100%": { opacity: "1", transform: "translateX(0) scale(1)" }, }, - slideOutLeft: { - "0%": { opacity: "1", transform: "translateX(0)" }, - "100%": { opacity: "0", transform: "translateX(-20px)" }, + wizardOutLeft: { + "0%": { opacity: "1", transform: "translateX(0) scale(1)" }, + "100%": { opacity: "0", transform: "translateX(-12px) scale(0.995)" }, }, - slideOutRight: { - "0%": { opacity: "1", transform: "translateX(0)" }, - "100%": { opacity: "0", transform: "translateX(20px)" }, + wizardOutRight: { + "0%": { opacity: "1", transform: "translateX(0) scale(1)" }, + "100%": { opacity: "0", transform: "translateX(12px) scale(0.995)" }, }, fadeOut: { "0%": { opacity: "1" }, From e8ae9e50807a0982d2509ca62e58c137f77cec66 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:03:40 +0530 Subject: [PATCH 02/27] revamp(1/7): design-system icons & logos Icon set and social/brand logos from the POH NEW Figma file, normalized to currentColor; Gift replaced with the design-system filled variant. --- public/logo/gnosis-app.svg | 23 +++++++++++++++++++++++ public/logo/human-connector.svg | 4 ++++ public/logo/notifications.svg | 10 +++++++--- public/logo/social-github.svg | 12 ++++++++++++ public/logo/social-help.svg | 12 ++++++++++++ public/logo/social-snapshot.svg | 5 +++++ public/logo/social-telegram.svg | 12 ++++++++++++ public/logo/social-x.svg | 12 ++++++++++++ src/icons/Challenge.svg | 10 ++++++++++ src/icons/CheckCircle.svg | 7 ------- src/icons/CheckCircleOutline.svg | 6 ++++++ src/icons/ChevronDown.svg | 6 ++++++ src/icons/CloseCircleOutline.svg | 10 ++++++++++ src/icons/Copy.svg | 17 +++++++++++++++++ src/icons/Download.svg | 10 ++++++++++ src/icons/ExternalLink.svg | 7 ------- src/icons/Eye.svg | 6 ++++++ src/icons/Gift.svg | 10 ++++++++++ src/icons/GnosisToken.svg | 7 +++++++ src/icons/Loading.svg | 10 ++++++++++ src/icons/NeedsVouch.svg | 6 ++++++ src/icons/Referral.svg | 5 +++++ src/icons/Stamp.svg | 3 +++ src/icons/TelegramLogo.svg | 6 ++++++ src/icons/Vouch.svg | 10 ++++++++++ src/icons/WhatsAppLogo.svg | 6 ++++++ src/icons/XLogo.svg | 6 ++++++ 27 files changed, 221 insertions(+), 17 deletions(-) create mode 100644 public/logo/gnosis-app.svg create mode 100644 public/logo/human-connector.svg create mode 100644 public/logo/social-github.svg create mode 100644 public/logo/social-help.svg create mode 100644 public/logo/social-snapshot.svg create mode 100644 public/logo/social-telegram.svg create mode 100644 public/logo/social-x.svg create mode 100644 src/icons/Challenge.svg create mode 100644 src/icons/CheckCircleOutline.svg create mode 100644 src/icons/ChevronDown.svg create mode 100644 src/icons/CloseCircleOutline.svg create mode 100644 src/icons/Copy.svg create mode 100644 src/icons/Download.svg create mode 100644 src/icons/Eye.svg create mode 100644 src/icons/Gift.svg create mode 100644 src/icons/GnosisToken.svg create mode 100644 src/icons/Loading.svg create mode 100644 src/icons/NeedsVouch.svg create mode 100644 src/icons/Referral.svg create mode 100644 src/icons/Stamp.svg create mode 100644 src/icons/TelegramLogo.svg create mode 100644 src/icons/Vouch.svg create mode 100644 src/icons/WhatsAppLogo.svg create mode 100644 src/icons/XLogo.svg diff --git a/public/logo/gnosis-app.svg b/public/logo/gnosis-app.svg new file mode 100644 index 00000000..fe018d04 --- /dev/null +++ b/public/logo/gnosis-app.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/logo/human-connector.svg b/public/logo/human-connector.svg new file mode 100644 index 00000000..63d19ea4 --- /dev/null +++ b/public/logo/human-connector.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/logo/notifications.svg b/public/logo/notifications.svg index 7940988b..f6475698 100644 --- a/public/logo/notifications.svg +++ b/public/logo/notifications.svg @@ -1,4 +1,8 @@ - - - + + + + + + + diff --git a/public/logo/social-github.svg b/public/logo/social-github.svg new file mode 100644 index 00000000..0823e3f1 --- /dev/null +++ b/public/logo/social-github.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/logo/social-help.svg b/public/logo/social-help.svg new file mode 100644 index 00000000..bc02c56e --- /dev/null +++ b/public/logo/social-help.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/logo/social-snapshot.svg b/public/logo/social-snapshot.svg new file mode 100644 index 00000000..e392dd58 --- /dev/null +++ b/public/logo/social-snapshot.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/logo/social-telegram.svg b/public/logo/social-telegram.svg new file mode 100644 index 00000000..95c0a08e --- /dev/null +++ b/public/logo/social-telegram.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/logo/social-x.svg b/public/logo/social-x.svg new file mode 100644 index 00000000..19bce76f --- /dev/null +++ b/public/logo/social-x.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/icons/Challenge.svg b/src/icons/Challenge.svg new file mode 100644 index 00000000..b99ecff9 --- /dev/null +++ b/src/icons/Challenge.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/CheckCircle.svg b/src/icons/CheckCircle.svg index 7ab5f78e..9f999fe8 100644 --- a/src/icons/CheckCircle.svg +++ b/src/icons/CheckCircle.svg @@ -1,10 +1,3 @@ - - - - - - - diff --git a/src/icons/CheckCircleOutline.svg b/src/icons/CheckCircleOutline.svg new file mode 100644 index 00000000..c53a49b2 --- /dev/null +++ b/src/icons/CheckCircleOutline.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/ChevronDown.svg b/src/icons/ChevronDown.svg new file mode 100644 index 00000000..387cec13 --- /dev/null +++ b/src/icons/ChevronDown.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/CloseCircleOutline.svg b/src/icons/CloseCircleOutline.svg new file mode 100644 index 00000000..1f4cbf44 --- /dev/null +++ b/src/icons/CloseCircleOutline.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/Copy.svg b/src/icons/Copy.svg new file mode 100644 index 00000000..4e4b9325 --- /dev/null +++ b/src/icons/Copy.svg @@ -0,0 +1,17 @@ + + + + diff --git a/src/icons/Download.svg b/src/icons/Download.svg new file mode 100644 index 00000000..18b569e9 --- /dev/null +++ b/src/icons/Download.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/ExternalLink.svg b/src/icons/ExternalLink.svg index df9c31b6..c42b8ffd 100644 --- a/src/icons/ExternalLink.svg +++ b/src/icons/ExternalLink.svg @@ -1,10 +1,3 @@ - - - - - - - diff --git a/src/icons/Eye.svg b/src/icons/Eye.svg new file mode 100644 index 00000000..32d8cb57 --- /dev/null +++ b/src/icons/Eye.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/Gift.svg b/src/icons/Gift.svg new file mode 100644 index 00000000..ae4d8598 --- /dev/null +++ b/src/icons/Gift.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/GnosisToken.svg b/src/icons/GnosisToken.svg new file mode 100644 index 00000000..125d1182 --- /dev/null +++ b/src/icons/GnosisToken.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/icons/Loading.svg b/src/icons/Loading.svg new file mode 100644 index 00000000..625d5fec --- /dev/null +++ b/src/icons/Loading.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/NeedsVouch.svg b/src/icons/NeedsVouch.svg new file mode 100644 index 00000000..07b3781c --- /dev/null +++ b/src/icons/NeedsVouch.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/Referral.svg b/src/icons/Referral.svg new file mode 100644 index 00000000..c95936c2 --- /dev/null +++ b/src/icons/Referral.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/icons/Stamp.svg b/src/icons/Stamp.svg new file mode 100644 index 00000000..579c2929 --- /dev/null +++ b/src/icons/Stamp.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/icons/TelegramLogo.svg b/src/icons/TelegramLogo.svg new file mode 100644 index 00000000..e1590757 --- /dev/null +++ b/src/icons/TelegramLogo.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/Vouch.svg b/src/icons/Vouch.svg new file mode 100644 index 00000000..16dd5d9b --- /dev/null +++ b/src/icons/Vouch.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/icons/WhatsAppLogo.svg b/src/icons/WhatsAppLogo.svg new file mode 100644 index 00000000..2985e365 --- /dev/null +++ b/src/icons/WhatsAppLogo.svg @@ -0,0 +1,6 @@ + + + diff --git a/src/icons/XLogo.svg b/src/icons/XLogo.svg new file mode 100644 index 00000000..1ae100d4 --- /dev/null +++ b/src/icons/XLogo.svg @@ -0,0 +1,6 @@ + + + From c3f5b53a02d8297d96ae6bcc586457881d2c90f4 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:03:40 +0530 Subject: [PATCH 03/27] fix: tolerate partial subgraph outages in getMyData Use settleChainQueries so one dead chain does not blank header/me identity, while keeping lowercased account ids for subgraph matching. --- src/data/user.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/data/user.ts b/src/data/user.ts index 84c56672..85ebf0a0 100644 --- a/src/data/user.ts +++ b/src/data/user.ts @@ -1,7 +1,6 @@ import { supportedChains, legacyChain } from "config/chains"; import { sdk } from "config/subgraph"; import { MeQuery } from "generated/graphql"; - import { settleChainQueries } from "./chainQuery"; const isTransferStatus = (statusId?: string | null) => @@ -44,9 +43,9 @@ const sanitize = (res: MeQuery[]) => { export const getMyData = async (account: string) => { const id = account.toLowerCase(); - const res = await settleChainQueries( + const res = await settleChainQueries( (chain) => sdk[chain.id].Me({ id }), - () => ({ claimer: null }), + (): MeQuery => ({ claimer: null }), ); sanitize(res); const homeChain = supportedChains.find((_, i) => { From 506fa801bbe4885d2b4876552f61c7491145acbf Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:03:40 +0530 Subject: [PATCH 04/27] chore: upgrade graphql-request and restore codegen plugin 6.x --- package.json | 2 +- src/generated/graphql.ts | 295 +++++++++++++++++++++++++++++++-------- yarn.lock | 40 ++---- 3 files changed, 249 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index 74652fdf..7c7b820f 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "classnames": "^2.3.2", "dotenv": "^16.0.3", "graphql": "^16.4.0", - "graphql-request": "^4.2.0", + "graphql-request": "^7.1.2", "graphql-tag": "^2.12.6", "next": "15.5.16", "pino-pretty": "^11.0.0", diff --git a/src/generated/graphql.ts b/src/generated/graphql.ts index 4689186f..f8969639 100644 --- a/src/generated/graphql.ts +++ b/src/generated/graphql.ts @@ -326,6 +326,7 @@ export enum Challenge_OrderBy { ReasonCount = 'reason__count', ReasonId = 'reason__id', Request = 'request', + RequestAdvanceRequesterFunded = 'request__advanceRequesterFunded', RequestChallengePeriodEnd = 'request__challengePeriodEnd', RequestCreationTime = 'request__creationTime', RequestExpirationTime = 'request__expirationTime', @@ -606,13 +607,34 @@ export type Claimer_Filter = { nbVouchesReceived_not?: InputMaybe; nbVouchesReceived_not_in?: InputMaybe>; or?: InputMaybe>>; + registration?: InputMaybe; registration_?: InputMaybe; + registration_contains?: InputMaybe; + registration_contains_nocase?: InputMaybe; + registration_ends_with?: InputMaybe; + registration_ends_with_nocase?: InputMaybe; + registration_gt?: InputMaybe; + registration_gte?: InputMaybe; + registration_in?: InputMaybe>; + registration_lt?: InputMaybe; + registration_lte?: InputMaybe; + registration_not?: InputMaybe; + registration_not_contains?: InputMaybe; + registration_not_contains_nocase?: InputMaybe; + registration_not_ends_with?: InputMaybe; + registration_not_ends_with_nocase?: InputMaybe; + registration_not_in?: InputMaybe>; + registration_not_starts_with?: InputMaybe; + registration_not_starts_with_nocase?: InputMaybe; + registration_starts_with?: InputMaybe; + registration_starts_with_nocase?: InputMaybe; vouchesReceived_?: InputMaybe; vouches_?: InputMaybe; }; export enum Claimer_OrderBy { CurrentRequest = 'currentRequest', + CurrentRequestAdvanceRequesterFunded = 'currentRequest__advanceRequesterFunded', CurrentRequestChallengePeriodEnd = 'currentRequest__challengePeriodEnd', CurrentRequestCreationTime = 'currentRequest__creationTime', CurrentRequestExpirationTime = 'currentRequest__expirationTime', @@ -744,9 +766,14 @@ export enum Contract_OrderBy { export type Contribution = { __typename?: 'Contribution'; amount: Scalars['BigInt']; + challenge: Challenge; contributor: Scalars['Bytes']; fund: Fund; + humanity: Humanity; id: Scalars['Bytes']; + request: Request; + round: Round; + side: Party; }; export type Contribution_Filter = { @@ -761,6 +788,27 @@ export type Contribution_Filter = { amount_not?: InputMaybe; amount_not_in?: InputMaybe>; and?: InputMaybe>>; + challenge?: InputMaybe; + challenge_?: InputMaybe; + challenge_contains?: InputMaybe; + challenge_contains_nocase?: InputMaybe; + challenge_ends_with?: InputMaybe; + challenge_ends_with_nocase?: InputMaybe; + challenge_gt?: InputMaybe; + challenge_gte?: InputMaybe; + challenge_in?: InputMaybe>; + challenge_lt?: InputMaybe; + challenge_lte?: InputMaybe; + challenge_not?: InputMaybe; + challenge_not_contains?: InputMaybe; + challenge_not_contains_nocase?: InputMaybe; + challenge_not_ends_with?: InputMaybe; + challenge_not_ends_with_nocase?: InputMaybe; + challenge_not_in?: InputMaybe>; + challenge_not_starts_with?: InputMaybe; + challenge_not_starts_with_nocase?: InputMaybe; + challenge_starts_with?: InputMaybe; + challenge_starts_with_nocase?: InputMaybe; contributor?: InputMaybe; contributor_contains?: InputMaybe; contributor_gt?: InputMaybe; @@ -792,6 +840,27 @@ export type Contribution_Filter = { fund_not_starts_with_nocase?: InputMaybe; fund_starts_with?: InputMaybe; fund_starts_with_nocase?: InputMaybe; + humanity?: InputMaybe; + humanity_?: InputMaybe; + humanity_contains?: InputMaybe; + humanity_contains_nocase?: InputMaybe; + humanity_ends_with?: InputMaybe; + humanity_ends_with_nocase?: InputMaybe; + humanity_gt?: InputMaybe; + humanity_gte?: InputMaybe; + humanity_in?: InputMaybe>; + humanity_lt?: InputMaybe; + humanity_lte?: InputMaybe; + humanity_not?: InputMaybe; + humanity_not_contains?: InputMaybe; + humanity_not_contains_nocase?: InputMaybe; + humanity_not_ends_with?: InputMaybe; + humanity_not_ends_with_nocase?: InputMaybe; + humanity_not_in?: InputMaybe>; + humanity_not_starts_with?: InputMaybe; + humanity_not_starts_with_nocase?: InputMaybe; + humanity_starts_with?: InputMaybe; + humanity_starts_with_nocase?: InputMaybe; id?: InputMaybe; id_contains?: InputMaybe; id_gt?: InputMaybe; @@ -803,17 +872,118 @@ export type Contribution_Filter = { id_not_contains?: InputMaybe; id_not_in?: InputMaybe>; or?: InputMaybe>>; + request?: InputMaybe; + request_?: InputMaybe; + request_contains?: InputMaybe; + request_contains_nocase?: InputMaybe; + request_ends_with?: InputMaybe; + request_ends_with_nocase?: InputMaybe; + request_gt?: InputMaybe; + request_gte?: InputMaybe; + request_in?: InputMaybe>; + request_lt?: InputMaybe; + request_lte?: InputMaybe; + request_not?: InputMaybe; + request_not_contains?: InputMaybe; + request_not_contains_nocase?: InputMaybe; + request_not_ends_with?: InputMaybe; + request_not_ends_with_nocase?: InputMaybe; + request_not_in?: InputMaybe>; + request_not_starts_with?: InputMaybe; + request_not_starts_with_nocase?: InputMaybe; + request_starts_with?: InputMaybe; + request_starts_with_nocase?: InputMaybe; + round?: InputMaybe; + round_?: InputMaybe; + round_contains?: InputMaybe; + round_contains_nocase?: InputMaybe; + round_ends_with?: InputMaybe; + round_ends_with_nocase?: InputMaybe; + round_gt?: InputMaybe; + round_gte?: InputMaybe; + round_in?: InputMaybe>; + round_lt?: InputMaybe; + round_lte?: InputMaybe; + round_not?: InputMaybe; + round_not_contains?: InputMaybe; + round_not_contains_nocase?: InputMaybe; + round_not_ends_with?: InputMaybe; + round_not_ends_with_nocase?: InputMaybe; + round_not_in?: InputMaybe>; + round_not_starts_with?: InputMaybe; + round_not_starts_with_nocase?: InputMaybe; + round_starts_with?: InputMaybe; + round_starts_with_nocase?: InputMaybe; + side?: InputMaybe; + side_?: InputMaybe; + side_contains?: InputMaybe; + side_contains_nocase?: InputMaybe; + side_ends_with?: InputMaybe; + side_ends_with_nocase?: InputMaybe; + side_gt?: InputMaybe; + side_gte?: InputMaybe; + side_in?: InputMaybe>; + side_lt?: InputMaybe; + side_lte?: InputMaybe; + side_not?: InputMaybe; + side_not_contains?: InputMaybe; + side_not_contains_nocase?: InputMaybe; + side_not_ends_with?: InputMaybe; + side_not_ends_with_nocase?: InputMaybe; + side_not_in?: InputMaybe>; + side_not_starts_with?: InputMaybe; + side_not_starts_with_nocase?: InputMaybe; + side_starts_with?: InputMaybe; + side_starts_with_nocase?: InputMaybe; }; export enum Contribution_OrderBy { Amount = 'amount', + Challenge = 'challenge', + ChallengeCreationTime = 'challenge__creationTime', + ChallengeDisputeId = 'challenge__disputeId', + ChallengeId = 'challenge__id', + ChallengeIndex = 'challenge__index', + ChallengeNbRounds = 'challenge__nbRounds', Contributor = 'contributor', Fund = 'fund', FundAmount = 'fund__amount', FundFeeRewards = 'fund__feeRewards', FundId = 'fund__id', FundWithdrawn = 'fund__withdrawn', - Id = 'id' + Humanity = 'humanity', + HumanityClaimerName = 'humanity__claimerName', + HumanityId = 'humanity__id', + HumanityInTransfer = 'humanity__inTransfer', + HumanityNbBridgedRequests = 'humanity__nbBridgedRequests', + HumanityNbLegacyRequests = 'humanity__nbLegacyRequests', + HumanityNbPendingRequests = 'humanity__nbPendingRequests', + HumanityNbRequests = 'humanity__nbRequests', + HumanityPendingRevocation = 'humanity__pendingRevocation', + HumanityVouching = 'humanity__vouching', + Id = 'id', + Request = 'request', + RequestAdvanceRequesterFunded = 'request__advanceRequesterFunded', + RequestChallengePeriodEnd = 'request__challengePeriodEnd', + RequestCreationTime = 'request__creationTime', + RequestExpirationTime = 'request__expirationTime', + RequestId = 'request__id', + RequestInTransferHash = 'request__inTransferHash', + RequestIndex = 'request__index', + RequestLastStatusChange = 'request__lastStatusChange', + RequestNbChallenges = 'request__nbChallenges', + RequestPunishedVouchTimestamp = 'request__punishedVouchTimestamp', + RequestRegistrationEvidenceRevokedReq = 'request__registrationEvidenceRevokedReq', + RequestRequester = 'request__requester', + RequestResolutionTime = 'request__resolutionTime', + RequestRevocation = 'request__revocation', + Round = 'round', + RoundCreationTime = 'round__creationTime', + RoundId = 'round__id', + RoundIndex = 'round__index', + Side = 'side', + SideCount = 'side__count', + SideId = 'side__id' } export type CrossChainGateway = { @@ -984,6 +1154,7 @@ export enum EvidenceGroup_OrderBy { Id = 'id', Length = 'length', Request = 'request', + RequestAdvanceRequesterFunded = 'request__advanceRequesterFunded', RequestChallengePeriodEnd = 'request__challengePeriodEnd', RequestCreationTime = 'request__creationTime', RequestExpirationTime = 'request__expirationTime', @@ -2535,6 +2706,7 @@ export enum Registration_OrderBy { export type Request = { __typename?: 'Request'; + advanceRequesterFunded: Scalars['Boolean']; arbitratorHistory: ArbitratorHistory; challengePeriodEnd: Scalars['BigInt']; challenges: Array; @@ -2583,6 +2755,10 @@ export type RequestVouchesArgs = { export type Request_Filter = { /** Filter for the block changed event. */ _change_block?: InputMaybe; + advanceRequesterFunded?: InputMaybe; + advanceRequesterFunded_in?: InputMaybe>; + advanceRequesterFunded_not?: InputMaybe; + advanceRequesterFunded_not_in?: InputMaybe>; and?: InputMaybe>>; arbitratorHistory?: InputMaybe; arbitratorHistory_?: InputMaybe; @@ -2901,6 +3077,7 @@ export type Request_Filter = { }; export enum Request_OrderBy { + AdvanceRequesterFunded = 'advanceRequesterFunded', ArbitratorHistory = 'arbitratorHistory', ArbitratorHistoryArbitrator = 'arbitratorHistory__arbitrator', ArbitratorHistoryClearingMeta = 'arbitratorHistory__clearingMeta', @@ -2939,6 +3116,7 @@ export enum Request_OrderBy { PunishedVouchReasonCount = 'punishedVouchReason__count', PunishedVouchReasonId = 'punishedVouchReason__id', PunishedVouchSourceRequest = 'punishedVouchSourceRequest', + PunishedVouchSourceRequestAdvanceRequesterFunded = 'punishedVouchSourceRequest__advanceRequesterFunded', PunishedVouchSourceRequestChallengePeriodEnd = 'punishedVouchSourceRequest__challengePeriodEnd', PunishedVouchSourceRequestCreationTime = 'punishedVouchSourceRequest__creationTime', PunishedVouchSourceRequestExpirationTime = 'punishedVouchSourceRequest__expirationTime', @@ -3389,6 +3567,7 @@ export enum VouchInProcess_OrderBy { Id = 'id', Processed = 'processed', Request = 'request', + RequestAdvanceRequesterFunded = 'request__advanceRequesterFunded', RequestChallengePeriodEnd = 'request__challengePeriodEnd', RequestCreationTime = 'request__creationTime', RequestExpirationTime = 'request__expirationTime', @@ -3648,6 +3827,14 @@ export type CrossChainUpdatesQueryVariables = Exact<{ export type CrossChainUpdatesQuery = { __typename?: 'Query', outUpdates: Array<{ __typename?: 'OutUpdate', id: string, humanityId: any, txHash: any, logIndex: any, timestamp: any }>, inUpdates: Array<{ __typename?: 'InUpdate', id: string, humanityId: any, txHash: any, logIndex: any, timestamp: any }> }; +export type HistoricalWinnerClaimQueryVariables = Exact<{ + humanityId: Scalars['Bytes']; + lastStatusChange: Scalars['BigInt']; +}>; + + +export type HistoricalWinnerClaimQuery = { __typename?: 'Query', requests: Array<{ __typename?: 'Request', creationTime: any, index: any, lastStatusChange: any, requester: any, resolutionTime: any, claimer: { __typename?: 'Claimer', id: any, name?: string | null }, evidenceGroup: { __typename?: 'EvidenceGroup', evidence: Array<{ __typename?: 'Evidence', uri: string }> } }> }; + export type HumanityQueryVariables = Exact<{ id: Scalars['ID']; }>; @@ -3662,14 +3849,6 @@ export type HumanityEventsQueryVariables = Exact<{ export type HumanityEventsQuery = { __typename?: 'Query', humanityEvents: Array<{ __typename?: 'HumanityEvent', id: string, timestamp: any, type: HumanityEventType, requestIndex?: any | null, transferHash?: any | null, voucher?: any | null, disputeId?: any | null, appealRound?: any | null, revocation?: boolean | null }> }; -export type HistoricalWinnerClaimQueryVariables = Exact<{ - humanityId: Scalars['Bytes']; - lastStatusChange: Scalars['BigInt']; -}>; - - -export type HistoricalWinnerClaimQuery = { __typename?: 'Query', requests: Array<{ __typename?: 'Request', creationTime: any, index: any, lastStatusChange: any, requester: any, resolutionTime: any, claimer: { __typename?: 'Claimer', id: any, name?: string | null }, evidenceGroup: { __typename?: 'EvidenceGroup', evidence: Array<{ __typename?: 'Evidence', uri: string }> } }> }; - export type MeQueryVariables = Exact<{ id: Scalars['ID']; }>; @@ -3921,6 +4100,31 @@ export const CrossChainUpdatesDocument = gql` } } `; +export const HistoricalWinnerClaimDocument = gql` + query HistoricalWinnerClaim($humanityId: Bytes!, $lastStatusChange: BigInt!) { + requests( + where: {humanity_: {id: $humanityId}, revocation: false, winnerParty: "requester", status_in: ["resolved", "transferred"], evidenceGroup_: {length_gt: 0}, lastStatusChange_lte: $lastStatusChange} + first: 1 + orderBy: lastStatusChange + orderDirection: desc + ) { + claimer { + id + name + } + creationTime + index + lastStatusChange + requester + resolutionTime + evidenceGroup { + evidence(orderBy: creationTime, orderDirection: asc, first: 1) { + uri + } + } + } +} + `; export const HumanityDocument = gql` query Humanity($id: ID!) { humanity(id: $id) { @@ -3996,31 +4200,6 @@ export const HumanityEventsDocument = gql` } } `; -export const HistoricalWinnerClaimDocument = gql` - query HistoricalWinnerClaim($humanityId: Bytes!, $lastStatusChange: BigInt!) { - requests( - where: {humanity_: {id: $humanityId}, revocation: false, winnerParty: "requester", status_in: ["resolved", "transferred"], evidenceGroup_: {length_gt: 0}, lastStatusChange_lte: $lastStatusChange} - first: 1 - orderBy: lastStatusChange - orderDirection: desc - ) { - claimer { - id - name - } - creationTime - index - lastStatusChange - requester - resolutionTime - evidenceGroup { - evidence(orderBy: creationTime, orderDirection: asc, first: 1) { - uri - } - } - } -} - `; export const MeDocument = gql` query Me($id: ID!) { claimer(id: $id) { @@ -4346,68 +4525,68 @@ const defaultWrapper: SdkFunctionWrapper = (action, _operationName, _operationTy export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = defaultWrapper) { return { GetCirclesAccountsByaddress(variables: GetCirclesAccountsByaddressQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(GetCirclesAccountsByaddressDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'GetCirclesAccountsByaddress', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: GetCirclesAccountsByaddressDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'GetCirclesAccountsByaddress', 'query', variables); }, GetHumanityWithCircleAccountById(variables: GetHumanityWithCircleAccountByIdQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(GetHumanityWithCircleAccountByIdDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'GetHumanityWithCircleAccountById', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: GetHumanityWithCircleAccountByIdDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'GetHumanityWithCircleAccountById', 'query', variables); }, HumanityIdByClaimer(variables: HumanityIdByClaimerQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(HumanityIdByClaimerDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'HumanityIdByClaimer', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: HumanityIdByClaimerDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'HumanityIdByClaimer', 'query', variables); }, RequestsToAdvance(variables?: RequestsToAdvanceQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RequestsToAdvanceDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'RequestsToAdvance', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RequestsToAdvanceDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'RequestsToAdvance', 'query', variables); }, Claimer(variables: ClaimerQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(ClaimerDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Claimer', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: ClaimerDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Claimer', 'query', variables); }, Contract(variables?: ContractQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(ContractDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Contract', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: ContractDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Contract', 'query', variables); }, CrossChainUpdates(variables: CrossChainUpdatesQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(CrossChainUpdatesDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'CrossChainUpdates', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: CrossChainUpdatesDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'CrossChainUpdates', 'query', variables); + }, + HistoricalWinnerClaim(variables: HistoricalWinnerClaimQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { + return withWrapper((wrappedRequestHeaders) => client.request({ document: HistoricalWinnerClaimDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'HistoricalWinnerClaim', 'query', variables); }, Humanity(variables: HumanityQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(HumanityDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Humanity', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: HumanityDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Humanity', 'query', variables); }, HumanityEvents(variables: HumanityEventsQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(HumanityEventsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'HumanityEvents', 'query', variables); - }, - HistoricalWinnerClaim(variables: HistoricalWinnerClaimQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(HistoricalWinnerClaimDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'HistoricalWinnerClaim', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: HumanityEventsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'HumanityEvents', 'query', variables); }, Me(variables: MeQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(MeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Me', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: MeDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Me', 'query', variables); }, ProfileHumanity(variables: ProfileHumanityQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(ProfileHumanityDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'ProfileHumanity', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: ProfileHumanityDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'ProfileHumanity', 'query', variables); }, ProfileRequest(variables: ProfileRequestQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(ProfileRequestDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'ProfileRequest', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: ProfileRequestDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'ProfileRequest', 'query', variables); }, Registration(variables: RegistrationQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RegistrationDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Registration', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RegistrationDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Registration', 'query', variables); }, Request(variables: RequestQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RequestDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Request', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RequestDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Request', 'query', variables); }, RequestTimelineNode(variables: RequestTimelineNodeQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RequestTimelineNodeDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'RequestTimelineNode', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RequestTimelineNodeDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'RequestTimelineNode', 'query', variables); }, Requests(variables?: RequestsQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RequestsDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Requests', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RequestsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Requests', 'query', variables); }, RewardClaim(variables: RewardClaimQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(RewardClaimDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'RewardClaim', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: RewardClaimDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'RewardClaim', 'query', variables); }, IsSynced(variables: IsSyncedQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(IsSyncedDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'IsSynced', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: IsSyncedDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'IsSynced', 'query', variables); }, Transfer(variables: TransferQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(TransferDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'Transfer', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: TransferDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'Transfer', 'query', variables); }, HumanityVouch(variables: HumanityVouchQueryVariables, requestHeaders?: GraphQLClientRequestHeaders, signal?: RequestInit['signal']): Promise { - return withWrapper((wrappedRequestHeaders) => client.request(HumanityVouchDocument, variables, { ...requestHeaders, ...wrappedRequestHeaders }), 'HumanityVouch', 'query', variables); + return withWrapper((wrappedRequestHeaders) => client.request({ document: HumanityVouchDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), 'HumanityVouch', 'query', variables); } }; } -export type Sdk = ReturnType; +export type Sdk = ReturnType; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 410d7e1a..b0ced63c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1421,9 +1421,9 @@ tslib "~2.4.0" "@graphql-codegen/typescript-graphql-request@^6.3.0": - version "6.3.0" - resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-graphql-request/-/typescript-graphql-request-6.3.0.tgz#8de6246edef0a114e2e7b5203215c98490ace95e" - integrity sha512-IX42XakdcbGosIQo0jkH/4Tj5hk5smDmACYHMJbuSAA9vlcJNHkl3LGyG1Ggy2qVSI20nmNMaxpTg74SSyb4Yg== + version "6.4.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-graphql-request/-/typescript-graphql-request-6.4.0.tgz#ea4fa1a825b7712224a69df4e91879a8ea2af45b" + integrity sha512-O51cfVFvteJQ9pfgRCyBcRE8FJgWLUYf9DR12FhRWYUbh+Qfd0h0t4DsarIWzAskMCHn3clxpAf44eZTTJ6Jew== dependencies: "@graphql-codegen/plugin-helpers" "^3.0.0" "@graphql-codegen/visitor-plugin-common" "2.13.8" @@ -6434,11 +6434,6 @@ extract-files@^11.0.0: resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== -extract-files@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" - integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== - fast-copy@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" @@ -6656,17 +6651,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.6" signal-exit "^4.0.1" -form-data@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.4.tgz#938273171d3f999286a4557528ce022dc2c98df1" - integrity sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - es-set-tostringtag "^2.1.0" - hasown "^2.0.2" - mime-types "^2.1.35" - form-data@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" @@ -6915,15 +6899,6 @@ graphql-config@^4.1.0: string-env-interpolation "1.0.1" tslib "^2.4.0" -graphql-request@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" - integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== - dependencies: - cross-fetch "^3.1.5" - extract-files "^9.0.0" - form-data "^3.0.0" - graphql-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f" @@ -6932,6 +6907,13 @@ graphql-request@^6.0.0: "@graphql-typed-document-node/core" "^3.2.0" cross-fetch "^3.1.5" +graphql-request@^7.1.2: + version "7.4.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-7.4.0.tgz#97a1fc871e79f682d816963446ac6b7f99c963f9" + integrity sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + graphql-tag@^2.11.0, graphql-tag@^2.12.6: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" @@ -8352,7 +8334,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.35: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== From 99b8b35b919b11be5988b8a268f241483c8c3d07 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:17:59 +0530 Subject: [PATCH 05/27] fix(revamp/1): wire new SVGs at correct display sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the social/notification badge assets in Footer and Header chrome, point Circles dark logo at gnosis-app.svg with its native 185×48 size, and make ExternalLink/CheckCircle scale via currentColor and className. --- src/app/Footer.tsx | 54 ++++++++--- src/app/Header/Options.tsx | 143 +++++++++++++---------------- src/app/Header/SettingsPopover.tsx | 17 ++-- src/data/integrations.ts | 4 +- src/icons/CheckCircle.svg | 2 +- src/icons/ExternalLink.svg | 7 +- 6 files changed, 123 insertions(+), 104 deletions(-) diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index b11f13da..13a956ad 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -1,6 +1,32 @@ import Image from "next/image"; import ExternalLink from "components/ExternalLink"; +/** Circular social badges are authored at 32×32 — render 1:1. */ +const SOCIAL_ICON_SIZE = 32; + +const SOCIALS = [ + { + alt: "snapshot", + src: "/logo/social-snapshot.svg", + href: "https://snapshot.org/#/poh.eth/", + }, + { + alt: "github", + src: "/logo/social-github.svg", + href: "https://github.com/proof-of-humanity", + }, + { + alt: "x", + src: "/logo/social-x.svg", + href: "https://twitter.com/proofofhumanity", + }, + { + alt: "telegram", + src: "/logo/social-telegram.svg", + href: "https://t.me/proofhumanity", + }, +] as const; + const Footer: React.FC = () => (
( kleros -
- - snapshot - - - github - - - twitter - - - telegram - +
+ {SOCIALS.map((social) => ( + + {social.alt} + + ))}
); diff --git a/src/app/Header/Options.tsx b/src/app/Header/Options.tsx index 86df2472..2a47ae84 100644 --- a/src/app/Header/Options.tsx +++ b/src/app/Header/Options.tsx @@ -1,91 +1,74 @@ import Image from "next/image"; -import React, { useEffect, useState } from "react"; +import React from "react"; import ExternalLink from "components/ExternalLink"; import Popover from "components/Popover"; import SettingsPopover from "./SettingsPopover"; -const Options: React.FC = () => { - const [isDarkMode, setIsDarkMode] = useState(false); +/** + * Header chrome badges are 32×32 assets; render at 36 so the touch target + * matches neighboring controls while keeping the artwork crisp. + */ +const HEADER_BADGE_SIZE = 36; - useEffect(() => { - const savedTheme = localStorage.getItem("theme"); - if (savedTheme === "dark") { - document.documentElement.classList.add("dark"); - setIsDarkMode(true); - } else { - document.documentElement.classList.remove("dark"); - setIsDarkMode(false); - } - }, []); - - const toggleTheme = () => { - if (isDarkMode) { - document.documentElement.classList.remove("dark"); - localStorage.setItem("theme", "light"); - setIsDarkMode(false); - } else { - document.documentElement.classList.add("dark"); - localStorage.setItem("theme", "dark"); - setIsDarkMode(true); - } - }; - - return ( -
- - - snapshot - +const Options: React.FC = () => ( +
+ + + snapshot + - question - } - > -
- - Get Help (English) - - - Get Help (Spanish) - - - Forums - - - Report Bugs (Telegram) - - - Report Bugs (Github) - - - Tutorial - - - Crypto Beginner's Guide - - - FAQ - -
-
- - toggle theme -
- ); -}; + + } + > +
+ + Get Help (English) + + + Get Help (Spanish) + + + Forums + + + Report Bugs (Telegram) + + + Report Bugs (Github) + + + Tutorial + + + Crypto Beginner's Guide + + + FAQ + +
+ +
+); export default Options; diff --git a/src/app/Header/SettingsPopover.tsx b/src/app/Header/SettingsPopover.tsx index 6bbfd813..2910ae5d 100644 --- a/src/app/Header/SettingsPopover.tsx +++ b/src/app/Header/SettingsPopover.tsx @@ -39,26 +39,29 @@ const SettingsPopover: React.FC = () => { const showUnreadDot = isVerified && !hasVerifiedEmail; return ( -
+
+ {/* notifications.svg is authored at 32×32; 36 matches other header badges */} notifications {showUnreadDot && ( + } open={isOpen} onClose={closeAndDiscardChanges} diff --git a/src/data/integrations.ts b/src/data/integrations.ts index e3438077..9d70eb53 100644 --- a/src/data/integrations.ts +++ b/src/data/integrations.ts @@ -8,7 +8,9 @@ const integrations: Record = { description: "Join our group on the Gnosis App to start your daily income and unlock exclusive perks!", logo: "/images/integrations/circles-logo.png", - logoWidth: 164, + // gnosis-app.svg is 185×48 — keep render size in sync with the asset. + darkLogo: "/logo/gnosis-app.svg", + logoWidth: 185, logoHeight: 48, isActive: true, startPath: "app/circles", diff --git a/src/icons/CheckCircle.svg b/src/icons/CheckCircle.svg index 9f999fe8..1ff47856 100644 --- a/src/icons/CheckCircle.svg +++ b/src/icons/CheckCircle.svg @@ -1,3 +1,3 @@ - + diff --git a/src/icons/ExternalLink.svg b/src/icons/ExternalLink.svg index c42b8ffd..b6b0c372 100644 --- a/src/icons/ExternalLink.svg +++ b/src/icons/ExternalLink.svg @@ -1,3 +1,6 @@ - - + + From 386f15f80284d04631949ca2ec683364bffe0942 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:23:04 +0530 Subject: [PATCH 06/27] feat(revamp/1): move navbar chrome into foundation Bring header navigation, wallet section, options, notifications control, and footer social badges from the chrome layer so the foundation PR owns the full shell UI and SVG wiring. --- src/app/Footer.tsx | 14 ++------ src/app/Header/DesktopNavigation.tsx | 33 ++++++++++------- src/app/Header/MobileMenu.tsx | 8 +++-- src/app/Header/Options.tsx | 16 +++------ src/app/Header/SettingsPopover.tsx | 6 ++-- src/app/Header/WalletSection.tsx | 13 +++---- src/app/Header/index.tsx | 53 ++++++---------------------- 7 files changed, 54 insertions(+), 89 deletions(-) diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index 13a956ad..842b1f04 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -1,9 +1,6 @@ import Image from "next/image"; import ExternalLink from "components/ExternalLink"; -/** Circular social badges are authored at 32×32 — render 1:1. */ -const SOCIAL_ICON_SIZE = 32; - const SOCIALS = [ { alt: "snapshot", @@ -25,10 +22,10 @@ const SOCIALS = [ src: "/logo/social-telegram.svg", href: "https://t.me/proofhumanity", }, -] as const; +]; const Footer: React.FC = () => ( -
+
( href={social.href} className="transition-opacity duration-200 hover:opacity-80" > - {social.alt} + {social.alt} ))}
diff --git a/src/app/Header/DesktopNavigation.tsx b/src/app/Header/DesktopNavigation.tsx index d02c884e..ae91eaa6 100644 --- a/src/app/Header/DesktopNavigation.tsx +++ b/src/app/Header/DesktopNavigation.tsx @@ -5,6 +5,14 @@ import { useSearchParams } from "next/navigation"; import { sepolia } from "viem/chains"; import ExternalLink from "components/ExternalLink"; import RegisterLink from "./RegisterLink"; +import { prettifyId } from "utils/identifier"; + +const navLink = (active: boolean) => + `relative whitespace-nowrap py-2 text-lg font-semibold transition-colors duration-200 after:absolute after:inset-x-0 after:-bottom-0.5 after:h-px after:origin-center after:rounded-full after:bg-peach after:shadow-[0_0_12px_rgba(255,176,138,0.45)] after:transition-transform after:duration-200 ${ + active + ? "text-orange after:scale-x-100" + : "text-secondaryText after:scale-x-0 hover:text-primaryText" + }`; interface DesktopNavigationProps { web3Loaded: boolean; @@ -31,14 +39,21 @@ const DesktopNavigation = ({ const currentUrl = searchParams.get("url"); const policyHref = policy && `/attachment?url=${encodeURIComponent(policy)}`; + const registerActive = me?.pohId + ? pathname === `/${prettifyId(me.pohId)}` + : pathname.includes("/claim"); + return ( -
+
{web3Loaded && chain.id === sepolia.id && ( - + Faucet )} - + Profiles {policyHref && ( - + Policy )} - + Rewards
diff --git a/src/app/Header/MobileMenu.tsx b/src/app/Header/MobileMenu.tsx index 266c0096..186403d0 100644 --- a/src/app/Header/MobileMenu.tsx +++ b/src/app/Header/MobileMenu.tsx @@ -6,6 +6,7 @@ import { Ref, forwardRef } from "react"; import Options from "./Options"; import RegisterLink from "./RegisterLink"; import WalletSection from "./WalletSection"; +import { prettifyId } from "utils/identifier"; interface MobileMenuProps { policy: string; @@ -38,11 +39,14 @@ const MobileMenu = forwardRef( const currentUrl = searchParams.get("url"); const policyHref = policy && `/attachment?url=${encodeURIComponent(policy)}`; + const registerActive = me?.pohId + ? pathname === `/${prettifyId(me.pohId)}` + : pathname.includes("/claim"); return (
{chain && ( -
+
)} -
+
{chain && (
From a91b14c5e7382cb2bc11b0238b1eca9b706bc15f Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 16:54:47 +0530 Subject: [PATCH 07/27] feat(revamp/1): wire Figma states, timeline icons and logos Timeline renders every milestone's design glyph (flag-checkered, eye, challenge, vouch, check/close-circle, hourglass, transfer) tinted with the status palette. New StatusIcon implements the Figma States set and feeds the request card chip, the grid status filter and the action-bar tag (now the dark-pill Tag style). Header uses the poh lockup, footer the built-by-kleros lockup; kleros + poh-ID marks refreshed from Figma. --- public/logo/built-by-kleros.svg | 18 ++++++ public/logo/kleros.svg | 12 +--- public/logo/poh.svg | 3 + public/logo/pohid.svg | 14 ++--- src/app/Footer.tsx | 8 ++- src/app/Header/index.tsx | 4 +- .../[pohid]/[chain]/[request]/ActionBar.tsx | 4 +- .../[pohid]/[chain]/[request]/Timeline.tsx | 58 ++++++++++++++----- src/components/Request/Card.tsx | 2 + src/components/Request/Grid.tsx | 18 ++---- src/components/StatusIcon.tsx | 54 +++++++++++++++++ src/icons/FlagCheckered.svg | 3 + src/icons/Hourglass.svg | 20 +++---- src/icons/Transfer.svg | 10 ++++ 14 files changed, 166 insertions(+), 62 deletions(-) create mode 100644 public/logo/built-by-kleros.svg create mode 100644 public/logo/poh.svg create mode 100644 src/components/StatusIcon.tsx create mode 100644 src/icons/FlagCheckered.svg create mode 100644 src/icons/Transfer.svg diff --git a/public/logo/built-by-kleros.svg b/public/logo/built-by-kleros.svg new file mode 100644 index 00000000..9d7b36e4 --- /dev/null +++ b/public/logo/built-by-kleros.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/logo/kleros.svg b/public/logo/kleros.svg index 33e06ef6..d16dd21e 100644 --- a/public/logo/kleros.svg +++ b/public/logo/kleros.svg @@ -1,11 +1,3 @@ - - - - - - - - - - + + diff --git a/public/logo/poh.svg b/public/logo/poh.svg new file mode 100644 index 00000000..7c5ba155 --- /dev/null +++ b/public/logo/poh.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/logo/pohid.svg b/public/logo/pohid.svg index 16b3274f..f9335bfe 100644 --- a/public/logo/pohid.svg +++ b/public/logo/pohid.svg @@ -1,17 +1,17 @@ - - - - + + + + - + - + - + diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index 842b1f04..1ba02243 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -30,8 +30,12 @@ const Footer: React.FC = () => ( className="flex items-center gap-2 text-sm" href="https://kleros.io/" > - BUILT BY{" "} - +
diff --git a/src/app/Header/index.tsx b/src/app/Header/index.tsx index d75fa4e3..46191595 100644 --- a/src/app/Header/index.tsx +++ b/src/app/Header/index.tsx @@ -59,8 +59,8 @@ export default function Header({ policy }: IHeader) { proof of humanity logo diff --git a/src/app/[pohid]/[chain]/[request]/ActionBar.tsx b/src/app/[pohid]/[chain]/[request]/ActionBar.tsx index 7860a03e..67a29d2b 100644 --- a/src/app/[pohid]/[chain]/[request]/ActionBar.tsx +++ b/src/app/[pohid]/[chain]/[request]/ActionBar.tsx @@ -2,6 +2,7 @@ import { enableReactUse } from "@legendapp/state/config/enableReactUse"; import ExternalLink from "components/ExternalLink"; +import StatusIcon from "components/StatusIcon"; import TimeAgo from "components/TimeAgo"; import ActionButton from "components/ActionButton"; import usePoHWrite from "contracts/hooks/usePoHWrite"; @@ -377,8 +378,9 @@ export default function ActionBar({
Status + {getStatusLabel(effectiveRequestStatus, "actionBar")}
diff --git a/src/app/[pohid]/[chain]/[request]/Timeline.tsx b/src/app/[pohid]/[chain]/[request]/Timeline.tsx index 620ab8f2..df5c1198 100644 --- a/src/app/[pohid]/[chain]/[request]/Timeline.tsx +++ b/src/app/[pohid]/[chain]/[request]/Timeline.tsx @@ -3,12 +3,24 @@ import ChainLogo from "components/ChainLogo"; import type { TimelineItem } from "data/requestTimeline"; import { idToChain } from "config/chains"; -import CheckCircleOutlineIcon from "icons/CheckCircleOutline16.svg"; -import CrossCircleIcon from "icons/CrossCircle16.svg"; +import ChallengeIcon from "icons/Challenge.svg"; +import CheckCircleOutlineIcon from "icons/CheckCircleOutline.svg"; +import CloseCircleOutlineIcon from "icons/CloseCircleOutline.svg"; +import EyeIcon from "icons/Eye.svg"; +import FlagCheckeredIcon from "icons/FlagCheckered.svg"; +import HourglassIcon from "icons/Hourglass.svg"; import NewTabIcon from "icons/NewTab.svg"; -import TimelineTransferIcon from "icons/TimelineTransfer.svg"; +import TransferIcon from "icons/Transfer.svg"; +import VouchIcon from "icons/Vouch.svg"; import Link from "next/link"; -import { type ReactNode, useEffect, useRef, useState } from "react"; +import { + type ComponentType, + type ReactNode, + type SVGProps, + useEffect, + useRef, + useState, +} from "react"; interface TimelineProps { items: TimelineItem[]; @@ -99,6 +111,28 @@ const TIMELINE_STYLES: Record< }, }; +// Figma "timeline-steps": every milestone renders its own icon, colored with +// the status palette. Kinds without an entry (appeal, withdrawn) keep the +// plain dot — the design defines no icon for them. +const TIMELINE_ICONS: Partial< + Record< + TimelineItem["kind"], + { Icon: ComponentType>; color: string } + > +> = { + submitted: { Icon: FlagCheckeredIcon, color: "text-primaryText" }, + inReview: { Icon: EyeIcon, color: "text-status-claim" }, + challenged: { Icon: ChallengeIcon, color: "text-status-challenged" }, + vouchReceived: { Icon: VouchIcon, color: "text-status-vouching" }, + vouchRemoved: { Icon: CloseCircleOutlineIcon, color: "text-status-removed" }, + verified: { Icon: CheckCircleOutlineIcon, color: "text-status-registered" }, + removed: { Icon: CloseCircleOutlineIcon, color: "text-status-removed" }, + rejected: { Icon: CloseCircleOutlineIcon, color: "text-status-rejected" }, + expired: { Icon: HourglassIcon, color: "text-secondaryText" }, + transferred: { Icon: TransferIcon, color: "text-secondaryText" }, + received: { Icon: TransferIcon, color: "text-secondaryText" }, +}; + const formatter = new Intl.DateTimeFormat("en-US", { month: "long", day: "2-digit", @@ -145,6 +179,7 @@ export default function Timeline({ items, children }: TimelineProps) {
{items.map((item, index) => { const styles = TIMELINE_STYLES[item.kind]; + const iconSpec = TIMELINE_ICONS[item.kind]; const isLast = index === items.length - 1; const lineDelay = `${index * ITEM_STEP_MS}ms`; const itemDelay = `${index * ITEM_STEP_MS + ITEM_REVEAL_OFFSET_MS}ms`; @@ -154,21 +189,12 @@ export default function Timeline({ items, children }: TimelineProps) {
- {item.kind === "transferred" ? ( - - ) : item.kind === "verified" ? ( - - ) : item.kind === "rejected" || - item.kind === "vouchRemoved" ? ( - + {iconSpec ? ( + ) : (
{item.isActive ? ( diff --git a/src/components/Request/Card.tsx b/src/components/Request/Card.tsx index 1886740e..5a9cef78 100644 --- a/src/components/Request/Card.tsx +++ b/src/components/Request/Card.tsx @@ -7,6 +7,7 @@ import { Suspense } from "react"; import { Address, Hash } from "viem"; import ChainLogo from "components/ChainLogo"; import ErrorBoundary from "components/ErrorBoundary"; +import StatusIcon from "components/StatusIcon"; import { WinnerClaimFragment } from "generated/graphql"; import useIPFS from "hooks/useIPFS"; import { EvidenceFile, RegistrationFile } from "types/docs"; @@ -143,6 +144,7 @@ function Card({
+ {getStatusLabel(requestStatus)} diff --git a/src/components/Request/Grid.tsx b/src/components/Request/Grid.tsx index db54a10d..3d1fbb3e 100644 --- a/src/components/Request/Grid.tsx +++ b/src/components/Request/Grid.tsx @@ -7,7 +7,6 @@ import { useObservable, useSelector, } from "@legendapp/state/react"; -import cn from "classnames"; import { SupportedChain, SupportedChainId, @@ -25,6 +24,7 @@ import { useEffect, useState } from "react"; import ChainLogo from "components/ChainLogo"; import DropdownItem from "components/Dropdown/Item"; import Dropdown from "components/Dropdown/Menu"; +import StatusIcon from "components/StatusIcon"; import { RequestsQuery } from "generated/graphql"; import { useLoading } from "hooks/useLoading"; import { @@ -33,7 +33,6 @@ import { getRequestStatusFilter, STATUS_FILTER_OPTIONS, getStatusLabel, - getStatusColor, } from "utils/status"; import Card from "./Card"; @@ -42,7 +41,7 @@ import Loading from "components/Loading"; enableReactUse(); const REQUESTS_BATCH_SIZE = 12; -var humanityLifespanAllChains: Record; +let humanityLifespanAllChains: Record; export type RequestsQueryItem = ArrayElement; @@ -70,7 +69,7 @@ const sortRequests = (request: RequestInterface[]): RequestInterface[] => { pohIdGrouped.forEach((val, key) => { val.sort((req1, req2) => req2.lastStatusChange - req1.lastStatusChange); }); - let requestsOut: RequestInterface[] = new Array(); + const requestsOut: RequestInterface[] = new Array(); pohIdGrouped.forEach((val, key) => { // We keep only the head request of each pohIdGrouped array which is the one representing the current status of the personhood const latestRequest = val[0]; @@ -323,16 +322,7 @@ function RequestsGrid() { {STATUS_FILTER_OPTIONS.map((status) => ( - } + icon={} selected={filter.status === status} onSelect={() => filter$.assign({ status, cursor: 1 })} name={getStatusLabel(status)} diff --git a/src/components/StatusIcon.tsx b/src/components/StatusIcon.tsx new file mode 100644 index 00000000..dfecb881 --- /dev/null +++ b/src/components/StatusIcon.tsx @@ -0,0 +1,54 @@ +import cn from "classnames"; +import ChallengeIcon from "icons/Challenge.svg"; +import CheckCircleOutlineIcon from "icons/CheckCircleOutline.svg"; +import CloseCircleOutlineIcon from "icons/CloseCircleOutline.svg"; +import EyeIcon from "icons/Eye.svg"; +import HourglassIcon from "icons/Hourglass.svg"; +import NeedsVouchIcon from "icons/NeedsVouch.svg"; +import TransferIcon from "icons/Transfer.svg"; +import type { ComponentType, SVGProps } from "react"; +import { getStatusColor, RequestStatus } from "utils/status"; + +// Figma "States" component set: each state renders its glyph tinted with the +// status color. Keyed by status color (many statuses share one color and, in +// the design, one glyph); colors without a dedicated glyph — the removal +// family, withdrawn, all — fall back to a plain dot, as in the design. +const STATUS_ICONS: Record>> = { + vouching: NeedsVouchIcon, + claim: EyeIcon, + registered: CheckCircleOutlineIcon, + challenged: ChallengeIcon, + rejected: CloseCircleOutlineIcon, + expired: HourglassIcon, + transferred: TransferIcon, + transferring: TransferIcon, +}; + +interface StatusIconProps { + status: RequestStatus; + className?: string; +} + +export default function StatusIcon({ status, className }: StatusIconProps) { + const color = getStatusColor(status); + const Icon = STATUS_ICONS[color]; + if (Icon) + return ( + + ); + return ( + + ); +} diff --git a/src/icons/FlagCheckered.svg b/src/icons/FlagCheckered.svg new file mode 100644 index 00000000..52a9c1f3 --- /dev/null +++ b/src/icons/FlagCheckered.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/icons/Hourglass.svg b/src/icons/Hourglass.svg index a15ba876..cbb7d609 100644 --- a/src/icons/Hourglass.svg +++ b/src/icons/Hourglass.svg @@ -1,10 +1,10 @@ - - - - - - - - - - \ No newline at end of file + + + + + + + + + + diff --git a/src/icons/Transfer.svg b/src/icons/Transfer.svg new file mode 100644 index 00000000..bdbab4c1 --- /dev/null +++ b/src/icons/Transfer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + From 94f03a68d23d2e83e901893f3dc931f84d6583f6 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 17:00:58 +0530 Subject: [PATCH 08/27] fix(revamp/1): enlarge header PoH lockup and swap favicon mark MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Render the new poh.svg lockup at its native 185×48 size and replace the legacy ethereum-era favicon with the human mark (poh-colored) via App Router icon assets. --- public/manifest.json | 2 +- src/app/Header/index.tsx | 8 +++++--- src/app/apple-icon.png | Bin 0 -> 4107 bytes src/app/favicon.ico | Bin 37662 -> 0 bytes src/app/icon.png | Bin 0 -> 663 bytes src/app/icon.svg | 9 +++++++++ 6 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/app/apple-icon.png delete mode 100644 src/app/favicon.ico create mode 100644 src/app/icon.png create mode 100644 src/app/icon.svg diff --git a/public/manifest.json b/public/manifest.json index f01dc4fc..8a28418d 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -4,7 +4,7 @@ "homepage_url": "https://poh.vercel.app", "name": "Proof of Humanity", "description": "Proof of Humanity", - "iconPath": "./poh-logo-colored.svg", + "iconPath": "/logo/poh-colored.svg", "short_name": "PoH", "start_url": ".", "theme_color": "#FF9966" diff --git a/src/app/Header/index.tsx b/src/app/Header/index.tsx index 46191595..edcaa751 100644 --- a/src/app/Header/index.tsx +++ b/src/app/Header/index.tsx @@ -56,12 +56,14 @@ export default function Header({ policy }: IHeader) { return (
- + proof of humanity logo diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8262e7978bafbcc1190e75ae9319f282a5d981 GIT binary patch literal 4107 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 OkPGIvX0;}s$^QZWx1K8i literal 0 HcmV?d00001 diff --git a/src/app/favicon.ico b/src/app/favicon.ico deleted file mode 100644 index 09232fde679041aaf46e48f2bcbbfd3570fe50a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37662 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 J-W9c8`Y!{J9{T_Q diff --git a/src/app/icon.png b/src/app/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e0bf512cdfdab0dd514344fc22a9a85ad9ab6aa6 GIT binary patch literal 663 zcmV;I0%-k-P)mNl8RORCt`l*1u~LaTv$()Ikt*X-Bn#oA_%}PzM(g2M58Svq($Q zwB%Y#ORdIINh`TazL&dvFK1#+8XKj9I*4>AZlZ%uBBF>01uG8mSA;6+TjK0pEq@cC@X?kvqsSkP`$3m>Cc@ z2>AlT-P2-tbRSY%MUK)208+UR2={Qa;ro$8H5`q$0cjV~S89mD?qK2B@OE<1HJo8O z2gpO}>SN;Z4FUc>a+h2b1pr9RpYRWN`wx(dpbk)6YycRLY5~_?HR`}Kr2wP24s`i- z;H%;hfK}@82IK~6{~NHX9B{d?#Rt&8tQ;^`-sZQ2=amDDQp_8W5AReC&`V!PRd#tJ zoX7*U9asQk@ihsLWkg0!{{sN%m3x1^3D}X%ID?3)VQ_#GGdm9`pJ}24v0F_8L~0!&`Y?=cgxibh9>j3_ z&DC#%>~ xRjl|Atcz7LGgUH)H<+`_WRhvp$s?@<{RZe=m^de-z|8;v002ovPDHLkV1h|QC?)^^ literal 0 HcmV?d00001 diff --git a/src/app/icon.svg b/src/app/icon.svg new file mode 100644 index 00000000..ab43d522 --- /dev/null +++ b/src/app/icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + From d8d98fd27b1030c8ee76b112a49dc77ca1bd5b02 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 17:11:11 +0530 Subject: [PATCH 09/27] chore(revamp/1): drop StatusIcon Figma comment --- src/components/StatusIcon.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/StatusIcon.tsx b/src/components/StatusIcon.tsx index dfecb881..8e909491 100644 --- a/src/components/StatusIcon.tsx +++ b/src/components/StatusIcon.tsx @@ -9,10 +9,6 @@ import TransferIcon from "icons/Transfer.svg"; import type { ComponentType, SVGProps } from "react"; import { getStatusColor, RequestStatus } from "utils/status"; -// Figma "States" component set: each state renders its glyph tinted with the -// status color. Keyed by status color (many statuses share one color and, in -// the design, one glyph); colors without a dedicated glyph — the removal -// family, withdrawn, all — fall back to a plain dot, as in the design. const STATUS_ICONS: Record>> = { vouching: NeedsVouchIcon, claim: EyeIcon, From ecceb7182b1fbdb5b57df25169c3807d72a90304 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 17:22:29 +0530 Subject: [PATCH 10/27] chore(revamp/1): remove design-doc comments from foundation PR --- src/app/[pohid]/[chain]/[request]/Timeline.tsx | 3 --- src/data/integrations.ts | 1 - 2 files changed, 4 deletions(-) diff --git a/src/app/[pohid]/[chain]/[request]/Timeline.tsx b/src/app/[pohid]/[chain]/[request]/Timeline.tsx index df5c1198..91aebe9e 100644 --- a/src/app/[pohid]/[chain]/[request]/Timeline.tsx +++ b/src/app/[pohid]/[chain]/[request]/Timeline.tsx @@ -111,9 +111,6 @@ const TIMELINE_STYLES: Record< }, }; -// Figma "timeline-steps": every milestone renders its own icon, colored with -// the status palette. Kinds without an entry (appeal, withdrawn) keep the -// plain dot — the design defines no icon for them. const TIMELINE_ICONS: Partial< Record< TimelineItem["kind"], diff --git a/src/data/integrations.ts b/src/data/integrations.ts index 9d70eb53..334fbacd 100644 --- a/src/data/integrations.ts +++ b/src/data/integrations.ts @@ -8,7 +8,6 @@ const integrations: Record = { description: "Join our group on the Gnosis App to start your daily income and unlock exclusive perks!", logo: "/images/integrations/circles-logo.png", - // gnosis-app.svg is 185×48 — keep render size in sync with the asset. darkLogo: "/logo/gnosis-app.svg", logoWidth: 185, logoHeight: 48, From 4c26faf18d87e9a9f5156c7415ed5a732fba6fd7 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 17:25:51 +0530 Subject: [PATCH 11/27] chore: trigger Netlify deploy preview after allowed_branches update From 5d311736d9712f27795fc27a5fc3b68f81a0748b Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 22:33:04 +0530 Subject: [PATCH 12/27] fix(revamp/1): address CodeRabbit review feedback Dark base text color instead of text-black (prevents unreadable flash), drop the duplicate .divider and redundant dark-mode button override, align explorerTxLink with explorerLink on SupportedChain, and extract isRegisterActive into utils/identifier for both navigations. --- src/app/Header/DesktopNavigation.tsx | 6 ++---- src/app/Header/MobileMenu.tsx | 6 ++---- src/app/globals.css | 11 +---------- src/config/chains.ts | 4 ++-- src/utils/identifier.ts | 5 +++++ 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/app/Header/DesktopNavigation.tsx b/src/app/Header/DesktopNavigation.tsx index ae91eaa6..3d599662 100644 --- a/src/app/Header/DesktopNavigation.tsx +++ b/src/app/Header/DesktopNavigation.tsx @@ -5,7 +5,7 @@ import { useSearchParams } from "next/navigation"; import { sepolia } from "viem/chains"; import ExternalLink from "components/ExternalLink"; import RegisterLink from "./RegisterLink"; -import { prettifyId } from "utils/identifier"; +import { isRegisterActive } from "utils/identifier"; const navLink = (active: boolean) => `relative whitespace-nowrap py-2 text-lg font-semibold transition-colors duration-200 after:absolute after:inset-x-0 after:-bottom-0.5 after:h-px after:origin-center after:rounded-full after:bg-peach after:shadow-[0_0_12px_rgba(255,176,138,0.45)] after:transition-transform after:duration-200 ${ @@ -39,9 +39,7 @@ const DesktopNavigation = ({ const currentUrl = searchParams.get("url"); const policyHref = policy && `/attachment?url=${encodeURIComponent(policy)}`; - const registerActive = me?.pohId - ? pathname === `/${prettifyId(me.pohId)}` - : pathname.includes("/claim"); + const registerActive = isRegisterActive(me?.pohId, pathname); return (
diff --git a/src/app/Header/MobileMenu.tsx b/src/app/Header/MobileMenu.tsx index 186403d0..a3450496 100644 --- a/src/app/Header/MobileMenu.tsx +++ b/src/app/Header/MobileMenu.tsx @@ -6,7 +6,7 @@ import { Ref, forwardRef } from "react"; import Options from "./Options"; import RegisterLink from "./RegisterLink"; import WalletSection from "./WalletSection"; -import { prettifyId } from "utils/identifier"; +import { isRegisterActive } from "utils/identifier"; interface MobileMenuProps { policy: string; @@ -39,9 +39,7 @@ const MobileMenu = forwardRef( const currentUrl = searchParams.get("url"); const policyHref = policy && `/attachment?url=${encodeURIComponent(policy)}`; - const registerActive = me?.pohId - ? pathname === `/${prettifyId(me.pohId)}` - : pathname.includes("/claim"); + const registerActive = isRegisterActive(me?.pohId, pathname); return (
`https://${getExplorerUrl(chain.id)}/address/${address}`; -export const explorerTxLink = (txHash: string, chainId: number) => - `https://${getExplorerUrl(chainId)}/tx/${txHash}`; +export const explorerTxLink = (txHash: string, chain: SupportedChain) => + `https://${getExplorerUrl(chain.id)}/tx/${txHash}`; export const supportedChains = configSetSelection.chainSet === ChainSet.MAINNETS diff --git a/src/utils/identifier.ts b/src/utils/identifier.ts index b2453f49..eb6e309d 100644 --- a/src/utils/identifier.ts +++ b/src/utils/identifier.ts @@ -7,6 +7,11 @@ import { Hash, toBytes, zeroAddress } from "viem"; export const prettifyId = (id: Hash) => id?.slice(2).toUpperCase(); // base58.encode(hexToBytes(id)); +export const isRegisterActive = ( + pohId: Hash | null | undefined, + pathname: string, +) => (pohId ? pathname === `/${prettifyId(pohId)}` : pathname.includes("/claim")); + export const machinifyId = (s: string) => { const id = `0x${zeroAddress.concat(s.toLowerCase()).slice(-40)}` as Hash; // const id = `0x${base58.decode(s)}` as Hash; From b7a0d37ac313daf60866576b353acec95ea75841 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Thu, 9 Jul 2026 23:24:04 +0530 Subject: [PATCH 13/27] fix(revamp/1): align header, footer and pages on a shared 1400px container Header/footer inners and page content now share the same max-width and responsive gutters (kleros-v2 court / scout layout system), so all edges align at every viewport and content stays centered beyond 1400px. Removes the per-page viewport-width hacks in favor of .content. --- src/app/Footer.tsx | 46 +++--- src/app/Header/index.tsx | 132 +++++++++--------- .../[chain]/[request]/DegradedRequestPage.tsx | 2 +- .../[chain]/[request]/RequestErrorState.tsx | 2 +- .../[request]/RequestLoadingSkeleton.tsx | 2 +- src/app/[pohid]/[chain]/[request]/error.tsx | 2 +- src/app/[pohid]/[chain]/[request]/page.tsx | 6 +- src/app/attachment/page.tsx | 2 +- src/app/error.tsx | 2 +- src/app/globals.css | 13 +- 10 files changed, 109 insertions(+), 100 deletions(-) diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index 1ba02243..b62c99bd 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -25,29 +25,31 @@ const SOCIALS = [ ]; const Footer: React.FC = () => ( -
- - built by kleros - +
+
+ + built by kleros + -
- {SOCIALS.map((social) => ( - - {social.alt} - - ))} +
+ {SOCIALS.map((social) => ( + + {social.alt} + + ))} +
); diff --git a/src/app/Header/index.tsx b/src/app/Header/index.tsx index edcaa751..85ab1804 100644 --- a/src/app/Header/index.tsx +++ b/src/app/Header/index.tsx @@ -55,64 +55,77 @@ export default function Header({ policy }: IHeader) { }, [menuOpen]); return ( -
- - proof of humanity logo - +
+
+ + proof of humanity logo + -
- {showRewardsCta ? ( - + {showRewardsCta ? ( + + Rewards + + ) : showRegisterCta ? ( + + ) : null} + -
+ + +
- {chain && ( -
- + {chain && ( +
+ +
+ )} + +
+ {chain && ( +
+ +
+ )} +
+ +
- )} +
{menuOpen && chain && ( )} - -
- {chain && ( -
- -
- )} -
- -
-
); } diff --git a/src/app/[pohid]/[chain]/[request]/DegradedRequestPage.tsx b/src/app/[pohid]/[chain]/[request]/DegradedRequestPage.tsx index 04ba1891..65866314 100644 --- a/src/app/[pohid]/[chain]/[request]/DegradedRequestPage.tsx +++ b/src/app/[pohid]/[chain]/[request]/DegradedRequestPage.tsx @@ -29,7 +29,7 @@ export default async function DegradedRequestPage({ return ( <> {winnerClaim ? ( -
+
Latest verified identity for this PoH ID diff --git a/src/app/[pohid]/[chain]/[request]/RequestErrorState.tsx b/src/app/[pohid]/[chain]/[request]/RequestErrorState.tsx index df235431..cdd5b5e5 100644 --- a/src/app/[pohid]/[chain]/[request]/RequestErrorState.tsx +++ b/src/app/[pohid]/[chain]/[request]/RequestErrorState.tsx @@ -1,7 +1,7 @@ import RetryButton from "app/[pohid]/RetryButton"; const CardShell: React.FC<{ children: React.ReactNode }> = ({ children }) => ( -
+
{children}
diff --git a/src/app/[pohid]/[chain]/[request]/RequestLoadingSkeleton.tsx b/src/app/[pohid]/[chain]/[request]/RequestLoadingSkeleton.tsx index 245cd7e2..b0abb6a0 100644 --- a/src/app/[pohid]/[chain]/[request]/RequestLoadingSkeleton.tsx +++ b/src/app/[pohid]/[chain]/[request]/RequestLoadingSkeleton.tsx @@ -1,6 +1,6 @@ export default function RequestLoadingSkeleton() { return ( -
+
diff --git a/src/app/[pohid]/[chain]/[request]/error.tsx b/src/app/[pohid]/[chain]/[request]/error.tsx index 31d59f89..3196fdfd 100644 --- a/src/app/[pohid]/[chain]/[request]/error.tsx +++ b/src/app/[pohid]/[chain]/[request]/error.tsx @@ -14,7 +14,7 @@ export default function RequestError({ }, [error]); return ( -
+
! diff --git a/src/app/[pohid]/[chain]/[request]/page.tsx b/src/app/[pohid]/[chain]/[request]/page.tsx index 3280d690..672cd17c 100644 --- a/src/app/[pohid]/[chain]/[request]/page.tsx +++ b/src/app/[pohid]/[chain]/[request]/page.tsx @@ -117,7 +117,7 @@ export default async function Request({ params }: PageProps) { contractResult.reason, ); return ( -
+
<> -
+
-
+
{ const url = safeIpfsUrl(rawUrl); return ( -
+
{rawUrl && !url ? ( diff --git a/src/app/error.tsx b/src/app/error.tsx index ad39169d..a58b78b4 100644 --- a/src/app/error.tsx +++ b/src/app/error.tsx @@ -15,7 +15,7 @@ export default function Error({ }, [error]); return ( -
+
! diff --git a/src/app/globals.css b/src/app/globals.css index 77aa7dcd..e83bf9cc 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -101,12 +101,18 @@ @apply h-2 w-2 rounded-full; } - .content { - @apply mx-auto mb-16 mt-8 w-11/12 sm:mt-12 sm:w-5/6 lg:w-3/5; + /* Shared page rhythm (same system as kleros-v2 court / scout): header and + footer inners use .app-container; page containers use .content, whose + width-based gutters keep the same edges (1304px = 1400px - 2 * 48px) + while letting card pages keep their outer margin. Beyond 1400px the + content stops growing and stays centered. */ + .app-container { + @apply mx-auto w-full max-w-[1400px] px-4 md:px-8 lg:px-12; } + .content, .content-wide { - @apply mx-auto mb-16 mt-8 w-11/12 sm:mt-12 sm:w-5/6 lg:w-4/5; + @apply mx-auto mb-16 mt-8 w-[calc(100%-2rem)] max-w-[1304px] sm:mt-12 md:w-[calc(100%-4rem)] lg:w-[calc(100%-6rem)]; } .request-grid { @@ -841,7 +847,6 @@ box-shadow: 0 10px 24px rgba(255, 122, 95, 0.1); } - .slider-thumb::-webkit-slider-thumb { @apply bg-theme h-4 w-4 cursor-pointer appearance-none rounded-full; } From f0cc5bb40f8a4352de04dbf4f62b828bd3975383 Mon Sep 17 00:00:00 2001 From: madhurMongia Date: Fri, 10 Jul 2026 00:52:24 +0530 Subject: [PATCH 14/27] revamp(2/7): atoms & molecules per the POH NEW spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restyles the shared primitives — buttons, inputs, checkbox/radio/switch, dropdowns, generic modal, token badges, and the new CurrencyField atom — with spec hover/pressed states and icon-button treatments, and adopts them at all non-referral call sites. --- src/app/Footer.tsx | 25 ++- src/app/Header/EmailField.tsx | 14 +- src/app/Header/Options.tsx | 24 +-- src/app/Header/SettingsPopover.tsx | 11 +- src/app/Toastify.tsx | 15 +- src/app/[pohid]/[chain]/[request]/Appeal.tsx | 10 +- .../[pohid]/[chain]/[request]/Evidence.tsx | 27 +-- src/app/[pohid]/[chain]/[request]/Funding.tsx | 10 +- src/app/[pohid]/claim/Info.tsx | 5 +- src/app/[pohid]/claim/Review.tsx | 32 ++-- .../[pohid]/cross-chain/TransferSection.tsx | 6 +- .../cross-chain/UpdateStateSection.tsx | 6 +- src/app/error.tsx | 6 +- src/app/globals.css | 130 +++++++++++-- src/components/Accordion.tsx | 27 +-- src/components/ActionButton.tsx | 12 +- src/components/Attachment.tsx | 7 +- src/components/BulletedNumber.tsx | 2 +- src/components/Checklist.tsx | 2 +- src/components/CurrencyField.tsx | 60 ++++++ src/components/Dropdown/Item.tsx | 6 +- src/components/Dropdown/Menu.tsx | 43 +++-- src/components/ExternalLink.tsx | 6 +- src/components/Field.tsx | 53 ++++-- src/components/FileUploadZone.tsx | 64 +++++++ src/components/LoadableImage.tsx | 64 +++++++ src/components/Modal.tsx | 7 +- src/components/Popover.tsx | 2 +- src/components/Previewed.tsx | 71 ++++--- src/components/Request/Card.tsx | 5 +- src/components/Request/Grid.tsx | 7 +- src/components/SearchBar.tsx | 31 +++ src/components/SignInButton.tsx | 14 +- src/components/SubgraphsStatus.tsx | 180 +++++++++++++----- src/components/Switch.tsx | 43 +++++ src/components/VideoThumbnail.tsx | 42 +++- src/components/Webcam.tsx | 6 +- src/components/addLinkToText.tsx | 14 +- src/hooks/useDarkMode.ts | 34 +--- src/icons/CaretDown.svg | 3 + src/icons/EthToken.svg | 1 + src/icons/Notifications.svg | 4 + src/icons/SocialGitHub.svg | 3 + src/icons/SocialHelp.svg | 3 + src/icons/SocialSnapshot.svg | 3 + src/icons/SocialTelegram.svg | 3 + src/icons/SocialX.svg | 3 + src/icons/XdaiToken.svg | 6 + tailwind.config.cjs | 4 +- 49 files changed, 843 insertions(+), 313 deletions(-) create mode 100644 src/components/CurrencyField.tsx create mode 100644 src/components/FileUploadZone.tsx create mode 100644 src/components/LoadableImage.tsx create mode 100644 src/components/SearchBar.tsx create mode 100644 src/components/Switch.tsx create mode 100644 src/icons/CaretDown.svg create mode 100644 src/icons/EthToken.svg create mode 100644 src/icons/Notifications.svg create mode 100644 src/icons/SocialGitHub.svg create mode 100644 src/icons/SocialHelp.svg create mode 100644 src/icons/SocialSnapshot.svg create mode 100644 src/icons/SocialTelegram.svg create mode 100644 src/icons/SocialX.svg create mode 100644 src/icons/XdaiToken.svg diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index b62c99bd..b17b295b 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -1,28 +1,32 @@ import Image from "next/image"; import ExternalLink from "components/ExternalLink"; +import SocialGitHubIcon from "icons/SocialGitHub.svg"; +import SocialSnapshotIcon from "icons/SocialSnapshot.svg"; +import SocialTelegramIcon from "icons/SocialTelegram.svg"; +import SocialXIcon from "icons/SocialX.svg"; const SOCIALS = [ { alt: "snapshot", - src: "/logo/social-snapshot.svg", href: "https://snapshot.org/#/poh.eth/", + Icon: SocialSnapshotIcon, }, { alt: "github", - src: "/logo/social-github.svg", href: "https://github.com/proof-of-humanity", + Icon: SocialGitHubIcon, }, { alt: "x", - src: "/logo/social-x.svg", href: "https://twitter.com/proofofhumanity", + Icon: SocialXIcon, }, { alt: "telegram", - src: "/logo/social-telegram.svg", href: "https://t.me/proofhumanity", + Icon: SocialTelegramIcon, }, -]; +] as const; const Footer: React.FC = () => (
@@ -40,13 +44,14 @@ const Footer: React.FC = () => (
- {SOCIALS.map((social) => ( + {SOCIALS.map(({ alt, href, Icon }) => ( - {social.alt} + ))}
diff --git a/src/app/Header/EmailField.tsx b/src/app/Header/EmailField.tsx index f8718284..56bf5de1 100644 --- a/src/app/Header/EmailField.tsx +++ b/src/app/Header/EmailField.tsx @@ -1,4 +1,5 @@ import React from "react"; +import cn from "classnames"; interface EmailFieldProps { value: string; @@ -24,15 +25,16 @@ const EmailField: React.FC = ({ onChange={(e) => onChange(e.target.value)} placeholder="Email" autoFocus={autoFocus} - className={`bg-whiteBackgroundWithOpacity text-primaryText placeholder:text-secondaryText min-h-[44px] w-full rounded-sm border px-4 py-2 text-center text-base font-medium transition-colors duration-200 focus:outline-none focus:ring-0 ${ - isInvalid - ? "border-red-500 focus:border-red-600" - : "border-stroke focus:border-stroke" - }`} + className={cn( + "flat-control text-primaryText placeholder:text-secondaryText min-h-12 w-full rounded-input px-4 py-2 text-center text-base font-medium transition-colors duration-200 focus:outline-none focus:ring-0", + isInvalid && "flat-control-error", + )} /> {isInvalid && ( -

Please enter a valid email

+

+ Please enter a valid email +

)} ); diff --git a/src/app/Header/Options.tsx b/src/app/Header/Options.tsx index c0c9f689..859e4a61 100644 --- a/src/app/Header/Options.tsx +++ b/src/app/Header/Options.tsx @@ -1,7 +1,8 @@ -import Image from "next/image"; import React from "react"; import ExternalLink from "components/ExternalLink"; import Popover from "components/Popover"; +import SocialHelpIcon from "icons/SocialHelp.svg"; +import SocialSnapshotIcon from "icons/SocialSnapshot.svg"; import SettingsPopover from "./SettingsPopover"; const Options: React.FC = () => ( @@ -9,29 +10,20 @@ const Options: React.FC = () => ( - snapshot + - help + } > @@ -55,7 +47,7 @@ const Options: React.FC = () => ( Tutorial - Crypto Beginner's Guide + Crypto Beginner's Guide FAQ diff --git a/src/app/Header/SettingsPopover.tsx b/src/app/Header/SettingsPopover.tsx index b3bafb61..c43352c8 100644 --- a/src/app/Header/SettingsPopover.tsx +++ b/src/app/Header/SettingsPopover.tsx @@ -1,8 +1,8 @@ import React from "react"; -import Image from "next/image"; import Popover from "components/Popover"; import ActionButton from "components/ActionButton"; import SignInButton from "components/SignInButton"; +import NotificationsIcon from "icons/Notifications.svg"; import EmailField from "./EmailField"; import EmailVerificationNotice from "./EmailVerificationNotice"; import UnsubscribeModal from "./UnsubscribeModal"; @@ -44,15 +44,10 @@ const SettingsPopover: React.FC = () => {
- = ({ {(externalDisabled || isReconciling) && ( - + {externalDisabled ? (externalTooltip ?? "Disabled") : "Syncing"} - )}
diff --git a/src/app/[pohid]/[chain]/[request]/Evidence.tsx b/src/app/[pohid]/[chain]/[request]/Evidence.tsx index a97ddd12..8a26d945 100644 --- a/src/app/[pohid]/[chain]/[request]/Evidence.tsx +++ b/src/app/[pohid]/[chain]/[request]/Evidence.tsx @@ -10,7 +10,7 @@ import Identicon from "components/Identicon"; import Label from "components/Label"; import Modal from "components/Modal"; import TimeAgo from "components/TimeAgo"; -import Uploader from "components/Uploader"; +import FileUploadZone from "components/FileUploadZone"; import { explorerLink, idToChain } from "config/chains"; import { Effects } from "contracts/hooks/types"; import usePoHWrite from "contracts/hooks/usePoHWrite"; @@ -299,11 +299,10 @@ export default function Evidence({ label="Add Evidence" /> {(isReconciling || isEvidenceDisabled) && ( - + {isReconciling ? "Syncing" : `Switch your chain above to ${idToChain(chainReq.id)?.name || "the correct chain"}`} - )}
@@ -345,20 +344,14 @@ export default function Evidence({ onChange={(e) => setDescription(e.target.value)} /> -
- { - const acceptedFile = acceptedFiles[0]; - if (acceptedFile) setFile(acceptedFile); - }} - > - {file - ? file?.name - : "Drag 'n drop some files here, or click to select files"} - -
+ { + const acceptedFile = acceptedFiles[0]; + if (acceptedFile) setFile(acceptedFile); + }} + /> = ({ {chain.nativeCurrency.symbol} Needed
- = ({ className="w-auto" /> {getTooltipMessage() && ( - + {getTooltipMessage()} - )}
diff --git a/src/app/[pohid]/claim/Info.tsx b/src/app/[pohid]/claim/Info.tsx index 068c6a23..8bceb3e5 100644 --- a/src/app/[pohid]/claim/Info.tsx +++ b/src/app/[pohid]/claim/Info.tsx @@ -62,10 +62,9 @@ function Info({ advance, state$, email$, isRenewal }: InfoProps) { placeholder="get notified about your profile request" value={email} onChange={(e) => email$.set(e.target.value)} + status={showEmailError ? "error" : undefined} + message={showEmailError ? "Please enter a valid email" : undefined} /> - {showEmailError && ( -

Please enter a valid email

- )}
If you don't fund the deposit now, PoH supporters can cover it diff --git a/src/app/[pohid]/cross-chain/TransferSection.tsx b/src/app/[pohid]/cross-chain/TransferSection.tsx index 6963768e..0709b98a 100644 --- a/src/app/[pohid]/cross-chain/TransferSection.tsx +++ b/src/app/[pohid]/cross-chain/TransferSection.tsx @@ -130,9 +130,8 @@ export default function TransferSection({ - + {WAITING_FOR_INDEXER_TOOLTIP} -
); @@ -157,9 +156,8 @@ export default function TransferSection({ Transfer {isReconciling ? ( - + {WAITING_FOR_INDEXER_TOOLTIP} - ) : null}
diff --git a/src/app/[pohid]/cross-chain/UpdateStateSection.tsx b/src/app/[pohid]/cross-chain/UpdateStateSection.tsx index 00f486df..2565f6e8 100644 --- a/src/app/[pohid]/cross-chain/UpdateStateSection.tsx +++ b/src/app/[pohid]/cross-chain/UpdateStateSection.tsx @@ -124,9 +124,8 @@ export default function UpdateStateSection({ - + {WAITING_FOR_INDEXER_TOOLTIP} -
); @@ -143,9 +142,8 @@ export default function UpdateStateSection({ Update state {isReconciling ? ( - + {WAITING_FOR_INDEXER_TOOLTIP} - ) : null}
diff --git a/src/app/error.tsx b/src/app/error.tsx index a58b78b4..31577ea3 100644 --- a/src/app/error.tsx +++ b/src/app/error.tsx @@ -15,8 +15,8 @@ export default function Error({ }, [error]); return ( -
-
+
+
!
@@ -30,7 +30,7 @@ export default function Error({
- {open && children} + {title} + + + + + {open &&
{children}
}
); }; diff --git a/src/components/ActionButton.tsx b/src/components/ActionButton.tsx index 46e9d9ae..4c675f33 100644 --- a/src/components/ActionButton.tsx +++ b/src/components/ActionButton.tsx @@ -19,14 +19,11 @@ export interface ActionButtonProps { } const buttonStyles = { - primary: - "flex items-center justify-center gradient rounded-sm font-medium text-white", - secondary: - "flex items-center justify-center border-2 border-theme text-orange rounded-sm font-semibold", + primary: "btn-primary", + secondary: "btn-secondary", }; -const buttonBaseClass = - "w-full md:w-auto normal-case disabled:opacity-50 disabled:cursor-not-allowed px-5 py-2"; +const buttonBaseClass = "disabled:cursor-not-allowed"; const ActionButton = React.forwardRef( ( @@ -87,9 +84,8 @@ const ActionButton = React.forwardRef( return (
{button} - + {tooltip} -
); diff --git a/src/components/Attachment.tsx b/src/components/Attachment.tsx index a30d8499..0fb2ac90 100644 --- a/src/components/Attachment.tsx +++ b/src/components/Attachment.tsx @@ -11,8 +11,11 @@ const Attachment: React.FC = ({ uri }) => { if (!uri) return null; return ( - - + + ); }; diff --git a/src/components/BulletedNumber.tsx b/src/components/BulletedNumber.tsx index 659db219..991ab327 100644 --- a/src/components/BulletedNumber.tsx +++ b/src/components/BulletedNumber.tsx @@ -18,7 +18,7 @@ const BulletedNumber: React.FC = ({
) : ( -
+
{number} diff --git a/src/components/Checklist.tsx b/src/components/Checklist.tsx index 692a7bf4..cb6ec593 100644 --- a/src/components/Checklist.tsx +++ b/src/components/Checklist.tsx @@ -15,7 +15,7 @@ interface ChecklistProps { const Checklist: React.FC = ({ title, items, warning }) => { return ( -
+

{title}

diff --git a/src/components/CurrencyField.tsx b/src/components/CurrencyField.tsx new file mode 100644 index 00000000..022a3576 --- /dev/null +++ b/src/components/CurrencyField.tsx @@ -0,0 +1,60 @@ +import cn from "classnames"; +import { InputHTMLAttributes, ReactNode } from "react"; +import CaretDownIcon from "icons/CaretDown.svg"; +import XdaiTokenIcon from "icons/XdaiToken.svg"; +import EthTokenIcon from "icons/EthToken.svg"; +import Label from "./Label"; + +type CurrencyFieldProps = InputHTMLAttributes & { + label?: ReactNode; + /** Native currency symbol deciding the token icon, e.g. "ETH" or "xDAI". */ + symbol?: string; + /** When set, the token becomes a selector with a caret. */ + onTokenClick?: () => void; +}; + +const tokenIcon = (symbol?: string) => + /dai/i.test(symbol ?? "") ? ( + + ) : ( + + ); + +function CurrencyField({ + label, + symbol, + onTokenClick, + className, + ...props +}: CurrencyFieldProps) { + return ( +
+ {label && } +
+ + {onTokenClick ? ( + + ) : ( + tokenIcon(symbol) + )} +
+
+ ); +} + +export default CurrencyField; diff --git a/src/components/Dropdown/Item.tsx b/src/components/Dropdown/Item.tsx index 7fd47ded..2cdb678d 100644 --- a/src/components/Dropdown/Item.tsx +++ b/src/components/Dropdown/Item.tsx @@ -15,8 +15,10 @@ const DropdownItem: React.FC = ({ }) => ( diff --git a/src/components/Dropdown/Menu.tsx b/src/components/Dropdown/Menu.tsx index 84da1178..79144394 100644 --- a/src/components/Dropdown/Menu.tsx +++ b/src/components/Dropdown/Menu.tsx @@ -1,22 +1,39 @@ +"use client"; + +import { useState } from "react"; import Popover from "components/Popover"; +import CaretDownIcon from "icons/CaretDown.svg"; +import cn from "classnames"; interface DropdownProps { title: string; children: React.ReactNode; } -const Dropdown: React.FC = ({ title, children }) => ( - - {title} - - } - > -
- {children} -
-
-); +const Dropdown: React.FC = ({ title, children }) => { + const [open, setOpen] = useState(false); + + return ( + setOpen(true)} + onClose={() => setOpen(false)} + trigger={ + + } + > +
+ {children} +
+
+ ); +}; export default Dropdown; diff --git a/src/components/ExternalLink.tsx b/src/components/ExternalLink.tsx index faa67a32..c19bc95d 100644 --- a/src/components/ExternalLink.tsx +++ b/src/components/ExternalLink.tsx @@ -1,7 +1,11 @@ import Link, { LinkProps } from "next/link"; const ExternalLink: React.FC< - LinkProps & { className?: string; children: React.ReactNode } + LinkProps & + React.AnchorHTMLAttributes & { + className?: string; + children: React.ReactNode; + } > = ({ children, className, ...props }) => ( & InputHTMLAttributes & { textarea?: boolean; label?: ReactNode; + status?: FieldStatus; + message?: ReactNode; }; -function Field({ label, textarea = false, className, ...props }: FieldProps) { - const [focused, setFocused] = useState(false); +const statusControl: Record = { + success: "flat-control-success", + warning: "flat-control-warning", + error: "flat-control-error", +}; + +const statusMessage: Record = { + success: "text-status-registered", + warning: "text-status-challenged", + error: "text-status-rejected", +}; +function Field({ + label, + textarea = false, + status, + message, + className, + ...props +}: FieldProps) { return (
{label && }
{textarea ? (