Skip to main content

Overview

GameLibrary is a comprehensive component that renders a virtualized grid of game cards with built-in search, filtering, sorting, and view modes. It’s the primary UI for browsing and managing your game collection.
For libraries larger than 100 games, GameLibrary automatically enables virtualized rendering to maintain 60fps scrolling performance.

Props

games
Game[]
required
Array of games to display in the library
onPlayGame
(game: Game, cardRect?: DOMRect) => void
required
Callback invoked when a user clicks a game card to launch it. Receives the game object and the card’s DOM rect for hero transition animations.
onGameOptions
(game: Game) => void
Callback invoked when the user opens the game options menu
getMenuItems
(game: Game) => GameCardMenuItem[]
Function that returns menu items for a specific game’s dropdown menu. Called dynamically for each card.
onToggleFavorite
(game: Game) => void
Callback invoked when the user toggles the favorite heart icon on a card
artworkSyncStore
ArtworkSyncStore
External store for per-game artwork sync phases. Each card subscribes to its own phase to show download progress.
launchingGameId
string | null
ID of the game currently being launched. Shows shimmer effect on that card and disables other cards.
scrollContainerRef
React.RefObject<HTMLElement | null>
Ref to the scrollable container element. Required for virtualization to work correctly.
className
string
Additional CSS classes to apply to the root element

Features

Search and filtering

GameLibrary includes built-in search and platform filtering:
  • Search - Filters games by title (case-insensitive)
  • Platform filter - Shows games for a specific system or all platforms
  • Favorites toggle - Filters to show only favorited games

View modes

Two display modes are available:
  • Grid view - Mosaic layout with cover art (default)
  • List view - Compact list with metadata columns

Sorting options

Games can be sorted by:
  • Title - Alphabetical order
  • Platform - Grouped by system
  • Last played - Most recently played first
  • Recent - Recently added to library

Virtualization

For libraries with more than 100 games, GameLibrary automatically enables virtualized rendering:
  • Only visible cards are rendered in the DOM
  • Reduces DOM nodes from 1200+ to ~40 for large libraries
  • Maintains smooth 60fps scrolling performance
  • Uses useMosaicVirtualizer hook under the hood

Flip animations

GameLibrary uses FLIP (First, Last, Invert, Play) animations when games are filtered or re-sorted, creating smooth position transitions.

Usage

Basic example

import { GameLibrary } from '@gamelord/ui';

function Library() {
  const games = [
    { id: '1', title: 'Super Mario Bros.', systemId: 'nes', /* ... */ },
    { id: '2', title: 'Sonic the Hedgehog', systemId: 'genesis', /* ... */ }
  ];

  const handlePlayGame = (game: Game, cardRect?: DOMRect) => {
    console.log('Launching game:', game.title);
    // Launch game with hero transition from cardRect
  };

  return (
    <GameLibrary
      games={games}
      onPlayGame={handlePlayGame}
    />
  );
}

With menu items and favorites

import { GameLibrary, GameCardMenuItem } from '@gamelord/ui';

function LibraryWithActions() {
  const getMenuItems = (game: Game): GameCardMenuItem[] => [
    {
      label: 'View Details',
      icon: 'info',
      onClick: () => console.log('Details for', game.title)
    },
    {
      label: 'Delete',
      icon: 'trash',
      variant: 'danger',
      onClick: () => confirmDelete(game)
    }
  ];

  const handleToggleFavorite = (game: Game) => {
    // Update game.isFavorite in your state
  };

  return (
    <GameLibrary
      games={games}
      onPlayGame={handlePlayGame}
      getMenuItems={getMenuItems}
      onToggleFavorite={handleToggleFavorite}
    />
  );
}

With artwork sync progress

import { GameLibrary, ArtworkSyncStore } from '@gamelord/ui';

function LibraryWithSync() {
  const artworkSyncStore = new ArtworkSyncStore();

  // Update sync phases as artwork downloads
  useEffect(() => {
    artworkSyncStore.setPhase('game-123', 'downloading');
    // ... later:
    artworkSyncStore.setPhase('game-123', 'done');
  }, []);

  return (
    <GameLibrary
      games={games}
      onPlayGame={handlePlayGame}
      artworkSyncStore={artworkSyncStore}
    />
  );
}

With virtualization

import { GameLibrary } from '@gamelord/ui';
import { useRef } from 'react';

function LargeLibrary() {
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  return (
    <div
      ref={scrollContainerRef}
      style={{ height: '100vh', overflow: 'auto' }}
    >
      <GameLibrary
        games={largeGameCollection} // 500+ games
        onPlayGame={handlePlayGame}
        scrollContainerRef={scrollContainerRef}
      />
    </div>
  );
}
Always provide a scrollContainerRef when using GameLibrary inside a fixed-height scrollable container. This enables virtualization to work correctly.

Performance optimizations

GameLibrary includes several performance optimizations:
  1. Virtualized rendering - Only visible cards are in the DOM (>100 games)
  2. FLIP animations - Smooth transitions without layout thrashing
  3. Memoized filtering - Search and filter operations are cached
  4. ResizeObserver - Efficient container width tracking for responsive layout
  5. Debounced search - Search input is debounced to reduce re-renders

Keyboard navigation

GameLibrary supports keyboard navigation:
  • Arrow keys - Navigate between cards
  • Enter - Launch selected game
  • / - Focus search input
  • Esc - Clear search

Build docs developers (and LLMs) love