Skip to main content
The Experience component displays professional work history in a Spotify playlist-inspired design with interactive playback-style controls.

Overview

Location: src/app/components/sections/ExperienceItems.tsx This component mimics a Spotify playlist interface to present professional experience in an engaging, familiar format. It features playlist-style controls and a scrollable list of positions.

Implementation

export default function ExperienceItem() {
  return (
    <section
      className="relative col-span-2 row-span-4 col-start-3 bg-spotify-light-dark rounded-xl max-md:overflow-y-scroll overflow-hidden max-md:col-span-1"
      id="experience"
    >
      <div className="bg-spotify-gray px-6 py-4">
        <h2 className="text-xl font-semibold mb-1">Professional Experience</h2>
        <p className="flex items-center gap-1.5 text-spotify-grey text-sm">
          <CiGlobe className="text-lg" />
          8 positions • 3+ internship experience
        </p>
      </div>

      <div className="px-4 py-3">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-4">
            <button 
              className="rounded-full bg-spotify-green p-3.5 hover:scale-105 transition-transform"
              aria-label="Play experience showcase"
            >
              <FaPlay className="text-spotify-black text-sm" />
            </button>
            <div className="flex items-center gap-5">
              <button aria-label="Shuffle experiences">
                <IoShuffle className="text-3xl text-spotify-grey sm:hover:text-white transition-colors" />
              </button>
              <button aria-label="Add to favorites">
                <FiPlusCircle className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
              </button>
              <button aria-label="Download resume">
                <MdOutlineDownloadForOffline className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
              </button>
              <button aria-label="More options">
                <BsThreeDots className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
              </button>
            </div>
          </div>
          <button aria-label="View list">
            <RxHamburgerMenu className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
          </button>
        </div>
      </div>

      <Positions />
    </section>
  );
}

Features

Header Section

The header displays aggregate experience statistics:
<div className="bg-spotify-gray px-6 py-4">
  <h2 className="text-xl font-semibold mb-1">Professional Experience</h2>
  <p className="flex items-center gap-1.5 text-spotify-grey text-sm">
    <CiGlobe className="text-lg" />
    8 positions • 3+ internship experience
  </p>
</div>
Title
string
Section heading: “Professional Experience”
Statistics
string
Total positions count and internship experience summary

Playback Controls

Spotify-style controls for thematic consistency:
While styled as playback controls, these buttons serve as decorative UI elements that reinforce the Spotify theme.

Primary Play Button

<button 
  className="rounded-full bg-spotify-green p-3.5 hover:scale-105 transition-transform"
  aria-label="Play experience showcase"
>
  <FaPlay className="text-spotify-black text-sm" />
</button>
  • Prominent Spotify-green circular button
  • Scales up on hover for interactive feedback

Secondary Controls

<div className="flex items-center gap-5">
  <button aria-label="Shuffle experiences">
    <IoShuffle className="text-3xl text-spotify-grey sm:hover:text-white transition-colors" />
  </button>
  <button aria-label="Add to favorites">
    <FiPlusCircle className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
  </button>
  <button aria-label="Download resume">
    <MdOutlineDownloadForOffline className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
  </button>
  <button aria-label="More options">
    <BsThreeDots className="text-2xl text-spotify-grey sm:hover:text-white transition-colors" />
  </button>
</div>
Control icons:
  • Shuffle (IoShuffle): Randomize order
  • Plus (FiPlusCircle): Add to favorites
  • Download (MdOutlineDownloadForOffline): Download resume
  • More (BsThreeDots): Additional options
All control buttons include hover effects that change color from grey to white, matching Spotify’s interaction patterns.

Positions Component

Implementation

function Positions() {
  return (
    <div className="px-4 pb-4 md:overflow-y-auto sm:h-[300px]">
      {experienceLists.map((position: experienceListsProps, index: number) => (
        <div
          className="flex items-center gap-4 p-2.5 sm:hover:bg-[#282828] rounded-lg transition-colors group"
          key={position.companyName}
        >
          <span className="text-spotify-grey sm:group-hover:text-white min-w-[20px]">
            {index + 1}
          </span>
          <div className="flex flex-col gap-0.5">
            <a
              href={position.url}
              target="_blank"
              rel="noopener noreferrer"
              className="text-spotify-green text-sm font-semibold mb-0.5 bg-spotify-green/20 rounded-md transition-all duration-200 w-fit px-2 py-0.5 hover:bg-spotify-green/10 cursor-pointer"
            >
              {position.companyName}
            </a>
            <p className="font-bold text-md mb-0.5">{position.positionTitle}</p>
            <p className="text-spotify-gray text-sm">{position.date}</p>
          </div>
        </div>
      ))}
    </div>
  );
}

Position Data Structure

Experience data is imported from a centralized data file:
import {
  experienceLists,
  experienceListsProps,
} from "../../../../data/experience";
companyName
string
required
Company or organization name
url
string
required
Link to company website
positionTitle
string
required
Job title or role
date
string
required
Employment date range

Position Row Layout

Each position displays as a numbered row:
<div className="flex items-center gap-4 p-2.5 sm:hover:bg-[#282828] rounded-lg transition-colors group">
  {/* Index number */}
  <span className="text-spotify-grey sm:group-hover:text-white min-w-[20px]">
    {index + 1}
  </span>
  
  {/* Position details */}
  <div className="flex flex-col gap-0.5">
    <a href={position.url} target="_blank" rel="noopener noreferrer">
      {position.companyName}
    </a>
    <p className="font-bold">{position.positionTitle}</p>
    <p className="text-spotify-gray text-sm">{position.date}</p>
  </div>
</div>

Interactive Elements

Row Hover Effect

sm:hover:bg-[#282828]  /* Background changes on hover */
group                   /* Enables child element coordination */
When hovering over a row:
  • Background color darkens
  • Index number changes from grey to white
<a
  className="text-spotify-green text-sm font-semibold mb-0.5 bg-spotify-green/20 rounded-md transition-all duration-200 w-fit px-2 py-0.5 hover:bg-spotify-green/10 cursor-pointer"
  href={position.url}
  target="_blank"
  rel="noopener noreferrer"
>
  {position.companyName}
</a>
Company names are displayed as badges with Spotify-green text on a semi-transparent background, creating visual hierarchy.

Grid Layout

Desktop Layout

.experience-item {
  grid-column: span 2;      /* Takes 2 columns */
  grid-row: span 4;         /* Takes 4 rows */
  grid-column-start: 3;     /* Starts at column 3 */
}

Mobile Responsive

  • Mobile: Single column (max-md:col-span-1)
  • Scrolling: Mobile uses overflow-y-scroll, desktop uses fixed height with scrollable content area
  • Height: Content area fixed at sm:h-[300px] for consistent scrolling

Styling Details

Color Scheme

/* Header background */
bg-spotify-gray          /* #282828 */

/* Card background */
bg-spotify-light-dark    /* #121212 */

/* Text colors */
text-spotify-grey        /* #B3B3B3 - for metadata */
text-spotify-green       /* #1DB954 - for company names */
text-white               /* Primary text */

/* Hover states */
hover:text-white         /* Control buttons on hover */
hover:bg-[#282828]       /* Row background on hover */

Spacing and Layout

  • Header padding: px-6 py-4
  • Controls padding: px-4 py-3
  • Positions padding: px-4 pb-4
  • Row padding: p-2.5
  • Gap between controls: gap-5
  • Gap in position details: gap-0.5

Scrolling Behavior

Fixed height container with scrollable positions list:
md:overflow-y-auto sm:h-[300px]

Accessibility

  • Semantic HTML with <section> for the main container
  • ARIA labels for all interactive buttons:
    • “Play experience showcase”
    • “Shuffle experiences”
    • “Add to favorites”
    • “Download resume”
    • “More options”
    • “View list”
  • External links include rel="noopener noreferrer" for security
  • Proper heading hierarchy (<h2> for section title)

Dependencies

{
  "react-icons/ci": "CiGlobe",
  "react-icons/io5": "IoShuffle",
  "react-icons/fi": "FiPlusCircle",
  "react-icons/md": "MdOutlineDownloadForOffline",
  "react-icons/bs": "BsThreeDots",
  "react-icons/rx": "RxHamburgerMenu",
  "react-icons/fa": "FaPlay"
}
Experience data is externalized in data/experience.ts for easy maintenance and updates without modifying component code.

Build docs developers (and LLMs) love