DEV Community

Muhammad Yazed Jamaludin
Muhammad Yazed Jamaludin

Posted on

Building Retro UIs with React: A Pixel Art Component Library Tutorial

Building Retro UIs with React: A Pixel Art Component Library Tutorial

Remember the golden age of 8-bit and 16-bit gaming? That distinctive pixel art aesthetic is making a comeback in modern web design. Whether you're building a browser-based game, a creative portfolio, or just want to stand out from the sea of Material UI clones, pixel art interfaces bring personality and nostalgia to your React applications.

In this tutorial, I'll show you how to build retro-styled UIs using pixelartui-react, an open-source component library I've been developing specifically for this purpose.

Why Pixel Art UIs?

Before we dive into code, let's talk about why you might want a pixel art UI:

  1. Unique Identity - In a world of minimalist designs, pixel art makes your app memorable
  2. Perfect for Games - Web-based games need UI that matches their pixel art assets
  3. Nostalgia Factor - Retro aesthetics resonate with gamers and creative developers
  4. Character & Personality - Pixel art has charm that flat design sometimes lacks
  5. Rapid Prototyping - Consistent component library speeds up development

What We're Building

Today we'll create a retro-styled user profile form using pixelartui-react. You'll learn how to use:

  • Buttons
  • Text Inputs
  • TextArea
  • Select Dropdowns
  • Switches
  • Modals

By the end, you'll have a fully functional, retro-styled React component.

Getting Started

Installation

First, create a new React project (or use an existing one):

npx create-react-app retro-profile-app
cd retro-profile-app
Enter fullscreen mode Exit fullscreen mode

Install pixelartui-react:

npm install pixelartui-react
Enter fullscreen mode Exit fullscreen mode

Peer Dependencies

Make sure you have React 19:

npm install react@^19.1.0 react-dom@^19.1.0
Enter fullscreen mode Exit fullscreen mode

Installing the Pixel Font

For that authentic pixel art look, install Pixelify Sans:

npm install @fontsource/pixelify-sans
Enter fullscreen mode Exit fullscreen mode

Then import it in your src/index.js:

import '@fontsource/pixelify-sans';
Enter fullscreen mode Exit fullscreen mode

Building the Profile Form

Let's create a retro user profile component with pixel art styling.

Step 1: Basic Setup

Create a new file src/ProfileForm.jsx:

import { useState } from 'react';
import {
  Button,
  TextInput,
  TextArea,
  Select,
  Switch,
  Modal
} from 'pixelartui-react';

function ProfileForm() {
  const [formData, setFormData] = useState({
    username: '',
    email: '',
    bio: '',
    experience: 'beginner',
    notifications: true
  });

  const [showConfirm, setShowConfirm] = useState(false);

  return (
    <div style={{ 
      maxWidth: '600px', 
      margin: '50px auto', 
      padding: '20px',
      fontFamily: 'Pixelify Sans, monospace'
    }}>
      <h1 style={{ textAlign: 'center', marginBottom: '30px' }}>
        🎮 Player Profile
      </h1>

      {/* We'll add form fields here */}
    </div>
  );
}

export default ProfileForm;
Enter fullscreen mode Exit fullscreen mode

Step 2: Text Input Fields

Add username and email inputs:

<div style={{ marginBottom: '20px' }}>
  <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
    Username
  </label>
  <TextInput
    placeholder="Enter your username"
    value={formData.username}
    onChange={(e) => setFormData({ ...formData, username: e.target.value })}
    style={{ width: '100%' }}
  />
</div>

<div style={{ marginBottom: '20px' }}>
  <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
    Email
  </label>
  <TextInput
    type="email"
    placeholder="player@example.com"
    value={formData.email}
    onChange={(e) => setFormData({ ...formData, email: e.target.value })}
    style={{ width: '100%' }}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Step 3: TextArea for Bio

Add a multiline bio field:

<div style={{ marginBottom: '20px' }}>
  <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
    Bio
  </label>
  <TextArea
    placeholder="Tell us about yourself..."
    value={formData.bio}
    onChange={(e) => setFormData({ ...formData, bio: e.target.value })}
    rows={4}
    style={{ width: '100%' }}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Step 4: Select Dropdown

Add an experience level selector:

