Skip to content

Improve mobile UX for RoomBrowser by switching table to card layout on small screens #276

@JaYRaNa213

Description

@JaYRaNa213

Description

The current RoomBrowser component renders a table for all screen sizes.
On mobile devices, this results in horizontal scrolling due to long Room IDs and multiple columns, which negatively impacts usability.

Although overflow-x-auto prevents layout breaking, horizontal scrolling tables are not a good mobile UX pattern.

Current Behavior

RoomBrowser.tsx always renders a table

On mobile:

Requires horizontal scrolling
Action buttons are cramped
Room IDs cause layout overflow

Expected Behavior :

  • Desktop: keep the existing table layout
  • Mobile: display rooms as stacked cards (vertical layout)
  • No change in data, logic, or API behavior

Proposed Solution

  • Render card-based layout on mobile (sm:hidden)
  • Render table layout on desktop (hidden sm:block)
  • Reuse existing handlers (handleJoinMatch, handleViewDebate)
  • No backend or API changes

Files to be Updated

src/components/RoomBrowser.tsx

Implementation Plan (Simple & Safe)

  1. Keep existing table (desktop only)

Wrap your existing table JSX like this:

<div className="hidden sm:block overflow-x-auto">
  {/* existing table exactly as-is */}
</div>

2.Add a mobile card layout (new JSX)

<div className="sm:hidden space-y-4">
  {rooms.map((room) => {
    const memberCount = room.participants?.length || 0;
    const avgElo = getAverageElo(room.participants);

    return (
      <div
        key={room.id}
        className="border border-border rounded-lg p-4 bg-card shadow"
      >
        <p className="text-sm text-muted-foreground">Room ID</p>
        <p className="font-mono text-sm break-all mb-2">{room.id}</p>

        <div className="flex justify-between text-sm mb-2">
          <span>Type</span>
          <span className="font-semibold">{room.type.toUpperCase()}</span>
        </div>

        <div className="flex justify-between text-sm mb-2">
          <span>Members</span>
          <span>{memberCount > 0 ? memberCount : 'Empty'}</span>
        </div>

        <div className="flex justify-between text-sm mb-4">
          <span>Avg Elo</span>
          <span>{memberCount > 0 ? avgElo : '--'}</span>
        </div>

        <div className="flex gap-2">
          <button
            onClick={() => handleJoinMatch(room.id)}
            className="flex-1 bg-primary text-primary-foreground py-2 rounded"
          >
            Join
          </button>

          <button
            onClick={() => handleViewDebate(room.id)}
            className="flex-1 bg-secondary text-secondary-foreground py-2 rounded"
          >
            View
          </button>
        </div>
      </div>
    );
  })}
</div>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions