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)