<div style={{ marginBottom: '20px' }}>
  <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
    Experience Level
  </label>
  <Select
    options={[
      { value: 'beginner', label: '🌱 Beginner' },
      { value: 'intermediate', label: '⚔️ Intermediate' },
      { value: 'expert', label: '👑 Expert' },
      { value: 'legend', label: '🏆 Legend' }
    ]}
    value={formData.experience}
    onChange={(value) => setFormData({ ...formData, experience: value })}
    style={{ width: '100%' }}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Step 5: Switch Toggle

Add a notification preference toggle:

<div style={{ marginBottom: '30px' }}>
  <Switch
    checked={formData.notifications}
    onChange={(checked) => setFormData({ ...formData, notifications: checked })}
    label="Enable Notifications"
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Step 6: Submit Button

Add the form submission button:

<Button
  onClick={() => setShowConfirm(true)}
  style={{ width: '100%', padding: '15px' }}
>
  💾 Save Profile
</Button>
Enter fullscreen mode Exit fullscreen mode

Step 7: Confirmation Modal

Add a modal for confirming the save:

<Modal
  isOpen={showConfirm}
  onClose={() => setShowConfirm(false)}
  title="Confirm Save"
>
  <div style={{ marginBottom: '20px' }}>
    <p>Save profile for <strong>{formData.username}</strong>?</p>
    <div style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
      <div>📧 {formData.email}</div>
      <div>⚔️ {formData.experience}</div>
      <div>🔔 {formData.notifications ? 'On' : 'Off'}</div>
    </div>
  </div>

  <div style={{ display: 'flex', gap: '10px' }}>
    <Button
      onClick={() => {
        console.log('Saving profile:', formData);
        setShowConfirm(false);
        alert('Profile saved! 🎉');
      }}
      style={{ flex: 1 }}
    >
      ✓ Confirm
    </Button>
    <Button
      onClick={() => setShowConfirm(false)}
      variant="secondary"
      style={{ flex: 1 }}
    >
      ✗ Cancel
    </Button>
  </div>
</Modal>
Enter fullscreen mode Exit fullscreen mode

Step 8: Use the Component

Update your src/App.js:

import ProfileForm from './ProfileForm';
import './App.css';

