Files
TUIkit/docs/app/components/FeatureCard.tsx
T
phranck d549869645 Refactor: Deep optimization pass across landing page codebase
Performance & memory:
- HeroTerminal: fix setInterval one-time random (now recursive setTimeout),
  reuse single Howl for seeks, track all timers via pendingTimersRef
- RainOverlay: cap at 30fps, skip on prefers-reduced-motion
- SpinnerLights: pre-compute boxShadow at spawn, nextId in useRef
- Remove eager audio preloads from <head> (Howler loads lazily)
- CloudBackground: remove unnecessary 'use client' (now Server Component)

Type safety & correctness:
- Import BootStep/SchoolStep/JoshuaStep/TerminalEntry from terminal-parser
  instead of duplicating interfaces; typed terminal-data.ts export
- ThemeProvider: isTheme() type guard replaces unsafe 'as Theme' casts,
  instanceof guard for event.target, try/catch on localStorage.setItem
- useCopyToClipboard: cancel previous timer on rapid clicks, try/catch
  around clipboard API, cleanup on unmount
- TerminalScreen: use config.initialCursorDelay instead of magic 18000,
  type predicate for filter(), track glitch reset timer for cleanup

Accessibility (WCAG):
- prefers-reduced-motion: global CSS rule + JS skip in Rain/Spinner/Glitch
- aria-hidden on decorative elements (Rain, Spinner, Clouds)
- focus-visible ring on ThemeSwitcher, CodePreview, PackageBadge buttons
- aria-pressed on active theme button, nav aria-label, main tabIndex

Code quality:
- Extract useCopyToClipboard hook (CodePreview + PackageBadge)
- bg-frosted-glass CSS utility replaces 3x inline color-mix
- hover:bg-white/* → hover:bg-foreground/* for theme consistency
- Remove dead zoomed prop, stale eslint-disable, move lineRefsRef up
- import type for ReactNode in FeatureCard
2026-02-02 14:21:03 +01:00

29 lines
886 B
TypeScript

import type { ReactNode } from "react";
interface FeatureCardProps {
icon: ReactNode;
title: string;
description: string;
}
/** A feature highlight card with icon, title, and description. */
export default function FeatureCard({
icon,
title,
description,
}: FeatureCardProps) {
return (
<div
className="group rounded-xl border border-border bg-frosted-glass p-6 backdrop-blur-xl transition-all duration-300 hover:border-accent/30"
>
<div className="mb-3 flex items-center gap-3">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-accent/10 text-accent transition-colors group-hover:bg-accent/15">
{icon}
</div>
<h3 className="text-2xl font-semibold text-foreground">{title}</h3>
</div>
<p className="text-xl leading-relaxed text-muted">{description}</p>
</div>
);
}