DEV Community

A0mineTV
A0mineTV

Posted on

Building a Modern Tic-Tac-Toe Game with Radix UI, Tailwind CSS v4, and AI Collaboration

๐ŸŽฏ Introduction

In this article, I'll walk you through building a modern, accessible Tic-Tac-Toe game using React, Radix UI, and Tailwind CSS v4. What makes this project unique is the collaborative approach: I used Gemini CLI for the core game logic and Claude Sonnet 4 for UX design decisions. This demonstrates how AI can enhance different aspects of development.

๐Ÿ› ๏ธ Tech Stack

  • React 19 - Latest React with concurrent features
  • TypeScript - Type safety and better DX
  • Radix UI - Accessible, unstyled components
  • Tailwind CSS v4 - Latest version with Vite plugin
  • Vite - Fast build tool and dev server

๐ŸŽฎ The Game Logic (Powered by Gemini CLI)

Why Gemini CLI for Logic ?

I chose Gemini CLI for the game logic because it excels at:

  • Algorithmic thinking - Perfect for game state management
  • TypeScript patterns - Clean, type-safe code generation
  • React hooks - Proper state management patterns

Core Game Implementation

// Game state management with TypeScript type SquareValue = 'X' | 'O' | null; interface BoardProps { xIsNext: boolean; squares: SquareValue[]; onPlay: (squares: SquareValue[]) => void; winningSquares?: number[]; } // AI opponent logic useEffect(() => { const winnerInfo = calculateWinner(squares); if (xIsNext && !winnerInfo && squares.some(s => s === null)) { const availableSquares = squares .map((value, index) => (value === null ? index : null)) .filter((val): val is number => val !== null); if (availableSquares.length > 0) { const randomMove = availableSquares[Math.floor(Math.random() * availableSquares.length)]; const nextSquares = squares.slice(); nextSquares[randomMove] = 'X'; const timer = setTimeout(() => { onPlay(nextSquares); }, 700); return () => clearTimeout(timer); } } }, [xIsNext, squares, onPlay]); 
Enter fullscreen mode Exit fullscreen mode

Key Features:

  • Type-safe game state with TypeScript
  • AI opponent with realistic timing
  • Win detection with winning squares highlighting
  • Game history with move navigation

UX Design (Powered by Claude Sonnet 4)

Why Claude Sonnet 4 for UX?

Claude Sonnet 4 was perfect for UX decisions because it:

  • Understands design patterns - Modern UI/UX best practices
  • Accessibility focus - WCAG compliance and inclusive design
  • Micro-interactions - Subtle animations and feedback
  • Responsive design - Mobile-first approach

Modern UI Implementation

// Accessible button with micro-interactions <button className={` w-20 h-20 lg:w-24 lg:h-24 bg-white border-2 border-gray-200 rounded-xl shadow-sm flex items-center justify-center transition-all duration-200 ease-out hover:border-indigo-400 hover:shadow-lg hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:hover:translate-y-0 group ${isWinningSquare ? 'bg-gradient-to-br from-emerald-400 to-emerald-500 border-emerald-500 animate-pulse shadow-emerald-200 shadow-lg' : '' } `} onClick={onSquareClick} disabled={value !== null} aria-label={value ? `Square played by ${value}` : 'Empty square, click to play'} > {value === 'X' && ( <Cross1Icon className="w-12 h-12 lg:w-14 lg:h-14 text-red-600 stroke-2 group-hover:scale-110 transition-transform duration-200 drop-shadow-sm" /> )} </button> 
Enter fullscreen mode Exit fullscreen mode

๐Ÿš€ Migrating to Tailwind CSS v4

The Migration Process

We migrated from Tailwind CSS v3 to v4 following the official guide:

  1. Install the Vite plugin:
 npm install @tailwindcss/vite 
Enter fullscreen mode Exit fullscreen mode
  1. Update Vite config:
 import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [ react(), tailwindcss(), ], }) 
Enter fullscreen mode Exit fullscreen mode
  1. Simplify CSS imports:
 @import "tailwindcss"; 
Enter fullscreen mode Exit fullscreen mode
  1. Remove old config files:
    • tailwind.config.js
    • postcss.config.js

Benefits of Tailwind v4

  • Better performance with Vite integration
  • Simplified configuration - no config file needed
  • Automatic scanning of used classes
  • Zero runtime - all styles compiled at build time

โ™ฟ Accessibility with Radix UI

Why Radix UI ?

Radix UI provides:

  • Unstyled components - Full styling control
  • Built-in accessibility - ARIA attributes and keyboard navigation
  • Composition patterns - Flexible component architecture
  • TypeScript support - Excellent type definitions

Accessibility Features

// Tooltip with proper ARIA <Tooltip.Provider> <Tooltip.Root> <Tooltip.Trigger asChild> <button aria-label="Reset game"> <ResetIcon /> </button> </Tooltip.Trigger> <Tooltip.Portal> <Tooltip.Content className="bg-gray-900 text-white px-3 py-2 rounded-lg"> Reset Game <Tooltip.Arrow /> </Tooltip.Content> </Tooltip.Portal> </Tooltip.Root> </Tooltip.Provider> 
Enter fullscreen mode Exit fullscreen mode

๐ŸŽฏ Key UX Improvements

1. Micro-interactions

  • Hover effects with scale and translate transforms
  • Focus states with ring indicators
  • Loading states with smooth transitions
  • Success animations for winning combinations

2. Visual Hierarchy

  • Gradient backgrounds for visual appeal
  • Consistent spacing with Tailwind's spacing scale
  • Color semantics (red for X, blue for O, green for wins)
  • Typography scale for clear information hierarchy

3. Responsive Design

  • Mobile-first approach
  • Flexible layouts that adapt to screen size
  • Touch-friendly button sizes
  • Optimized spacing for different devices

๐Ÿค– AI Collaboration Insights

Working with Gemini CLI

Strengths:

  • Excellent at algorithmic problems
  • Generates clean, maintainable code
  • Good understanding of React patterns
  • Strong TypeScript knowledge

Best practices:

  • Provide clear context about your tech stack
  • Ask for specific patterns (e.g., "use React hooks")
  • Request explanations for complex logic

Working with Claude Sonnet 4

Strengths:

  • Deep understanding of UX principles
  • Excellent at design system thinking
  • Strong accessibility knowledge
  • Great at explaining design decisions

Best practices:

  • Share your design goals and constraints
  • Ask for multiple design approaches
  • Request accessibility considerations
  • Get explanations for UX decisions

๐Ÿ“ฑ Performance Optimizations

1. Tailwind CSS v4 Benefits

  • Purge unused styles automatically
  • Optimized bundle size with Vite
  • Fast hot reload during development

2. React Optimizations

  • Proper dependency arrays in useEffect
  • Memoization where beneficial
  • Efficient re-renders with proper state management

3. Bundle Analysis

npm run build npx vite-bundle-analyzer 
Enter fullscreen mode Exit fullscreen mode

๐Ÿš€ Deployment

The app is ready for deployment on:

  • Vercel - Zero config deployment
  • Netlify - Drag and drop deployment
  • GitHub Pages - Free hosting for open source

๐ŸŽ‰ Conclusion

This project demonstrates the power of combining:

  • Modern web technologies (React, TypeScript, Tailwind v4)
  • Accessible UI components (Radix UI)
  • AI collaboration for different aspects of development

The result is a polished, accessible, and performant game that showcases best practices in modern web development.

๐Ÿ”— Resources

Top comments (0)