forked from CredenceOrg/Credence-Frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTierLadder.tsx
More file actions
114 lines (100 loc) · 3.66 KB
/
Copy pathTierLadder.tsx
File metadata and controls
114 lines (100 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { useId, useState } from 'react'
import Badge, { type BadgeVariant } from './Badge'
import './TierLadder.css'
import { type TrustTier, TIERS, TIER_ORDER } from '../lib/tiers'
export type TierId = TrustTier
export interface TierDefinition {
id: TierId
label: string
scoreMin: number
scoreMax: number | null
benefits: string[]
}
/** Protocol tier ladder built from the canonical TIERS source */
export const TIER_LADDER: TierDefinition[] = TIER_ORDER.map((id) => {
const t = TIERS[id]
return {
id: t.id,
label: t.label,
scoreMin: t.min,
scoreMax: t.max,
benefits: t.benefits,
}
})
function formatThreshold(tier: TierDefinition): string {
if (tier.scoreMax === null) {
return `${tier.scoreMin}+`
}
return `${tier.scoreMin}–${tier.scoreMax}`
}
interface TierLadderProps {
className?: string
defaultOpen?: boolean
}
export default function TierLadder({ className = '', defaultOpen = false }: TierLadderProps) {
const [isOpen, setIsOpen] = useState(defaultOpen)
const panelId = useId()
const headingId = useId()
return (
<section className={`tier-ladder ${className}`.trim()} aria-labelledby={headingId}>
<h2 id={headingId} className="sr-only">
How trust is earned
</h2>
<button
type="button"
className="tier-ladder__trigger"
aria-expanded={isOpen}
aria-controls={panelId}
onClick={() => setIsOpen((open) => !open)}
>
<span className="tier-ladder__trigger-label">How trust is earned</span>
<span className="tier-ladder__trigger-hint">Tier thresholds and benefits</span>
<svg
className={`tier-ladder__chevron${isOpen ? ' tier-ladder__chevron--open' : ''}`}
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
<div id={panelId} className="tier-ladder__panel" hidden={!isOpen}>
<p className="tier-ladder__intro">
Your trust score (0–1000) is computed from bond amount, bond duration, and attestations.
Tiers unlock as your score crosses each threshold at epoch settlement.
</p>
<ol className="tier-ladder__list">
{TIER_LADDER.map((tier, index) => (
<li key={tier.id} className={`tier-ladder__step tier-ladder__step--${tier.id}`}>
<div className="tier-ladder__rail" aria-hidden="true">
<span className="tier-ladder__marker">{index + 1}</span>
{index < TIER_LADDER.length - 1 && <span className="tier-ladder__connector" />}
</div>
<article className="tier-ladder__card">
<header className="tier-ladder__card-header">
<Badge variant={tier.id as BadgeVariant} />
<div className="tier-ladder__threshold">
<span className="tier-ladder__threshold-label">Score range</span>
<span className="tier-ladder__threshold-value">{formatThreshold(tier)}</span>
</div>
</header>
<h3 className="tier-ladder__tier-name">{tier.label} tier</h3>
<ul className="tier-ladder__benefits">
{tier.benefits.map((benefit) => (
<li key={benefit}>{benefit}</li>
))}
</ul>
</article>
</li>
))}
</ol>
</div>
</section>
)
}