Fixes: - Chart hover dot now uses DOM element instead of SVG circle (no more squished dots) - Chart hover line uses proper stroke-dasharray - Tooltip positioning improved New Components: - Shimmer.tsx: Unified shimmer component for loading/locked states - 404 Page: Professional not-found page with navigation options Consistency improvements identified for future: - All pages now use consistent Header/Footer - Trend colors standardized (orange=up, green=down) - Typography system follows design tokens
47 lines
1.2 KiB
TypeScript
47 lines
1.2 KiB
TypeScript
'use client'
|
|
|
|
import clsx from 'clsx'
|
|
|
|
interface ShimmerProps {
|
|
className?: string
|
|
variant?: 'default' | 'text' | 'card'
|
|
}
|
|
|
|
/**
|
|
* Unified Shimmer component for loading/locked states
|
|
* Use throughout the app for consistent loading UI
|
|
*/
|
|
export function Shimmer({ className, variant = 'default' }: ShimmerProps) {
|
|
return (
|
|
<div className={clsx(
|
|
"relative overflow-hidden rounded",
|
|
variant === 'default' && "bg-foreground/[0.06]",
|
|
variant === 'text' && "bg-foreground/[0.04]",
|
|
variant === 'card' && "bg-foreground/[0.03]",
|
|
className
|
|
)}>
|
|
<div
|
|
className="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-foreground/[0.08] to-transparent"
|
|
style={{
|
|
animation: 'shimmer 2s infinite',
|
|
}}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Shimmer block for price/data placeholders when user is not authenticated
|
|
*/
|
|
export function ShimmerBlock({ className }: { className?: string }) {
|
|
return <Shimmer className={className} variant="default" />
|
|
}
|
|
|
|
/**
|
|
* Shimmer text for inline text placeholders
|
|
*/
|
|
export function ShimmerText({ className }: { className?: string }) {
|
|
return <Shimmer className={clsx("h-4", className)} variant="text" />
|
|
}
|
|
|