feat: Add neon esports landing page with WCAG accessibility
- Create HeroSection with animated search bar and stat counters - Add LiveMatchTicker with auto-scrolling recent matches - Build FlashLeaderboard "Wall of Shame" with podium display - Implement FeatureShowcase with scroll-triggered animations - Add NeonCTA call-to-action section with trust badges - Create reusable NeonButton component with glow effects Accessibility improvements: - Add aria-labels, aria-hidden for decorative elements - Implement focus-visible ring styles for keyboard navigation - Support prefers-reduced-motion across all animations - Use semantic HTML (article, nav, dl) for screen readers - Improve color contrast ratios for WCAG compliance 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
73
src/lib/components/ui/NeonButton.svelte
Normal file
73
src/lib/components/ui/NeonButton.svelte
Normal file
@@ -0,0 +1,73 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
href?: string;
|
||||
variant?: 'blue' | 'gold' | 'red' | 'green';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
children: Snippet;
|
||||
onclick?: () => void;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
href,
|
||||
variant = 'blue',
|
||||
size = 'md',
|
||||
children,
|
||||
onclick,
|
||||
class: className = ''
|
||||
}: Props = $props();
|
||||
|
||||
const variantClasses = {
|
||||
blue: {
|
||||
bg: 'bg-neon-blue',
|
||||
text: 'text-void',
|
||||
glow: 'hover:shadow-[0_0_30px_rgba(0,212,255,0.5)]',
|
||||
border: 'border-neon-blue'
|
||||
},
|
||||
gold: {
|
||||
bg: 'bg-neon-gold',
|
||||
text: 'text-void',
|
||||
glow: 'hover:shadow-[0_0_30px_rgba(255,215,0,0.5)]',
|
||||
border: 'border-neon-gold'
|
||||
},
|
||||
red: {
|
||||
bg: 'bg-neon-red',
|
||||
text: 'text-white',
|
||||
glow: 'hover:shadow-[0_0_30px_rgba(255,51,102,0.5)]',
|
||||
border: 'border-neon-red'
|
||||
},
|
||||
green: {
|
||||
bg: 'bg-neon-green',
|
||||
text: 'text-void',
|
||||
glow: 'hover:shadow-[0_0_30px_rgba(0,255,136,0.5)]',
|
||||
border: 'border-neon-green'
|
||||
}
|
||||
};
|
||||
|
||||
const sizeClasses = {
|
||||
sm: 'px-4 py-2 text-sm',
|
||||
md: 'px-6 py-3 text-base',
|
||||
lg: 'px-8 py-4 text-lg'
|
||||
};
|
||||
|
||||
const classes = variantClasses[variant];
|
||||
const sizeClass = sizeClasses[size];
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
{href}
|
||||
class="inline-flex items-center justify-center rounded-lg font-semibold transition-all duration-300 hover:scale-105 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-void motion-reduce:transition-none motion-reduce:hover:scale-100 {classes.bg} {classes.text} {classes.glow} {sizeClass} {className}"
|
||||
>
|
||||
{@render children()}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
{onclick}
|
||||
class="inline-flex items-center justify-center rounded-lg font-semibold transition-all duration-300 hover:scale-105 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-void motion-reduce:transition-none motion-reduce:hover:scale-100 {classes.bg} {classes.text} {classes.glow} {sizeClass} {className}"
|
||||
>
|
||||
{@render children()}
|
||||
</button>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user