Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/CRISP/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
/>
<meta name="theme-color" content="#ffffff" />
<link rel="manifest" href="/manifest.json" />

<!-- Editorial design system fonts (Interfold re-skin) -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&family=JetBrains+Mono:wght@400;500;600&display=swap"
rel="stylesheet"
/>
</head>
<body class="overflow-hidden">
<div id="root"></div>
Expand Down
16 changes: 2 additions & 14 deletions examples/CRISP/client/src/components/Cards/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,8 @@ const Card: React.FC<CardProps> = ({ children, isActive, isDetails, checked, onC
return (
<div
data-test-id='card'
className={`
h-full w-full
cursor-pointer
${isDetails ? ' p-4' : 'min-h-[144px] p-10 md:min-h-[288px] md:p-20'}
rounded-[24px] bg-white text-black
${!isDetails && 'shadow-md'}
transform
border-2 transition-all duration-300 ease-in-out
${derivedIsClicked ? 'scale-105 border-lime-400' : ''}
${derivedIsClicked ? 'border-lime-400' : 'border-slate-600/20'}
${derivedIsClicked ? 'bg-white' : 'bg-slate-100'}
${!isDetails && 'hover:border-lime-300 hover:bg-white hover:shadow-lg'}
flex w-full items-center justify-center
`}
className={`faceoff-slot ${derivedIsClicked ? 'selected' : ''}`}
style={{ aspectRatio: '1 / 1', cursor: isDetails ? 'default' : 'pointer', minHeight: isDetails ? 96 : 144 }}
onClick={handleClick}
>
{children}
Expand Down
2 changes: 1 addition & 1 deletion examples/CRISP/client/src/components/Cards/CardContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface CardContentProps {

const CardContent: React.FC<CardContentProps> = ({ children }) => {
return (
<div className='z-50 w-full max-w-screen-md space-y-10 rounded-2xl border-2 border-slate-600/20 bg-white p-8 shadow-2xl md:p-12'>
<div className='card col' style={{ width: '100%', maxWidth: 720, gap: 28, padding: 32 }}>
{children}
</div>
)
Expand Down
39 changes: 23 additions & 16 deletions examples/CRISP/client/src/components/Cards/PollCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,34 @@ const PollCard: React.FC<PollResult> = ({ roundId, options, totalVotes, date, en
}

return (
<div
className='relative flex min-h-[248px] w-full cursor-pointer flex-col items-center justify-center space-y-4 rounded-3xl border-2 border-slate-600/20 bg-white/50 p-8 pt-2 shadow-lg md:max-w-[274px] hover:border-slate-600/40 transition-colors'
<button
type='button'
className='card col'
style={{
width: '100%',
maxWidth: 300,
gap: 16,
cursor: 'pointer',
alignItems: 'center',
background: 'transparent',
border: 'none',
textAlign: 'inherit',
font: 'inherit',
}}
onClick={handleNavigation}
>
<div className='external-icon absolute right-4 top-4' />
<div className='text-xs font-bold text-slate-600'>{formatDate(date)}</div>
<div className='flex space-x-8 '>
<PollCardResult results={results} totalVotes={displayVoteCount} isActive={isActive} />
<div className='between' style={{ width: '100%' }}>
<span className='mono-sm muted'>{formatDate(date)}</span>
<span className='linkish' style={{ border: 'none', padding: 0 }}>
View →
</span>
</div>
{isActive && (
<div
className={`flex items-center space-x-2 rounded-lg border-2 ${isCurrentRound ? 'border-lime-600/80 bg-lime-400' : 'border-blue-600/80 bg-blue-400'} px-2 py-1 text-center font-bold uppercase leading-none text-white`}
>
<div className='h-1.5 w-1.5 animate-pulse rounded-full bg-white'></div>
<div>{isCurrentRound ? 'Live' : 'Active'}</div>
</div>
)}
<div className='absolute bottom-[-1rem] left-1/2 -translate-x-1/2 transform '>
<PollCardResult results={results} totalVotes={displayVoteCount} isActive={isActive} />
<div className='row' style={{ gap: 8, justifyContent: 'center' }}>
{isActive && <span className={`tag dot ${isCurrentRound ? 'live' : 'tally'}`}>{isCurrentRound ? 'Live' : 'Active'}</span>}
<VotesBadge totalVotes={displayVoteCount} />
</div>
</div>
</button>
)
}

Expand Down
45 changes: 26 additions & 19 deletions examples/CRISP/client/src/components/Cards/PollCardResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,42 @@ const PollCardResult: React.FC<PollCardResultProps> = ({ isResult, results, tota
}

return (
<div className={`grid ${isResult ? 'sm:w-full md:w-1/3' : 'w-full'} z-50 grid-cols-2 gap-4 md:gap-8`}>
<div
className='grid'
style={{ gridTemplateColumns: '1fr 1fr', gap: isResult ? 24 : 16, width: '100%', maxWidth: isResult ? 420 : undefined }}
>
{results.map((poll) => (
<div data-test-id={`poll-result-${poll.value}`} className='col-span-1 w-full' key={`${poll.label}-${poll.value}`}>
<div
className={`flex w-full flex-col items-center justify-center ${isResult ? 'aspect-square space-y-6 max-sm:space-y-2' : 'space-y-4'}`}
>
<div data-test-id={`poll-result-${poll.value}`} key={`${poll.label}-${poll.value}`}>
<div className='col' style={{ alignItems: 'center', gap: isResult ? 16 : 10 }}>
<Card isDetails checked={totalVotes === 0 ? false : poll.checked} isActive={isActive}>
<p className={isResult ? 'text-8xl max-sm:p-5 max-sm:text-6xl' : 'text-5xl'}>{poll.label}</p>
<span className='faceoff-emoji' style={{ fontSize: isResult ? undefined : 40 }}>
{poll.label}
</span>
</Card>

{isActive && isResult && (
<div className={isResult ? 'space-y-2 ' : ''}>
<div className='flex w-full items-center justify-center space-x-1 rounded-lg border-2 border-slate-600/20 bg-white p-2 py-1 font-bold uppercase shadow-md'>
<ShieldSlash weight='bold' size={24} className='text-slate-800/50' />
<div className={`text-center text-sm font-bold uppercase text-slate-800/50 `}>vote encrypted</div>
</div>
<p className={` text-center text-sm font-extrabold uppercase text-slate-600/50 max-sm:text-xs`}>revealed when poll ends</p>
<div className='col' style={{ alignItems: 'center', gap: 6 }}>
<span className='tag dot'>
<ShieldSlash weight='bold' size={14} />
vote encrypted
</span>
<span className='mono-sm muted'>revealed when poll ends</span>
</div>
)}
{!isActive && (
<div className={isResult ? 'space-y-2 max-sm:space-y-0' : ''}>
<h3
className={`text-center ${isResult ? 'text-h1' : 'text-h3'} font-bold ${totalVotes > 0 && poll.checked ? 'text-lime-400' : 'text-slate-600/50'}`}
<div className='col' style={{ alignItems: 'center', gap: 2 }}>
<div
className={isResult ? 'display' : 'h2'}
style={{
fontSize: isResult ? 'clamp(40px, 8vw, 80px)' : undefined,
color: totalVotes > 0 && poll.checked ? 'var(--accent)' : 'var(--ink-soft)',
}}
>
{totalVotes ? calculatePercentage(poll.votes) : 0}%
</h3>
<p className={`text-center ${isResult ? 'text-2xl font-semibold' : 'text-xs font-bold'} text-slate-600/50`}>
{poll.votes} votes
</p>
</div>
<span className='cap'>
{poll.votes} {poll.votes === 1 ? 'vote' : 'votes'}
</span>
</div>
)}
</div>
Expand Down
64 changes: 31 additions & 33 deletions examples/CRISP/client/src/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,42 @@

import React from 'react'
import GnosisGuildLogo from '@/assets/icons/gg.svg'
import { Link } from 'react-router-dom'
import { CastleTurret, GithubLogo, TelegramLogo, TwitterLogo } from '@phosphor-icons/react'

const Footer: React.FC = () => {
return (
<footer className='relative z-10 flex w-full border-t-2 border-slate-600/20 bg-slate-200 p-6'>
<div className='mx-auto flex w-full max-w-screen-xl items-center justify-start gap-3 md:flex-row'>
<Link to='https://github.com/gnosisguild/enclave' target='_blank'>
<GithubLogo size={24} />
</Link>
<Link to='https://x.com/EnclaveE3' target='_blank'>
<TwitterLogo size={24} />
</Link>
<Link to='https://t.me/enclave_e3' target='_blank'>
<TelegramLogo size={24} />
</Link>
<Link to='https://warpcast.com/enclavee3' target='_blank'>
<CastleTurret size={24} />
</Link>
</div>
<div className='mx-auto flex w-full max-w-screen-xl flex-col items-center justify-end gap-1 md:flex-row'>
<div className='flex items-center gap-1'>
<p className='text-sm'>Secured with</p>
<Link to='https://enclave.gg' target='_blank'>
<p className='font-serif font-bold'>Enclave</p>
</Link>
<div className='crisp-editorial' data-palette='interfold' data-mode='light' data-density='comfortable'>
<footer className='footer'>
<span>© 2026 — Crisp Protocol</span>
<span className='muted'>Secret-ballot voting with FHE + threshold MPC</span>
<div className='links' style={{ alignItems: 'center' }}>
<a href='https://github.com/gnosisguild/enclave' target='_blank' rel='noopener noreferrer' aria-label='GitHub'>
<GithubLogo size={18} />
</a>
<a href='https://x.com/EnclaveE3' target='_blank' rel='noopener noreferrer' aria-label='X'>
<TwitterLogo size={18} />
</a>
<a href='https://t.me/enclave_e3' target='_blank' rel='noopener noreferrer' aria-label='Telegram'>
<TelegramLogo size={18} />
</a>
<a href='https://warpcast.com/enclavee3' target='_blank' rel='noopener noreferrer' aria-label='Farcaster'>
<CastleTurret size={18} />
</a>
<a href='https://theinterfold.com' target='_blank' rel='noopener noreferrer'>
Secured with The Interfold
</a>
<a
href='https://www.gnosisguild.org/'
target='_blank'
rel='noopener noreferrer'
style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}
>
Gnosis Guild
<img src={GnosisGuildLogo} className='h-4 w-4' alt='Gnosis Guild' />
</a>
</div>
<div className='flex items-center gap-1'>
<p className='text-sm'>built by</p>
<div className='flex items-center gap-1 duration-300 ease-in-out hover:opacity-70'>
<Link to='https://www.gnosisguild.org/' target='_blank' className='flex items-center gap-2 md:flex-row'>
<p className='text-sm font-bold'>Gnosis Guild</p>
<img src={GnosisGuildLogo} className='h-6 w-6' />
</Link>
</div>
</div>
</div>
</footer>
</footer>
</div>
)
}

Expand Down
57 changes: 25 additions & 32 deletions examples/CRISP/client/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
// or FITNESS FOR A PARTICULAR PURPOSE.

import React from 'react'
import Logo from '@/assets/icons/logo.svg'
import { Link } from 'react-router-dom'
import NavMenu from '@/components/NavMenu'
import { ConnectKitButton } from 'connectkit'
import useToken from '@/hooks/generic/useMintToken'

const PAGES = [
{
label: 'Live Poll',
path: '/current',
},
{
label: 'About',
path: '/about',
Expand All @@ -26,40 +29,30 @@ const Navbar: React.FC = () => {
const { mintTokens, isMinting } = useToken()

return (
<nav className='absolute left-0 top-0 z-10 w-screen px-6 lg:px-9'>
<div className='mx-auto max-w-screen-xl'>
<div className='flex h-20 items-center justify-between'>
<Link
to={'/'}
className='hover:text-twilight-blue-600 cursor-pointer font-bold text-slate-600 duration-300 ease-in-out hover:opacity-70'
>
<img src={Logo} alt='CRISP Logo' className='h-6 cursor-pointer duration-300 ease-in-out hover:opacity-70 md:h-8' />
</Link>
<div className='crisp-editorial' data-palette='interfold' data-mode='light' data-density='comfortable'>
<header className='topbar'>
<Link to={'/'} className='brand' style={{ cursor: 'pointer' }}>
<span className='glyph' />
<span style={{ fontWeight: 500 }}>Crisp</span>
</Link>

<div className='flex items-center gap-2 md:gap-8'>
<button
disabled={isMinting}
onClick={mintTokens}
className='hover:text-twilight-blue-600 cursor-pointer font-bold text-slate-600 duration-300 ease-in-out hover:opacity-70 max-md:hidden'
>
Mint tokens
</button>
<nav className='topnav max-md:hidden'>
{PAGES.map(({ label, path }) => (
<Link key={label} to={path}>
{label}
</Link>
))}
</nav>

{PAGES.map(({ label, path }) => (
<Link
key={label}
to={path}
className='hover:text-twilight-blue-600 cursor-pointer font-bold text-slate-600 duration-300 ease-in-out hover:opacity-70 max-md:hidden'
>
{label}
</Link>
))}
<ConnectKitButton />
<NavMenu />
</div>
<div className='topbar-right'>
<button disabled={isMinting} onClick={mintTokens} className='pill-mint max-md:hidden'>
+ Mint test tokens
</button>
<ConnectKitButton />
<NavMenu />
</div>
</div>
</nav>
</header>
</div>
)
}

Expand Down
8 changes: 3 additions & 5 deletions examples/CRISP/client/src/components/VotesBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ type VotesBadgeProps = {

const VotesBadge: React.FC<VotesBadgeProps> = ({ totalVotes }) => {
return (
<div
className={`w-fit rounded-lg border-2 border-slate-600/20 bg-white p-2 py-1 text-center font-bold uppercase text-slate-800/50 shadow-md`}
>
{totalVotes} votes
</div>
<span className='tag'>
{totalVotes} {totalVotes === 1 ? 'vote' : 'votes'}
</span>
)
}

Expand Down
Loading
Loading