RETRO // NEXTUI

PixelCharacter

SVG pixel-art sprite with three variants: hero (neon green), ghost (magenta), and coin (yellow). Supports a CSS float animation and configurable size.

$npx @voltenworks/shipui add pixelcharacter --theme retro
Or install the base component for free:
Live Preview
Open full demo
voltenworks.com/shipui/retro/demo/components#08-character
Usage
TSX
<PixelCharacter variant="hero" size={64} animate={true} />
Variants
<PixelCharacter variant="hero" size={64} animate={true} />
<PixelCharacter variant="ghost" size={64} animate={true} />
<PixelCharacter variant="coin" size={64} animate={false} />
Source
TSX
import { cn } from '@/lib/utils'

interface PixelCharacterProps {
  variant?: 'hero' | 'ghost' | 'coin'
  size?: number
  animate?: boolean
  className?: string
}

function HeroPixels(): React.JSX.Element {
  const pixels: Array<{ x: number; y: number }> = [
    { x: 6, y: 0 }, { x: 7, y: 0 }, { x: 8, y: 0 }, { x: 9, y: 0 },
    { x: 5, y: 1 }, { x: 6, y: 1 }, { x: 7, y: 1 }, { x: 8, y: 1 }, { x: 9, y: 1 }, { x: 10, y: 1 },
    { x: 5, y: 2 }, { x: 6, y: 2 }, { x: 7, y: 2 }, { x: 8, y: 2 }, { x: 9, y: 2 }, { x: 10, y: 2 },
    { x: 5, y: 3 }, { x: 6, y: 3 }, { x: 7, y: 3 }, { x: 8, y: 3 }, { x: 9, y: 3 }, { x: 10, y: 3 },
    { x: 5, y: 4 }, { x: 6, y: 4 }, { x: 7, y: 4 }, { x: 8, y: 4 }, { x: 9, y: 4 }, { x: 10, y: 4 },
    { x: 4, y: 5 }, { x: 5, y: 5 }, { x: 6, y: 5 }, { x: 7, y: 5 }, { x: 8, y: 5 }, { x: 9, y: 5 }, { x: 10, y: 5 }, { x: 11, y: 5 },
    { x: 4, y: 6 }, { x: 5, y: 6 }, { x: 6, y: 6 }, { x: 7, y: 6 }, { x: 8, y: 6 }, { x: 9, y: 6 }, { x: 10, y: 6 }, { x: 11, y: 6 },
    { x: 5, y: 7 }, { x: 6, y: 7 }, { x: 7, y: 7 }, { x: 8, y: 7 }, { x: 9, y: 7 }, { x: 10, y: 7 },
    { x: 5, y: 8 }, { x: 6, y: 8 }, { x: 9, y: 8 }, { x: 10, y: 8 },
    { x: 5, y: 9 }, { x: 6, y: 9 }, { x: 9, y: 9 }, { x: 10, y: 9 },
    { x: 5, y: 10 }, { x: 6, y: 10 }, { x: 9, y: 10 }, { x: 10, y: 10 },
  ]
  return (
    <>
      {pixels.map(({ x, y }) => (
        <rect key={`${x}-${y}`} x={x} y={y} width={1} height={1} fill="#00ff41" />
      ))}
    </>
  )
}

function GhostPixels(): React.JSX.Element {
  const pixels: Array<{ x: number; y: number }> = [
    { x: 3, y: 2 }, { x: 4, y: 2 }, { x: 5, y: 2 }, { x: 6, y: 2 }, { x: 7, y: 2 }, { x: 8, y: 2 },
    { x: 2, y: 3 }, { x: 3, y: 3 }, { x: 4, y: 3 }, { x: 5, y: 3 }, { x: 6, y: 3 }, { x: 7, y: 3 }, { x: 8, y: 3 }, { x: 9, y: 3 },
    { x: 2, y: 4 }, { x: 3, y: 4 }, { x: 4, y: 4 }, { x: 5, y: 4 }, { x: 6, y: 4 }, { x: 7, y: 4 }, { x: 8, y: 4 }, { x: 9, y: 4 },
    { x: 2, y: 5 }, { x: 3, y: 5 }, { x: 4, y: 5 }, { x: 5, y: 5 }, { x: 6, y: 5 }, { x: 7, y: 5 }, { x: 8, y: 5 }, { x: 9, y: 5 },
    { x: 2, y: 6 }, { x: 3, y: 6 }, { x: 4, y: 6 }, { x: 5, y: 6 }, { x: 6, y: 6 }, { x: 7, y: 6 }, { x: 8, y: 6 }, { x: 9, y: 6 },
    { x: 2, y: 7 }, { x: 3, y: 7 }, { x: 4, y: 7 }, { x: 5, y: 7 }, { x: 6, y: 7 }, { x: 7, y: 7 }, { x: 8, y: 7 }, { x: 9, y: 7 },
    { x: 2, y: 8 }, { x: 3, y: 8 }, { x: 5, y: 8 }, { x: 6, y: 8 }, { x: 8, y: 8 }, { x: 9, y: 8 },
    { x: 2, y: 9 }, { x: 5, y: 9 }, { x: 6, y: 9 }, { x: 9, y: 9 },
  ]
  return (
    <>
      {pixels.map(({ x, y }) => (
        <rect key={`${x}-${y}`} x={x} y={y} width={1} height={1} fill="#ff00a8" />
      ))}
    </>
  )
}