function App() {
  return (
    <div className="App" style={{ 
      minHeight: '100vh',
      background: 'linear-gradient(to bottom, #1a1a2e, #0f0f1e)',
      color: '#fff',
      padding: '20px'
    }}>
      <ProfileForm />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Complete Code

Here's the full ProfileForm.jsx:

import { useState } from 'react';
import {
  Button,
  TextInput,
  TextArea,
  Select,
  Switch,
  Modal
} from 'pixelartui-react';

function ProfileForm() {
  const [formData, setFormData] = useState({
    username: '',
    email: '',
    bio: '',
    experience: 'beginner',
    notifications: true
  });

  const [showConfirm, setShowConfirm] = useState(false);

  return (
    <div style={{ 
      maxWidth: '600px', 
      margin: '50px auto', 
      padding: '20px',
      fontFamily: 'Pixelify Sans, monospace'
    }}>
      <h1 style={{ textAlign: 'center', marginBottom: '30px' }}>
        🎮 Player Profile
      </h1>

      <div style={{ marginBottom: '20px' }}>
        <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
          Username
        </label>
        <TextInput
          placeholder="Enter your username"
          value={formData.username}
          onChange={(e) => setFormData({ ...formData, username: e.target.value })}
          style={{ width: '100%' }}
        />
      </div>

      <div style={{ marginBottom: '20px' }}>
        <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
          Email
        </label>
        <TextInput
          type="email"
          placeholder="player@example.com"
          value={formData.email}
          onChange={(e) => setFormData({ ...formData, email: e.target.value })}
          style={{ width: '100%' }}
        />
      </div>

      <div style={{ marginBottom: '20px' }}>
        <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
          Bio
        </label>
        <TextArea
          placeholder="Tell us about yourself..."
          value={formData.bio}
          onChange={(e) => setFormData({ ...formData, bio: e.target.value })}
          rows={4}
          style={{ width: '100%' }}
        />
      </div>

      <div style={{ marginBottom: '20px' }}>
        <label style={{ display: 'block', marginBottom: '8px', fontWeight: 'bold' }}>
          Experience Level
        </label>
        <Select
          options={[
            { value: 'beginner', label: '🌱 Beginner' },
            { value: 'intermediate', label: '⚔️ Intermediate' },
            { value: 'expert', label: '👑 Expert' },
            { value: 'legend', label: '🏆 Legend' }
          ]}
          value={formData.experience}
          onChange={(value) => setFormData({ ...formData, experience: value })}
          style={{ width: '100%' }}
        />
      </div>

      <div style={{ marginBottom: '30px' }}>
        <Switch
          checked={formData.notifications}
          onChange={(checked) => setFormData({ ...formData, notifications: checked })}
          label="Enable Notifications"
        />
      </div>

      <Button
        onClick={() => setShowConfirm(true)}
        style={{ width: '100%', padding: '15px' }}
      >
        💾 Save Profile
      </Button>

      <Modal
        isOpen={showConfirm}
        onClose={() => setShowConfirm(false)}
        title="Confirm Save"
      >
        <div style={{ marginBottom: '20px' }}>
          <p>Save profile for <strong>{formData.username}</strong>?</p>
          <div style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
            <div>📧 {formData.email}</div>
            <div>⚔️ {formData.experience}</div>
            <div>🔔 {formData.notifications ? 'On' : 'Off'}</div>
          </div>
        </div>

        <div style={{ display: 'flex', gap: '10px' }}>
          <Button
            onClick={() => {
              console.log('Saving profile:', formData);
              setShowConfirm(false);
              alert('Profile saved! 🎉');
            }}
            style={{ flex: 1 }}
          >
            ✓ Confirm
          </Button>
          <Button
            onClick={() => setShowConfirm(false)}
            variant="secondary"
            style={{ flex: 1 }}
          >
            ✗ Cancel
          </Button>
        </div>
      </Modal>
    </div>
  );
}

export default ProfileForm;
Enter fullscreen mode Exit fullscreen mode

Customization Tips

Theming

pixelartui-react supports theming. You can customize colors to match your brand:

import { ThemeProvider } from 'pixelartui-react';

const customTheme = {
  primary: '#ff006e',
  secondary: '#8338ec',
  background: '#1a1a2e',
  text: '#ffffff'
};

<ThemeProvider theme={customTheme}>
  <ProfileForm />
</ThemeProvider>
Enter fullscreen mode Exit fullscreen mode

Component Variants

Many components support different variants:

<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="danger">Danger</Button>
Enter fullscreen mode Exit fullscreen mode

Size Options

Adjust component sizes:

<Button size="small">Small</Button>
<Button size="medium">Medium</Button>
<Button size="large">Large</Button>
Enter fullscreen mode Exit fullscreen mode

Additional Components

pixelartui-react includes other useful components:

Pagination

import { Pagination } from 'pixelartui-react';

<Pagination
  currentPage={currentPage}
  totalPages={10}
  onPageChange={(page) => setCurrentPage(page)}
/>
Enter fullscreen mode Exit fullscreen mode

Box Container

import { Box } from 'pixelartui-react';

<Box title="Inventory">
  <p>Your items here</p>
</Box>
Enter fullscreen mode Exit fullscreen mode

Pixel Component

For custom pixel art elements:

import { Pixel } from 'pixelartui-react';

<Pixel color="#ff0000" size={8} />
Enter fullscreen mode Exit fullscreen mode

Use Cases

pixelartui-react is perfect for:

  • 🎮 Web-based games - UI that matches your pixel art assets
  • 🎨 Creative portfolios - Stand out with a unique aesthetic
  • 🏆 Hackathon projects - Rapid prototyping with character
  • 💎 NFT/Web3 projects - Retro vibes for digital collectibles
  • 📚 Educational apps - Engaging UI for learning platforms

What's Next?

The pixelartui-react roadmap includes:

  • More components (Tabs, Tooltips, Dropdowns, Progress bars)
  • Animation system for retro transitions
  • Visual theme builder
  • Storybook documentation
  • Additional style variants (8-bit, 16-bit, 32-bit)

Get Involved

pixelartui-react is open source and community-driven!

Conclusion

Building retro UIs doesn't have to be time-consuming. With pixelartui-react, you get production-ready pixel art components that bring character to your React applications.

Whether you're building the next browser game hit or just want your portfolio to stand out, pixelartui-react offers a polished, customizable solution.

Give it a try and let me know what you build! Drop a comment with your projects or questions.

Happy coding, and may your pixels be perfectly aligned! 🎮✨
Have questions? Drop them in the comments below!

Top comments (0)