7. User Experience7.5 Progressive Disclosure

7.5. Progressive Disclosure

Progressive Disclosure is the foundational UX philosophy of Fhenix-FairMarket v2.0. In traditional decentralized applications, users are often overwhelmed by raw cryptographic terminology (FHE.lte, Ciphertext Hash, AVS Proof), opaque state transitions, and technical error messages that obscure economic intent.

Version 2.0 resolves this through a layered information architecture that reveals complexity only when necessary: beginners see intuitive, trust-building language ( Protected Bid, ️ Sealed Vault), while advanced users can opt into technical details via expandable sections. This design reduces cognitive load, prevents “signing blindness,” and maintains mathematical privacy by never exposing plaintext data prematurely.

Core Design Principles

PrincipleTechnical Implementation
Layered ComplexityDefault UI shows user-friendly terms; “Advanced Mode” toggle reveals technical details (FHE, CoFHE, AVS) for developers/auditors.
State-Gated RevelationInformation visibility is strictly bound to AuctionState: ACTIVE shows encryption status; RESOLVING shows processing progress; FINALIZED reveals outcome.
Terminology AbstractionA centralized terminology.ts dictionary maps technical terms to user-facing language. No raw cryptographic jargon appears in primary UI strings.
Contextual Help SystemEvery metric includes a ? tooltip with layered explanations: simple summary → technical deep-dive → documentation link.
Accessibility-First DisclosureAll progressive layers comply with WCAG 2.1 AA: keyboard navigation, screen-reader labels, and color-blind safe indicators for each disclosure level.

️ Technical Implementation

1. Centralized Terminology Dictionary (terminology.ts)

All user-facing strings are sourced from a single, auditable dictionary that enforces abstraction consistency.

// packages/frontend/src/lib/i18n/terminology.ts
export const TERMINOLOGY = {
 // Encryption Layer
 'FHE_ENCRYPTION': {
 simple: ' Bid Protected',
 detailed: 'Your bid is encrypted using Fully Homomorphic Encryption (FHE). No one—not even validators—can see its value until settlement.',
 technical: 'Client-side encryption via @cofhe/sdk ^1.2.0. Ciphertext hash stored on-chain; plaintext never transmitted.'
 },
 
 // Processing Layer
 'COFHE_PROCESSING': {
 simple: '️ Sealed Vault Active',
 detailed: 'Encrypted bids are being compared off-chain. The comparison happens without decryption, preserving privacy.',
 technical: 'FHEOS coprocessor executing constant-time FHE.select multiplexers. Results bound to EigenLayer AVS signatures.'
 },
 
 // Verification Layer
 'AVS_VERIFICATION': {
 simple: ' Verified by Network',
 detailed: 'Multiple independent operators have cryptographically signed the result. Economic penalties deter manipulation.',
 technical: 'EigenLayer AVS threshold consensus (3/5 operators). Fraud proofs enable slashing for invalid submissions.'
 },
 
 // Emergency Layer
 'DYNAMIC_TIMEOUT': {
 simple: '️ Auto-Refund Triggered',
 detailed: 'Network delay detected. Your funds are safe and can be claimed immediately via the refund button.',
 technical: 'Moving Time Average × 1.5 threshold exceeded. Contract transitioned to VOIDED; FHE engine disabled.'
 },
 
 // Settlement Layer
 'PULL_REFUND': {
 simple: ' Claim Your Funds',
 detailed: 'Click to withdraw your deposit. No loops, no gas wars—your refund is guaranteed.',
 technical: 'Pull-over-Push pattern: state mutation precedes external call. O(1) gas, reentrancy-immune.'
 }
} as const;
 
export type TermKey = keyof typeof TERMINOLOGY;
export type DisclosureLevel = 'simple' | 'detailed' | 'technical';

2. State-Gated Component Rendering (ProgressiveInfo.tsx)

A reusable component that conditionally renders disclosure layers based on user preference and auction state.

// packages/frontend/src/components/ui/ProgressiveInfo.tsx
'use client';
 
import { useState } from 'react';
import { TERMINOLOGY, TermKey, DisclosureLevel } from '@lib/i18n/terminology';
import { useAuctionState } from '@lib/hooks/useAuctionState';
import { Tooltip } from '@components/ui/Tooltip';
 
interface ProgressiveInfoProps {
 term: TermKey;
 auctionId?: string;
 defaultLevel?: DisclosureLevel;
}
 
export function ProgressiveInfo({ term, auctionId, defaultLevel = 'simple' }: ProgressiveInfoProps) {
 const [level, setLevel] = useState<DisclosureLevel>(defaultLevel);
 const { state } = useAuctionState(auctionId || '');
 
 // State-gated visibility: technical details only shown post-finalization
 const canShowTechnical = state === 'FINALIZED' || state === 'VOIDED';
 const availableLevels = (['simple', 'detailed', ...(canShowTechnical ? ['technical' as const] : [])] as DisclosureLevel[]);
 
 const content = TERMINOLOGY[term][level];
 
 return (
 <div className="progressive-info" role="group" aria-label={`${term} disclosure`}>
 <div className="content">
 {content}
 <Tooltip content={TERMINOLOGY[term].detailed}>
 <button className="help-icon" aria-label="Learn more">?</button>
 </Tooltip>
 </div>
 
 {/* Advanced Mode Toggle (only if technical content available) */}
 {canShowTechnical && availableLevels.length > 1 && (
 <div className="disclosure-controls">
 <label>
 <input 
 type="checkbox" 
 checked={level === 'technical'}
 onChange={(e) => setLevel(e.target.checked ? 'technical' : 'simple')}
 />
 Show technical details
 </label>
 </div>
 )}
 </div>
 );
}

