Improve UX: Add Footer everywhere, unified max-width, beautiful charts

- Added Footer component to all pages (home, dashboard, TLD pages)
- Changed max-width from 6xl to 7xl for consistent layout
- Enhanced mini-charts with gradients, area fills, and data points
- Better visual hierarchy and spacing
- Consistent design across all pages
This commit is contained in:
2025-12-08 07:46:58 +01:00
parent d12c5ddfa5
commit 48b33e9252
5 changed files with 75 additions and 35 deletions

View File

@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation'
import { useStore } from '@/lib/store'
import { api } from '@/lib/api'
import { Header } from '@/components/Header'
import { Footer } from '@/components/Footer'
import {
Plus,
Trash2,
@ -560,6 +561,8 @@ export default function DashboardPage() {
</div>
</div>
)}
<Footer />
</div>
)
}

View File

@ -2,6 +2,7 @@
import { useEffect, useState } from 'react'
import { Header } from '@/components/Header'
import { Footer } from '@/components/Footer'
import { DomainChecker } from '@/components/DomainChecker'
import { useStore } from '@/lib/store'
import { api } from '@/lib/api'
@ -148,7 +149,7 @@ export default function HomePage() {
{/* Hero Section */}
<section className="relative pt-32 sm:pt-36 md:pt-40 lg:pt-48 pb-16 sm:pb-20 px-4 sm:px-6">
<div className="max-w-6xl mx-auto text-center">
<div className="max-w-7xl mx-auto text-center">
{/* Tagline */}
<div className="inline-flex items-center gap-2 sm:gap-2.5 px-3 sm:px-4 py-1.5 sm:py-2 bg-background-secondary/80 backdrop-blur-sm border border-border rounded-full mb-6 sm:mb-8 md:mb-10 animate-fade-in">
<div className="w-1.5 h-1.5 rounded-full bg-accent animate-glow-pulse" />
@ -176,7 +177,7 @@ export default function HomePage() {
{/* TLD Price Intelligence Section */}
<section className="relative py-16 sm:py-20 md:py-24 px-4 sm:px-6 border-t border-border-subtle">
<div className="max-w-6xl mx-auto">
<div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="text-center mb-10 sm:mb-12">
<div className="inline-flex items-center gap-2 px-3 py-1.5 bg-accent-muted border border-accent/20 rounded-full mb-5">
@ -287,7 +288,7 @@ export default function HomePage() {
{/* Features Section */}
<section className="relative py-20 sm:py-24 md:py-32 px-4 sm:px-6">
<div className="max-w-6xl mx-auto">
<div className="max-w-7xl mx-auto">
<div className="text-center mb-12 sm:mb-16 md:mb-20">
<p className="label sm:label-md text-accent mb-3 sm:mb-4 md:mb-5">How It Works</p>
<h2 className="font-display text-[1.75rem] sm:text-[2.5rem] md:text-[3.25rem] lg:text-[4rem] leading-[1.1] tracking-[-0.03em] text-foreground mb-4 sm:mb-5 md:mb-6">
@ -414,25 +415,7 @@ export default function HomePage() {
</div>
</section>
{/* Footer */}
<footer className="py-8 sm:py-10 px-4 sm:px-6 border-t border-border-subtle">
<div className="max-w-6xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-4 sm:gap-6">
<p className="text-ui-sm sm:text-ui text-foreground-subtle">
© 2024 pounce
</p>
<div className="flex items-center gap-6 sm:gap-8">
<Link href="/tld-pricing" className="text-ui-sm sm:text-ui text-foreground-subtle hover:text-foreground transition-colors duration-300">
TLD Pricing
</Link>
<Link href="/pricing" className="text-ui-sm sm:text-ui text-foreground-subtle hover:text-foreground transition-colors duration-300">
Plans
</Link>
<Link href="/login" className="text-ui-sm sm:text-ui text-foreground-subtle hover:text-foreground transition-colors duration-300">
Sign In
</Link>
</div>
</div>
</footer>
<Footer />
</div>
)
}

View File

@ -3,6 +3,7 @@
import { useEffect, useState } from 'react'
import { useParams } from 'next/navigation'
import { Header } from '@/components/Header'
import { Footer } from '@/components/Footer'
import { api } from '@/lib/api'
import {
ArrowLeft,
@ -398,6 +399,8 @@ export default function TldDetailPage() {
</div>
</div>
</main>
<Footer />
</div>
)
}

View File

@ -48,7 +48,7 @@ interface TldHistoryData {
type SortField = 'tld' | 'avg_registration_price' | 'min_registration_price' | 'registrar_count'
type SortDirection = 'asc' | 'desc'
// Mini sparkline chart component with real data
// Mini sparkline chart component with real data - Enhanced version
function MiniChart({ tld, isAuthenticated }: { tld: string, isAuthenticated: boolean }) {
const [historyData, setHistoryData] = useState<number[]>([])
const [loading, setLoading] = useState(true)
@ -61,8 +61,7 @@ function MiniChart({ tld, isAuthenticated }: { tld: string, isAuthenticated: boo
const loadHistory = async () => {
try {
const data = await api.getTldHistory(tld, 365) // Get 1 year of data
// Sample down to 12 data points (monthly)
const data = await api.getTldHistory(tld, 365)
const history = data.history || []
const sampledData = history
.filter((_, i) => i % Math.floor(history.length / 12) === 0)
@ -90,27 +89,79 @@ function MiniChart({ tld, isAuthenticated }: { tld: string, isAuthenticated: boo
const min = Math.min(...historyData)
const max = Math.max(...historyData)
const range = max - min || 1
const isIncreasing = historyData[historyData.length - 1] > historyData[0]
const points = historyData.map((value, i) => {
// Create line points
const linePoints = historyData.map((value, i) => {
const x = (i / (historyData.length - 1)) * 100
const y = 100 - ((value - min) / range) * 100
const y = 100 - ((value - min) / range) * 80 - 10 // Add padding
return `${x},${y}`
}).join(' ')
const isIncreasing = historyData[historyData.length - 1] > historyData[0]
// Create area path for gradient fill
const areaPath = historyData.map((value, i) => {
const x = (i / (historyData.length - 1)) * 100
const y = 100 - ((value - min) / range) * 80 - 10
return i === 0 ? `M${x},${y}` : `L${x},${y}`
}).join(' ') + ' L100,100 L0,100 Z'
const gradientId = `gradient-${tld}`
return (
<svg className="w-24 h-8" viewBox="0 0 100 100" preserveAspectRatio="none">
<svg className="w-32 h-10" viewBox="0 0 100 100" preserveAspectRatio="none">
<defs>
<linearGradient id={gradientId} x1="0%" y1="0%" x2="0%" y2="100%">
<stop
offset="0%"
stopColor={isIncreasing ? "#f97316" : "#00d4aa"}
stopOpacity="0.3"
/>
<stop
offset="100%"
stopColor={isIncreasing ? "#f97316" : "#00d4aa"}
stopOpacity="0.02"
/>
</linearGradient>
</defs>
{/* Area fill */}
<path
d={areaPath}
fill={`url(#${gradientId})`}
className="transition-all duration-300"
/>
{/* Line */}
<polyline
points={points}
points={linePoints}
fill="none"
stroke="currentColor"
strokeWidth="3"
strokeWidth="2.5"
strokeLinecap="round"
strokeLinejoin="round"
className={clsx(
"transition-colors",
isIncreasing ? "text-[#f97316]/60" : "text-accent/60"
"transition-all duration-300",
isIncreasing ? "stroke-[#f97316]" : "stroke-accent"
)}
/>
{/* Dots for each data point */}
{historyData.map((value, i) => {
const x = (i / (historyData.length - 1)) * 100
const y = 100 - ((value - min) / range) * 80 - 10
return (
<circle
key={i}
cx={x}
cy={y}
r="1.5"
className={clsx(
"transition-all duration-300",
isIncreasing ? "fill-[#f97316]" : "fill-accent"
)}
opacity={i === historyData.length - 1 ? "1" : "0.4"}
/>
)
})}
</svg>
)
}

View File

@ -27,7 +27,7 @@ export function Header() {
return (
<header className="fixed top-0 left-0 right-0 z-50 bg-background/80 backdrop-blur-xl border-b border-border-subtle">
<div className="max-w-6xl mx-auto px-4 sm:px-6 h-14 sm:h-16 flex items-center justify-between">
<div className="max-w-7xl mx-auto px-4 sm:px-6 h-14 sm:h-16 flex items-center justify-between">
{/* Left side: Logo + Nav Links */}
<div className="flex items-center gap-6 sm:gap-8">
{/* Logo */}