import type { Meta, StoryObj } from '@storybook/react'; import { PixelFadeIn, PixelSlideIn, PixelPulse, PixelBounce, PixelTypewriter, PixelGlitch, PixelFloat, PixelShake, PixelRotate, PixelZoomIn, PixelFlicker, } from './animations'; import { AnimatedPxlKitIcon, PxlKitIcon } from '@pxlkit/core'; import { Trophy, FireSword, Crown, Star } from '@pxlkit/gamification'; import { Heart } from '@pxlkit/social'; const TONES = ['green', 'cyan', 'gold', 'red', 'purple', 'pink', 'neutral'] as const; const TRIGGERS = ['mount', 'hover', 'click', 'focus', 'inView'] as const; const meta: Meta = { title: 'UI Kit / Animations', parameters: { layout: 'padded' }, }; export default meta; type Story = StoryObj; /** Overview — every animation primitive applied to a real animated pxlkit icon. */ export const AllAnimations: Story = { render: () => (
), }; function Frame({ label, children }: { label: string; children: React.ReactNode }) { return (
{children} {label}
); } const childArg = ; const animationBaseArgs = { trigger: 'mount' as const, duration: 1000, delay: 0, }; const animationBaseControls = { trigger: { control: 'inline-radio', options: TRIGGERS }, duration: { control: { type: 'number', min: 0, step: 50 } }, delay: { control: { type: 'number', min: 0, step: 50 } }, }; /* ────────────────────────────────────────────────────────────────────────── PixelFadeIn ────────────────────────────────────────────────────────────────────────── */ export const PixelFadeInStory: Story = { name: 'PixelFadeIn', render: (args: any) => {args.children as React.ReactNode}, argTypes: animationBaseControls, args: { ...animationBaseArgs, duration: 400, repeat: 1, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelSlideIn ────────────────────────────────────────────────────────────────────────── */ export const PixelSlideInStory: Story = { name: 'PixelSlideIn', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, from: { control: 'inline-radio', options: ['up', 'down', 'left', 'right'] }, distance: { control: { type: 'number' } }, }, args: { ...animationBaseArgs, duration: 350, from: 'down', distance: 10, repeat: 1, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelPulse ────────────────────────────────────────────────────────────────────────── */ export const PixelPulseStory: Story = { name: 'PixelPulse', render: (args: any) => {args.children as React.ReactNode}, argTypes: animationBaseControls, args: { ...animationBaseArgs, duration: 2000, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelBounce ────────────────────────────────────────────────────────────────────────── */ export const PixelBounceStory: Story = { name: 'PixelBounce', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, height: { control: { type: 'number' } }, }, args: { ...animationBaseArgs, duration: 800, height: 8, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelFloat ────────────────────────────────────────────────────────────────────────── */ export const PixelFloatStory: Story = { name: 'PixelFloat', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, distance: { control: { type: 'number' } }, }, args: { ...animationBaseArgs, duration: 2200, distance: 6, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelShake ────────────────────────────────────────────────────────────────────────── */ export const PixelShakeStory: Story = { name: 'PixelShake', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, distance: { control: { type: 'number' } }, }, args: { ...animationBaseArgs, duration: 450, distance: 2, trigger: 'hover' as const, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelRotate ────────────────────────────────────────────────────────────────────────── */ export const PixelRotateStory: Story = { name: 'PixelRotate', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, direction: { control: 'inline-radio', options: ['normal', 'reverse', 'alternate', 'alternate-reverse'] }, }, args: { ...animationBaseArgs, duration: 1800, direction: 'normal', children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelZoomIn ────────────────────────────────────────────────────────────────────────── */ export const PixelZoomInStory: Story = { name: 'PixelZoomIn', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, startScale: { control: { type: 'number', min: 0, max: 1, step: 0.01 } }, }, args: { ...animationBaseArgs, duration: 320, startScale: 0.92, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelFlicker ────────────────────────────────────────────────────────────────────────── */ export const PixelFlickerStory: Story = { name: 'PixelFlicker', render: (args: any) => {args.children as React.ReactNode}, argTypes: animationBaseControls, args: { ...animationBaseArgs, duration: 2200, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelGlitch ────────────────────────────────────────────────────────────────────────── */ export const PixelGlitchStory: Story = { name: 'PixelGlitch', render: (args: any) => {args.children as React.ReactNode}, argTypes: { ...animationBaseControls, intensity: { control: { type: 'number', min: 1, max: 12 } }, }, args: { ...animationBaseArgs, duration: 3000, intensity: 4, trigger: 'hover' as const, children: childArg }, }; /* ────────────────────────────────────────────────────────────────────────── PixelTypewriter ────────────────────────────────────────────────────────────────────────── */ export const PixelTypewriterStory: Story = { name: 'PixelTypewriter', render: (args: any) => (
), argTypes: { text: { control: 'text' }, speed: { control: { type: 'number', min: 0, step: 5 } }, delay: { control: { type: 'number', min: 0, step: 50 } }, cursor: { control: 'boolean' }, tone: { control: 'select', options: TONES }, trigger: { control: 'inline-radio', options: TRIGGERS }, }, args: { text: 'PXLKIT_BOOT_OK', speed: 60, delay: 0, cursor: true, tone: 'green', trigger: 'mount', }, };