3. Integration in ConfidenceDashboard.tsx

The dashboard consumes ProgressiveInfo to render state-aware, layered metrics.

// packages/frontend/src/app/auction/[id]/components/ConfidenceDashboard.tsx (excerpt)
import { ProgressiveInfo } from '@components/ui/ProgressiveInfo';
 
export function ConfidenceDashboard({ auctionId }: { auctionId: string }) {
 const { state, activeBids, timeRemaining } = useAuctionState(auctionId);
 
 return (
 <div className="dashboard-grid">
 {/* Always Visible: Process Transparency */}
 <MetricCard 
 label="Sealed Bids" 
 value={<ProgressiveInfo term="FHE_ENCRYPTION" auctionId={auctionId} />}
 icon=""
 />
 
 {/* State-Gated: Processing Status */}
 {state === 'RESOLVING' && (
 <MetricCard 
 label="Settlement Progress" 
 value={<ProgressiveInfo term="COFHE_PROCESSING" auctionId={auctionId} />}
 icon="️"
 />
 )}
 
 {/* State-Gated: Final Outcome */}
 {state === 'FINALIZED' && (
 <MetricCard 
 label="Result Verification" 
 value={<ProgressiveInfo term="AVS_VERIFICATION" auctionId={auctionId} defaultLevel="detailed" />}
 icon=""
 />
 )}
 </div>
 );
}

Disclosure Flow by Auction State

️ Security & Privacy Guarantees

  1. Zero Premature Disclosure: Technical details (FHE.lte, Ciphertext Hash, AVS Proof) are never rendered in the DOM before FINALIZED or VOIDED state. CI lint rules enforce this at build time.
  2. Cognitive Load Reduction: By default, users see only 3-5 high-level metrics. Advanced details require explicit opt-in, preventing information overload during critical decision points.
  3. Accessibility Compliance: All disclosure layers include ARIA labels, keyboard navigation support, and screen-reader optimized text. Color indicators are supplemented with icons and text for color-blind users.
  4. Contextual Help Without Leakage: Tooltips provide educational content without exposing sensitive data. The “technical” layer is gated behind both state validation and user preference.
  5. Auditability of Abstraction: The terminology.ts dictionary is a single source of truth. Any change to user-facing language requires a PR review, ensuring consistency and preventing accidental plaintext exposure via UI strings.

Audit Gate Compliance (P0)

Progression through Phase 5 is strictly blocked until all P0 items pass:

  • [] Zero Raw Terminology in Default UI: CI lint rules fail the build if any component renders FHE, CoFHE, AVS, or Ciphertext in primary UI strings without ProgressiveInfo wrapper.
  • [] State-Gated Technical Disclosure: Unit tests confirm that technical disclosure level is inaccessible before FINALIZED/VOIDED state transitions.
  • [] Centralized Dictionary Enforcement: All user-facing strings are sourced from terminology.ts; no hardcoded UI text bypasses the abstraction layer.
  • [] Accessibility Compliance: Automated axe-core scans confirm WCAG 2.1 AA compliance for all disclosure variants (simple/detailed/technical).
  • [] Tooltip Safety: Contextual help content is audited to ensure no plaintext bid values, winner addresses, or decrypted data appear in tooltips before cryptographic finality.
  • [] Opt-In Technical Layer: The “Show technical details” toggle is disabled by default and requires explicit user interaction to activate.

Unresolved Points & Explicit Gaps

Gap / Unresolved PointImpactCurrent StatusRecommended Action
Multi-Language Terminologyterminology.ts currently supports English/Arabic only. Global accessibility requires i18n expansion.i18n framework not initialized in Phase 5 specs.Integrate next-i18next and translation files for top 5 languages before Mainnet.
Dynamic Terminology UpdatesCan governance propose new user-facing terms without code deployment?Terminology is hardcoded in frontend bundle.Design a governance-controlled TerminologyRegistry.sol for dynamic term updates in v2.1.
Personalized Disclosure PreferencesCan users save their preferred disclosure level (simple/detailed) across sessions?Preference is session-scoped only.Add encrypted localStorage for user preferences with explicit consent flow.
Analytics on Disclosure UsageWhich disclosure levels do users actually engage with?No telemetry implemented for privacy reasons.Implement privacy-preserving, aggregate-only analytics via zero-knowledge proofs in v2.2.

Fact vs. Analysis Distinction: The layered complexity architecture, state-gated revelation, centralized terminology dictionary, and accessibility compliance are verified facts from Phase 5 Sub-Tasks Matrix (Task 5.4) and the README.md UX 2.0 principles. Multi-language support, dynamic terminology updates, personalized preferences, and disclosure analytics are unresolved UX enhancements requiring explicit definition before Mainnet launch.


Next Steps