diff --git a/app/page.tsx b/app/page.tsx index e20d650..424b575 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,284 +1,165 @@ -'use client' +import React from 'react'; +// Import the client components from the new file +import { ThemeProvider } from './components/ThemeProvider.client'; -import Link from 'next/link' -import Image from 'next/image' -import { Button } from '@/components/ui/button' -import { Card } from '@/components/ui/card' -import { useMatrixEffect } from '@/hooks/useMatrixEffect' +// --- MAIN PAGE COMPONENTS (TAILWIND STYLED) --- -export default function HomePage() { - const heroMatrixRef = useMatrixEffect(0.2, 2) // Matrix effect for hero section - const sectionMatrixRef = useMatrixEffect(0.15, 1.5) // Matrix effect for lower section +// HomePage Component (renamed from App for Next.js conventions) +// The ThemeProvider is now a client component wrapping the rest of the page. +export default function HomePage(): JSX.Element { + return ( + + + + ); +} + +function HomePageContent(): JSX.Element { + // We no longer need 'mounted' check here due to FIX 3. + // const { mounted } = useTheme(); + + // + // The 'mounted' check is only necessary inside ThemeToggle. return ( - <> -
- {/* Background gradient */} -
- - {/* Matrix background effect */} -
-
- - {/* Additional purple glow effects */} -
-
-
- - {/* Subtle overlay for depth */} -
-
+ // Base classes for full screen, dark mode transition, and text color + // The transition-colors class here now handles the smooth theme change. +
-
- {/* Logo Animation */} -
+ {/* Header */} +
+
+ hodlCoin +
+ + Theme Toggle → + +
+
+
- {/* Main Content */} -
-

- hodlCoin Staking Platform -

-

- Self-Stabilizing Staking vaults where the price is mathematically proven to always increase!
- Unstaking fees benefit vault creators and those who keep staking longer. -

+ {/* Main Content */} +
+ + {/* Hero Section */} +
+

+ hodlCoin Staking Platform +

+

+ Self-Stabilizing Staking vaults where the price is mathematically proven to always increase!
+ Unstaking fees benefit vault creators and those who keep staking longer. +

+ +

+ Choose the blockchain where you would like to stake: +

+ +
+ + +
+
-
-

- Choose the blockchain where you would like to stake: + {/* How HodlCoin Works */} +
+
+

+ How hodlCoin Works

-
+
- {/* Action Buttons */} -
- - - - - - - - - +

+ HodlCoin is a staking protocol that encourages staking ("hodling") assets for long periods of time. When hodling, users deposit coins of a given asset in a vault and receive a proportional amount of corresponding hodlCoins. +

+

+ When unhodling, users must pay an unstaking fee that benefits the vault's creator and users who continue hodling longer. Moreover, anyone (especially vault creators) can distribute rewards to hodlers, to further incentivize hodling. +

-
-
- {/* Matrix background effect */} -
-
- - {/* Additional purple glow effects */} -
-
-
- - {/* Subtle grid overlay */} -
-
+ {/* Why HodlCoin Section */} +
+

+ Why hodlCoin +

-
- {/* How HodlCoin Works Section */} -
- {/* Paper Image */} -
- - -
- Research Paper -
-
- - -
+
- {/* Content */} -
-
-

- How hodlCoin Works -

-
-
- -
-

- HodlCoin is a staking protocol that encourages staking ("hodling") - assets for long periods of time. When hodling, users deposit coins of - a given asset in a vault and receive a proportional amount of corresponding hodlCoins. -

-

- When unhodling, users must pay an unstaking fee that benefits the vault's creator and users - who continue hodling longer. Moreover, anyone (especially vault creators) can - distribute rewards to hodlers, to further incentivize hodling. -

-
+ {/* For Vault Creators */} +
+

+ For Vault Creators +

+
-
- - Read the Research Paper - - - - -
+
    +
  • +
    +
    +

    Reward your Loyal Tokenholders

    +

    Efficiently distribute rewards to all your tokenholders with a single transaction.

    +
    +
  • +
  • +
    +
    +

    Signal your Long-Term Commitment

    +

    Stake your own tokens in a vault with a high unstaking fee, to show your community that you are holding for the long run.

    +
    +
  • +
  • +
    +
    +

    Earn Unstaking Fees

    +

    Receive a portion of fees when users unstake early.

    +
    +
  • +
-
- {/* Why HodlCoin Section */} -
-
-

- Why hodlCoin -

-
+ {/* For Stakers */} +
+

+ For Stakers +

+
-
- {/* For Vault Creators */} - -
-
-

For Vault Creators

