diff --git a/apps/web/src/app/arcade/matching/components/PlayerStatusBar.stories.tsx b/apps/web/src/app/arcade/matching/components/PlayerStatusBar.stories.tsx deleted file mode 100644 index 033a458c..00000000 --- a/apps/web/src/app/arcade/matching/components/PlayerStatusBar.stories.tsx +++ /dev/null @@ -1,455 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react' -import React, { useEffect } from 'react' -import { css } from '../../../../../styled-system/css' -import { gamePlurals } from '../../../../utils/pluralization' - -// Inject the celebration animations for Storybook -const celebrationAnimations = ` -@keyframes gentle-pulse { - 0%, 100% { - box-shadow: 0 0 0 2px white, 0 0 0 6px rgba(102, 126, 234, 0.3), 0 12px 32px rgba(0,0,0,0.1); - } - 50% { - box-shadow: 0 0 0 2px white, 0 0 0 6px rgba(102, 126, 234, 0.5), 0 12px 32px rgba(0,0,0,0.2); - } -} - -@keyframes gentle-bounce { - 0%, 100% { - transform: translateY(0); - } - 50% { - transform: translateY(-3px); - } -} - -@keyframes gentle-sway { - 0%, 100% { transform: rotate(-2deg) scale(1); } - 50% { transform: rotate(2deg) scale(1.05); } -} - -@keyframes breathe { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.03); } -} - -@keyframes float { - 0%, 100% { transform: translateY(0px); } - 50% { transform: translateY(-6px); } -} - -@keyframes turn-entrance { - 0% { - transform: scale(0.8) rotate(-10deg); - opacity: 0.6; - } - 50% { - transform: scale(1.1) rotate(5deg); - opacity: 1; - } - 100% { - transform: scale(1.08) rotate(0deg); - opacity: 1; - } -} - -@keyframes streak-pulse { - 0%, 100% { - opacity: 0.9; - transform: scale(1); - } - 50% { - opacity: 1; - transform: scale(1.05); - } -} - -@keyframes great-celebration { - 0% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #22c55e40, 0 12px 32px rgba(0,0,0,0.2); - } - 50% { - transform: scale(1.12) translateY(-6px); - box-shadow: 0 0 0 2px white, 0 0 0 8px #22c55e60, 0 15px 35px rgba(34,197,94,0.3); - } - 100% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #22c55e40, 0 12px 32px rgba(0,0,0,0.2); - } -} - -@keyframes epic-celebration { - 0% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #f97316, 0 12px 32px rgba(0,0,0,0.2); - } - 25% { - transform: scale(1.15) translateY(-8px) rotate(2deg); - box-shadow: 0 0 0 3px white, 0 0 0 10px #f97316, 0 18px 40px rgba(249,115,22,0.4); - } - 75% { - transform: scale(1.15) translateY(-8px) rotate(-2deg); - box-shadow: 0 0 0 3px white, 0 0 0 10px #f97316, 0 18px 40px rgba(249,115,22,0.4); - } - 100% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #f97316, 0 12px 32px rgba(0,0,0,0.2); - } -} - -@keyframes legendary-celebration { - 0% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #a855f7, 0 12px 32px rgba(0,0,0,0.2); - } - 20% { - transform: scale(1.2) translateY(-12px) rotate(5deg); - box-shadow: 0 0 0 4px gold, 0 0 0 12px #a855f7, 0 25px 50px rgba(168,85,247,0.5); - } - 40% { - transform: scale(1.18) translateY(-10px) rotate(-3deg); - box-shadow: 0 0 0 3px gold, 0 0 0 10px #a855f7, 0 20px 45px rgba(168,85,247,0.4); - } - 60% { - transform: scale(1.22) translateY(-14px) rotate(3deg); - box-shadow: 0 0 0 4px gold, 0 0 0 12px #a855f7, 0 25px 50px rgba(168,85,247,0.5); - } - 80% { - transform: scale(1.15) translateY(-8px) rotate(-1deg); - box-shadow: 0 0 0 3px gold, 0 0 0 8px #a855f7, 0 18px 40px rgba(168,85,247,0.3); - } - 100% { - transform: scale(1.08) translateY(-4px); - box-shadow: 0 0 0 2px white, 0 0 0 6px #a855f7, 0 12px 32px rgba(0,0,0,0.2); - } -} -` - -// Component to inject animations -const AnimationProvider = ({ children }: { children: React.ReactNode }) => { - useEffect(() => { - if (typeof document !== 'undefined' && !document.getElementById('celebration-animations')) { - const style = document.createElement('style') - style.id = 'celebration-animations' - style.textContent = celebrationAnimations - document.head.appendChild(style) - } - }, []) - - return <>{children} -} - -const meta: Meta = { - title: 'Games/Matching/PlayerStatusBar', - parameters: { - layout: 'centered', - docs: { - description: { - component: ` -The PlayerStatusBar component displays the current state of players in the matching game. -It shows different layouts for single player vs multiplayer modes and includes escalating -celebration effects for consecutive matching pairs. - -## Features -- Single player mode with epic styling -- Multiplayer mode with competitive grid layout -- Escalating celebration animations based on consecutive matches: - - 2+ matches: Great celebration (green) - - 3+ matches: Epic celebration (orange) - - 5+ matches: Legendary celebration (purple with gold accents) -- Real-time turn indicators -- Score tracking and progress display -- Responsive design for mobile and desktop - -## Animation Preview -The animations demonstrate different celebration levels that activate when players get consecutive matches. - ` - } - } - }, - decorators: [ - (Story) => ( - -
- -
-
- ) - ] -} - -export default meta -type Story = StoryObj - -// Create a mock player card component that showcases the animations -const MockPlayerCard = ({ - emoji, - name, - score, - consecutiveMatches, - isCurrentPlayer = true, - celebrationLevel -}: { - emoji: string - name: string - score: number - consecutiveMatches: number - isCurrentPlayer?: boolean - celebrationLevel: 'normal' | 'great' | 'epic' | 'legendary' -}) => { - const playerColor = celebrationLevel === 'legendary' ? '#a855f7' : - celebrationLevel === 'epic' ? '#f97316' : - celebrationLevel === 'great' ? '#22c55e' : '#3b82f6' - - return ( -
- - {/* Player emoji */} -
- {emoji} -
- - {/* Player info */} -
-
- {name} -
- -
- {gamePlurals.pair(score)} - {isCurrentPlayer && ( - - {' • Your turn'} - - )} - {consecutiveMatches > 1 && ( -
- 🔥 {consecutiveMatches} streak! -
- )} -
-
- - {/* Epic score display */} - {isCurrentPlayer && ( -
- ⚡{score}⚡ -
- )} -
- ) -} - -// Normal celebration level -export const NormalPlayer: Story = { - render: () => ( - - ) -} - -// Great celebration level -export const GreatStreak: Story = { - render: () => ( - - ) -} - -// Epic celebration level -export const EpicStreak: Story = { - render: () => ( - - ) -} - -// Legendary celebration level -export const LegendaryStreak: Story = { - render: () => ( - - ) -} - -// All levels showcase -export const AllCelebrationLevels: Story = { - render: () => ( -
-

- Consecutive Match Celebration Levels -

- -
- {/* Normal */} -
-

- Normal (0-1 matches) -

- -
- - {/* Great */} -
-

- Great (2+ matches) -

- -
- - {/* Epic */} -
-

- Epic (3+ matches) -

- -
- - {/* Legendary */} -
-

- Legendary (5+ matches) -

- -
-
- -
-

- These animations trigger when a player gets consecutive matching pairs in the memory matching game. - The celebrations get more intense as the streak grows, providing visual feedback and excitement! -

-
-
- ), - parameters: { - layout: 'fullscreen' - } -} \ No newline at end of file