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
83 changes: 83 additions & 0 deletions app/glossary-demo/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { GlossaryTerm } from "@/components/ui/glossary-term"
import { getAllGlossaryTerms } from "@/data/glossary"

export const metadata = {
title: "Glossary Demo - PSE",
description: "Technical terms glossary with hover tooltips",
}

export default function GlossaryDemoPage() {
const allTerms = getAllGlossaryTerms()

// Group terms by category
const termsByCategory = allTerms.reduce((acc, term) => {
const category = term.category || "Other"
if (!acc[category]) acc[category] = []
acc[category].push(term)
return acc
}, {} as Record<string, typeof allTerms>)

return (
<div className="min-h-screen bg-white dark:bg-anakiwa-975 py-16 px-4">
<div className="max-w-3xl mx-auto">
<h1 className="text-3xl font-bold text-tuatara-950 dark:text-white mb-4">
Glossary Demo
</h1>
<p className="text-tuatara-600 dark:text-tuatara-300 mb-8">
Hover over the underlined terms to see their definitions.
</p>

{/* Example paragraph with glossary terms */}
<div className="bg-tuatara-50 dark:bg-anakiwa-950 rounded-lg p-6 mb-12">
<h2 className="text-xl font-semibold text-tuatara-900 dark:text-white mb-4">
Example Usage
</h2>
<p className="text-tuatara-700 dark:text-tuatara-200 leading-relaxed">
<GlossaryTerm term="pse">PSE</GlossaryTerm> is focused on building
privacy-preserving tools using technologies like{" "}
<GlossaryTerm term="zero-knowledge">zero-knowledge proofs</GlossaryTerm>.
Projects like <GlossaryTerm term="semaphore">Semaphore</GlossaryTerm> and{" "}
<GlossaryTerm term="bandada">Bandada</GlossaryTerm> enable anonymous
group membership, while <GlossaryTerm term="tlsn">TLSNotary</GlossaryTerm>{" "}
provides data verification without revealing everything.
</p>
<p className="text-tuatara-700 dark:text-tuatara-200 leading-relaxed mt-4">
Privacy networks like <GlossaryTerm term="tor">Tor</GlossaryTerm> protect
users when making <GlossaryTerm term="rpc">RPC</GlossaryTerm> calls to
blockchain nodes. Advanced cryptographic techniques like{" "}
<GlossaryTerm term="fhe">FHE</GlossaryTerm> and{" "}
<GlossaryTerm term="mpc">MPC</GlossaryTerm> enable computation on
encrypted data.
</p>
</div>

{/* Full glossary list */}
<h2 className="text-2xl font-bold text-tuatara-950 dark:text-white mb-6">
All Terms
</h2>

{Object.entries(termsByCategory).map(([category, terms]) => (
<div key={category} className="mb-8">
<h3 className="text-lg font-semibold text-anakiwa-600 dark:text-anakiwa-400 mb-3">
{category}
</h3>
<div className="grid gap-2">
{terms.map((entry) => (
<div
key={entry.term}
className="flex items-start gap-2 p-3 rounded-lg bg-tuatara-50 dark:bg-anakiwa-950"
>
<GlossaryTerm term={entry.term.toLowerCase().replace(/\s+/g, "-")}>
<span className="font-medium text-tuatara-900 dark:text-white">
{entry.term}
</span>
</GlossaryTerm>
</div>
))}
</div>
</div>
))}
</div>
</div>
)
}
3 changes: 0 additions & 3 deletions components/site-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,6 @@ export function SiteFooter() {
</AppLink>
</LinksWrapper>
<LinksWrapper>
<AppLink href={siteConfig.links.discord} external variant="button">
<ItemLabel label="Feedback" />
</AppLink>
<AppLink
href={siteConfig.links.privacyPolicy}
external
Expand Down
89 changes: 89 additions & 0 deletions components/ui/glossary-term.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use client"

import { useState } from "react"
import { findGlossaryTerm, GlossaryEntry } from "@/data/glossary"
import { cn } from "@/lib/utils"

interface GlossaryTermProps {
/** The term to look up in the glossary */
term: string
/** Optional: custom text to display (defaults to the term) */
children?: React.ReactNode
/** Optional: custom definition (overrides glossary lookup) */
definition?: string
/** Optional: additional CSS classes */
className?: string
}

export function GlossaryTerm({
term,
children,
definition: customDefinition,
className,
}: GlossaryTermProps) {
const [isVisible, setIsVisible] = useState(false)

// Look up term in glossary
const glossaryEntry = findGlossaryTerm(term)
const definition = customDefinition || glossaryEntry?.definition
const displayTerm = glossaryEntry?.term || term

// If no definition found, just render the text without tooltip
if (!definition) {
return <span className={className}>{children || term}</span>
}

return (
<span
className={cn("relative inline-block", className)}
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
>
{/* The term with dotted underline to indicate it's interactive */}
<span className="border-b border-dotted border-anakiwa-500 dark:border-anakiwa-400 cursor-help">
{children || term}
</span>

{/* Tooltip popup */}
{isVisible && (
<span
role="tooltip"
className={cn(
"absolute z-50 bottom-full left-1/2 -translate-x-1/2 mb-2",
"w-64 p-3 rounded-lg shadow-lg",
"bg-white dark:bg-anakiwa-950",
"border border-tuatara-200 dark:border-anakiwa-800",
"text-sm text-tuatara-700 dark:text-tuatara-200",
"animate-in fade-in-0 zoom-in-95 duration-200"
)}
>
{/* Arrow */}
<span
className={cn(
"absolute top-full left-1/2 -translate-x-1/2",
"border-8 border-transparent border-t-white dark:border-t-anakiwa-950",
"drop-shadow-sm"
)}
/>

{/* Term title */}
<span className="block font-semibold text-tuatara-900 dark:text-white mb-1">
{displayTerm}
</span>

{/* Category badge */}
{glossaryEntry?.category && (
<span className="inline-block px-2 py-0.5 mb-2 text-xs rounded-full bg-anakiwa-100 dark:bg-anakiwa-900 text-anakiwa-700 dark:text-anakiwa-300">
{glossaryEntry.category}
</span>
)}

{/* Definition */}
<span className="block leading-relaxed">
{definition}
</span>
</span>
)}
</span>
)
}
4 changes: 2 additions & 2 deletions config/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export const siteConfig = {
twitter: "https://x.com/PrivacyEthereum",
github: "https://github.com/privacy-ethereum",
docs: "https://ui.shadcn.com",
discord: "https://discord.com/invite/sF5CT5rzrR",
discord: "https://discord.gg/5vv7bk5u5y",
articles: "https://pse.dev/blog",
youtube: "https://www.youtube.com/@PrivacyEthereum",
jobs: "https://jobs.lever.co/ethereumfoundation/?department=Ethereum%20Foundation&team=Privacy%20and%20Scaling%20Explorations",
jobs: "https://jobs.ashbyhq.com/ethereum-foundation",
termOfUse: "https://ethereum.org/en/terms-of-use/",
privacyPolicy: "https://ethereum.org/en/privacy-policy/",
activity:
Expand Down
Loading