-
+
    +
  • +
    +
    +

    Earn from Others' Impatience

    +

    Benefit from unstaking fees paid by users who exit early.

    - -
      -
    • -
      -
      -

      Reward your Loyal Tokenholders

      -

      Efficiently distribute rewards to all your tokenholders with a single transaction.

      -
      -
    • -
    • -
      -
      -

      Signal your Long-Term Commitment

      -

      Stake your own tokens in a vault with a high unstaking fee, to show your community that you are holding for the long run.

      -
      -
    • -
    • -
      -
      -

      Earn Unstaking Fees

      -

      Receive a portion of fees when users unstake early.

      -
      -
    • -
    • -
      -
      -

      Protect your Token from Sell Pressure

      -

      The unstaking fee disincentivizes sellers and incentivizes holders without inflation.

      -
      -
    • -
    -
    - - - {/* For Stakers */} - -
    -
    -

    For Stakers

    -
    +
  • +
  • +
    +
    +

    Long-Term Value Growth

    +

    The price of the hodlCoin is mathematically guaranteed to grow w.r.t. the price of the underlying coin, if you hodl longer than others.

    +
    +
  • +
  • +
    +
    +

    Receive Rewards

    +

    Get additional rewards distributed by vault creators who want to incentivize staking.

    - -
      -
    • -
      -
      -

      Earn from Others' Impatience

      -

      Benefit from unstaking fees paid by users who exit early.

      -
      -
    • -
    • -
      -
      -

      Long-Term Value Growth

      -

      The price of the hodlCoin is mathematically guaranteed to grow w.r.t. the price of the underlying coin, if you hodl longer than others.

      -
      -
    • -
    • -
      -
      -

      Receive Rewards

      -

      Get additional rewards distributed by vault creators who want to incentivize staking.

      -
      -
    • -
    • -
      -
      -

      Flexible Participation

      -

      Stake and unstake at any time, choosing from a wide variety of vaults for various tokens.

      -
      -
    • -
    -
    - +
  • +
-
- - ) -} +

+
+ ); +} \ No newline at end of file diff --git a/components/ThemeProvider.client.tsx b/components/ThemeProvider.client.tsx new file mode 100644 index 0000000..58d6a4b --- /dev/null +++ b/components/ThemeProvider.client.tsx @@ -0,0 +1,136 @@ +'use client'; +import React, { createContext, useContext, useEffect, useState } from 'react'; +import { Moon, Sun } from 'lucide-react'; + +// --- TYPES AND CONTEXT --- +interface ThemeContextType { + theme: 'light' | 'dark'; + toggleTheme: () => void; + mounted: boolean; +} + +interface ThemeProviderProps { + children: React.ReactNode; +} + +// Theme Context +const ThemeContext = createContext(null); + +// --- THEME PROVIDER LOGIC --- + +/** + * Applies or removes the 'dark' class on the element. + * Handles the DOM side-effect. + */ +const setRootClass = (newTheme: 'light' | 'dark'): void => { + if (typeof document !== 'undefined') { + // Only toggle the 'dark' class + document.documentElement.classList.toggle('dark', newTheme === 'dark'); + // NOTE: Global transition classes are removed here based on feedback, + // as the main content wrapper handles the transition. + } +}; + +export function ThemeProvider({ children }: ThemeProviderProps): JSX.Element { + const [theme, setTheme] = useState<'light' | 'dark'>('dark'); + const [mounted, setMounted] = useState(false); + + // 1. Initialization Effect (Runs ONCE on mount) + useEffect(() => { + if (typeof window === 'undefined') return; + + let storedRaw: string | null = null; + try { + // FIX 1A: Harden theme persistence read with try/catch + storedRaw = localStorage.getItem('theme'); + } catch { + // Ignore storage read failures + } + + const stored = (storedRaw === 'light' || storedRaw === 'dark') ? storedRaw : null; + + // Use system preference if no valid stored theme is found + const initial = stored ?? + (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + + setTheme(initial); + setRootClass(initial); // Initial application of class to prevent FOUC on initial render + setMounted(true); + }, []); + + // 2. Side Effect Listener (Runs on 'theme' state change) + useEffect(() => { + // Only run side effects once mounted and window is available + if (!mounted || typeof window === 'undefined') return; + + // Run DOM side-effect + setRootClass(theme); + + // FIX 1C/4: Harden theme persistence write with try/catch and isolate from state updater + try { + localStorage.setItem('theme', theme); + } catch { + // Ignore storage write failures + } + }, [theme, mounted]); + + + // FIX 1B/4: Use functional state update for race-safe toggling and KEEP PURE. + // Side effects (setRootClass, localStorage) are handled in the useEffect above. + const toggleTheme = (): void => { + setTheme((prev) => (prev === 'light' ? 'dark' : 'light')); + }; + + return ( + + {children} + + ); +} + +// Hook to use theme +export function useTheme(): ThemeContextType { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within ThemeProvider'); + } + return context; +} + +// --- THEME TOGGLE COMPONENT (TAILWIND STYLED) --- +export function ThemeToggle(): JSX.Element { + const { theme, toggleTheme, mounted } = useTheme(); + + // Show a loading state until mounted + if (!mounted) { + return ( + + ); + } + + return ( + + ); +} \ No newline at end of file