function CoinPixels(): React.JSX.Element {
  const pixels: Array<{ x: number; y: number }> = [
    { x: 4, y: 1 }, { x: 5, y: 1 }, { x: 6, y: 1 }, { x: 7, y: 1 },
    { x: 3, y: 2 }, { x: 4, y: 2 }, { x: 5, y: 2 }, { x: 6, y: 2 }, { x: 7, y: 2 }, { x: 8, y: 2 },
    { x: 3, y: 3 }, { x: 4, y: 3 }, { x: 5, y: 3 }, { x: 6, y: 3 }, { x: 7, y: 3 }, { x: 8, y: 3 },
    { x: 3, y: 4 }, { x: 4, y: 4 }, { x: 5, y: 4 }, { x: 6, y: 4 }, { x: 7, y: 4 }, { x: 8, y: 4 },
    { x: 3, y: 5 }, { x: 4, y: 5 }, { x: 5, y: 5 }, { x: 6, y: 5 }, { x: 7, y: 5 }, { x: 8, y: 5 },
    { x: 3, y: 6 }, { x: 4, y: 6 }, { x: 5, y: 6 }, { x: 6, y: 6 }, { x: 7, y: 6 }, { x: 8, y: 6 },
    { x: 3, y: 7 }, { x: 4, y: 7 }, { x: 5, y: 7 }, { x: 6, y: 7 }, { x: 7, y: 7 }, { x: 8, y: 7 },
    { x: 4, y: 8 }, { x: 5, y: 8 }, { x: 6, y: 8 }, { x: 7, y: 8 },
  ]
  return (
    <>
      {pixels.map(({ x, y }) => (
        <rect key={`${x}-${y}`} x={x} y={y} width={1} height={1} fill="#ffe600" />
      ))}
      {/* $ symbol overlay */}
      <rect x={5} y={3} width={2} height={1} fill="#070810" />
      <rect x={5} y={4} width={3} height={1} fill="#070810" />
      <rect x={5} y={5} width={2} height={1} fill="#070810" />
      <rect x={4} y={6} width={3} height={1} fill="#070810" />
      <rect x={5} y={7} width={2} height={1} fill="#070810" />
    </>
  )
}

export function PixelCharacter({
  variant = 'hero',
  size = 64,
  animate = true,
  className,
}: PixelCharacterProps): React.JSX.Element {
  return (
    <svg
      width={size}
      height={size}
      viewBox="0 0 16 16"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
      focusable="false"
      className={cn(animate && 'animate-float', '[image-rendering:pixelated]', className)}
    >
      {variant === 'hero' && <HeroPixels />}
      {variant === 'ghost' && <GhostPixels />}
      {variant === 'coin' && <CoinPixels />}
    </svg>
  )
}
Preview in theme demoGet full theme, $29
Works withNext.js 15React 19Tailwind v4TypeScript 5
More from RETRO // NEXT
RETRO // NEXTUI

Button

Arcade-styled button with neon green, magenta, cyan, and yellow variants in three sizes. Renders as a Next.js Link when an href is provided.

RETRO // NEXTUI

Badge

Neon-glow badge with magenta, cyan, yellow, and green color variants. Used for category tags and status labels in the arcade aesthetic.

RETRO // NEXTUI

Card

Game-card component with neon-colored icon, tag, title, description, and a five-star rating display. Supports a "coming soon" locked overlay state.

RETRO // NEXTUI

ScoreBoard

High-scores leaderboard that renders as a table on desktop and as stacked cards on mobile. Highlights ranks 1-3 with distinct neon color classes.

RETRO // NEXTUI

SectionHeader

Section heading block with a numbered label, a two-part heading where the last word is accented in neon, and an optional subtitle. Supports left or center alignment.

RETRO // NEXTUI

StatBlock

Single-stat display with a large pixel-font value in neon cyan and a label below. Wrapped in a pixel-border container for the arcade aesthetic.

RETRO // NEXTUI

Text

Polymorphic text primitive with body, caption, label, and code variants styled for the RETRO dark arcade palette.