Fix #134: Cosmetic title replaces clickable username on leaderboard #137

Merged
typosaurus merged 1 commits from typosaurus/ticket-134 into master 2026-07-26 23:27:59 +02:00
Collaborator

Resolves #134.

Plan

Implementation Plan: Fix leaderboard username squeeze when a title is equipped

Root Cause

In devplacepy/static/css/game.css, the leaderboard row uses flex layout. The username link (.game-lb-name) has flex: 1; min-width: 0, making it shrink to zero when the total row width is exceeded. The title (.game-lb-title) has flex-shrink: 0, so it never shrinks. When a long title like "Serial Refactorer" is present, the username collapses to ~1 pixel, becoming invisible (only an ellipsis shown).

Change Summary

Restructure the leaderboard row in the JavaScript template (GameFarm.js) and update corresponding CSS (game.css) so that the username and title are stacked vertically inside a flex column container, rather than competing on the same horizontal line.

Specifically:

  • In the JS template, wrap the <a class="game-lb-name"> and the optional <span class="game-lb-title"> in a new div with a class game-lb-name-group.
  • Adjust the CSS so that .game-lb-name-group is a flex column (no gap), the name link retains clickable styling, and the title is a small italic line below the name.
  • Ensure the overall row still fits within the container and the username never gets hidden.

Files to Modify

  1. devplacepy/static/js/GameFarm.js – lines 370–374
    Change the template literal to wrap the name and title in a container.

  2. devplacepy/static/css/game.css – lines 224–271
    Update .game-lb-row, .game-lb-name, .game-lb-title rules to accommodate the new structure.
    Remove the conflicting flex: 1; min-width: 0 from .game-lb-name.
    Add .game-lb-name-group styling.

  3. Optional but recommended: tests/e2e/game/index.py – add a new test case that equips a title and asserts the username link is visible and clickable.

Detailed Steps

Step 1: Modify the JavaScript template (GameFarm.js)

Current (lines 370–374):

const title = entry.title ? `<span class="game-lb-title">${entry.title}</span>` : "";
const value = this._leaderboardValue(board, entry);
return `<li class="game-lb-row${entry.username === this.username ? " game-lb-self" : ""}">
  <span class="game-lb-rank">#${entry.rank}</span>
  <a class="game-lb-name" href="/game/farm/${entry.username}">${entry.username}</a>
  ${title}
  <span class="game-lb-level">Lv ${entry.level}</span>
  <span class="game-lb-score">${value}</span>
</li>`;

New:

const title = entry.title ? `<span class="game-lb-title">${entry.title}</span>` : "";
const value = this._leaderboardValue(board, entry);
return `<li class="game-lb-row${entry.username === this.username ? " game-lb-self" : ""}">
  <span class="game-lb-rank">#${entry.rank}</span>
  <div class="game-lb-name-group">
    <a class="game-lb-name" href="/game/farm/${entry.username}">${entry.username}</a>
    ${title}
  </div>
  <span class="game-lb-level">Lv ${entry.level}</span>
  <span class="game-lb-score">${value}</span>
</li>`;

Step 2: Update CSS (game.css)

Remove or replace the following:

  • .game-lb-name (line 244–254): change flex: 1 → remove flex properties, keep link styling (font-weight: 600, text-decoration: none, etc.). Add white-space: nowrap; overflow: hidden; text-overflow: ellipsis; so that if the username itself is very long it still truncates, but it will now have a minimum width via its container.
  • .game-lb-title (line 266–271): remove flex-shrink: 0; because it's no longer a direct child of the row. Keep font-style: italic; color: var(--accent); and add display: block; (or inline-block) and font-size: 0.75rem; to appear on a second line.

Add new rule:

.game-lb-name-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1;                         /* take remaining space */
  min-width: 0;
  overflow: hidden;                /* clip if name + title overflow horizontally */
}

Adjust .game-lb-row (line 224): no changes needed; still display: flex; align-items: center; gap: var(--space-sm);.

Adjust .game-lb-rank, .game-lb-level, .game-lb-score: they keep their flex-shrink: 0 and fixed widths.

Add a test in tests/e2e/game/index.py that:

  1. Equips a known title (e.g., "Serial Refactorer" from cosmetics shop).
  2. Opens the game page.
  3. Asserts that the username link is visible, has the correct href, and that the title text is also visible.

Example:

def test_leaderboard_shows_username_and_title(alice):
    page, _ = alice
    reset_farm("alice_test")
    # equip title "Serial Refactorer"
    page.goto("/game/farm/alice_test/shop")
    # ... (locate and click equip for that title)
    open_game(page)
    page.locator(".game-lb-row").first.wait_for(state="visible")
    # username must be visible and clickable
    link = page.locator("a.game-lb-name[href='/game/farm/alice_test']")
    expect(link).to_be_visible()
    expect(link).to_have_text("alice_test")
    # title must be rendered
    title_span = page.locator(".game-lb-title")
    expect(title_span).to_be_visible()
    expect(title_span).to_have_text("Serial Refactorer")

Place this test after test_leaderboard_panel_populates (line 290).

Verification (Definition of Done)

  • The CSS change is applied correctly: inspect a row with a title equipped; the username is fully visible, forms a link to the player’s farm page, and the title is shown as an italic badge on a new line below the username.
  • All existing unit/integration tests pass when running the project’s own test command:
    pip install -e '.[dev]' -q && python -m pytest tests/
    (If any pre-existing failures occur, they are unrelated to this change; no new failures are introduced.)
  • The E2E test test_leaderboard_shows_username_and_title (if added) passes.
  • Manual verification in a browser:
    1. Log in and equip a cosmetic title like "Serial Refactorer" via the shop.
    2. Navigate to /game.
    3. Confirm the player’s row on the leaderboard shows the clickable username link on the first line and the title on a second line.
    4. Click the username link – it navigates to the player’s farm page.

The above plan addresses the root CSS conflict without altering backend logic or the data schema. It ensures the username link always remains clearly visible and functional, even with the longest currently defined titles (e.g., "Serial Refactorer" at ~15 characters).

Opened automatically by Typosaurus.

Resolves #134. ## Plan ## Implementation Plan: Fix leaderboard username squeeze when a title is equipped ### Root Cause In `devplacepy/static/css/game.css`, the leaderboard row uses flex layout. The username link (`.game-lb-name`) has `flex: 1; min-width: 0`, making it shrink to zero when the total row width is exceeded. The title (`.game-lb-title`) has `flex-shrink: 0`, so it never shrinks. When a long title like "Serial Refactorer" is present, the username collapses to ~1 pixel, becoming invisible (only an ellipsis shown). ### Change Summary Restructure the leaderboard row in the JavaScript template (`GameFarm.js`) and update corresponding CSS (`game.css`) so that the username and title are stacked vertically inside a flex column container, rather than competing on the same horizontal line. Specifically: - In the JS template, wrap the `<a class="game-lb-name">` and the optional `<span class="game-lb-title">` in a new `div` with a class `game-lb-name-group`. - Adjust the CSS so that `.game-lb-name-group` is a flex column (no gap), the name link retains clickable styling, and the title is a small italic line below the name. - Ensure the overall row still fits within the container and the username never gets hidden. ### Files to Modify 1. **`devplacepy/static/js/GameFarm.js`** – lines 370–374 Change the template literal to wrap the name and title in a container. 2. **`devplacepy/static/css/game.css`** – lines 224–271 Update `.game-lb-row`, `.game-lb-name`, `.game-lb-title` rules to accommodate the new structure. Remove the conflicting `flex: 1; min-width: 0` from `.game-lb-name`. Add `.game-lb-name-group` styling. 3. **Optional but recommended: `tests/e2e/game/index.py`** – add a new test case that equips a title and asserts the username link is visible and clickable. ### Detailed Steps #### Step 1: Modify the JavaScript template (`GameFarm.js`) **Current (lines 370–374):** ```javascript const title = entry.title ? `<span class="game-lb-title">${entry.title}</span>` : ""; const value = this._leaderboardValue(board, entry); return `<li class="game-lb-row${entry.username === this.username ? " game-lb-self" : ""}"> <span class="game-lb-rank">#${entry.rank}</span> <a class="game-lb-name" href="/game/farm/${entry.username}">${entry.username}</a> ${title} <span class="game-lb-level">Lv ${entry.level}</span> <span class="game-lb-score">${value}</span> </li>`; ``` **New:** ```javascript const title = entry.title ? `<span class="game-lb-title">${entry.title}</span>` : ""; const value = this._leaderboardValue(board, entry); return `<li class="game-lb-row${entry.username === this.username ? " game-lb-self" : ""}"> <span class="game-lb-rank">#${entry.rank}</span> <div class="game-lb-name-group"> <a class="game-lb-name" href="/game/farm/${entry.username}">${entry.username}</a> ${title} </div> <span class="game-lb-level">Lv ${entry.level}</span> <span class="game-lb-score">${value}</span> </li>`; ``` #### Step 2: Update CSS (`game.css`) **Remove or replace the following:** - `.game-lb-name` (line 244–254): change `flex: 1` → remove flex properties, keep link styling (`font-weight: 600`, `text-decoration: none`, etc.). Add `white-space: nowrap; overflow: hidden; text-overflow: ellipsis;` so that if the username itself is very long it still truncates, but it will now have a minimum width via its container. - `.game-lb-title` (line 266–271): remove `flex-shrink: 0;` because it's no longer a direct child of the row. Keep `font-style: italic; color: var(--accent);` and add `display: block;` (or `inline-block`) and `font-size: 0.75rem;` to appear on a second line. **Add new rule:** ```css .game-lb-name-group { display: flex; flex-direction: column; align-items: flex-start; flex: 1; /* take remaining space */ min-width: 0; overflow: hidden; /* clip if name + title overflow horizontally */ } ``` **Adjust `.game-lb-row` (line 224):** no changes needed; still `display: flex; align-items: center; gap: var(--space-sm);`. **Adjust `.game-lb-rank`, `.game-lb-level`, `.game-lb-score`:** they keep their `flex-shrink: 0` and fixed widths. #### Step 3: Update E2E test (optional but recommended) Add a test in `tests/e2e/game/index.py` that: 1. Equips a known title (e.g., "Serial Refactorer" from cosmetics shop). 2. Opens the game page. 3. Asserts that the username link is visible, has the correct `href`, and that the title text is also visible. Example: ```python def test_leaderboard_shows_username_and_title(alice): page, _ = alice reset_farm("alice_test") # equip title "Serial Refactorer" page.goto("/game/farm/alice_test/shop") # ... (locate and click equip for that title) open_game(page) page.locator(".game-lb-row").first.wait_for(state="visible") # username must be visible and clickable link = page.locator("a.game-lb-name[href='/game/farm/alice_test']") expect(link).to_be_visible() expect(link).to_have_text("alice_test") # title must be rendered title_span = page.locator(".game-lb-title") expect(title_span).to_be_visible() expect(title_span).to_have_text("Serial Refactorer") ``` Place this test after `test_leaderboard_panel_populates` (line 290). ### Verification (Definition of Done) - [ ] The CSS change is applied correctly: inspect a row with a title equipped; the username is fully visible, forms a link to the player’s farm page, and the title is shown as an italic badge on a new line below the username. - [ ] All existing unit/integration tests pass when running the project’s own test command: `pip install -e '.[dev]' -q && python -m pytest tests/` (If any pre-existing failures occur, they are unrelated to this change; no new failures are introduced.) - [ ] The E2E test `test_leaderboard_shows_username_and_title` (if added) passes. - [ ] Manual verification in a browser: 1. Log in and equip a cosmetic title like "Serial Refactorer" via the shop. 2. Navigate to `/game`. 3. Confirm the player’s row on the leaderboard shows the clickable username link on the first line and the title on a second line. 4. Click the username link – it navigates to the player’s farm page. The above plan addresses the root CSS conflict without altering backend logic or the data schema. It ensures the username link always remains clearly visible and functional, even with the longest currently defined titles (e.g., "Serial Refactorer" at ~15 characters). Opened automatically by Typosaurus.
typosaurus added 1 commit 2026-07-25 13:58:24 +02:00
ticket #134 attempt 1
Some checks failed
DevPlace CI / test (pull_request) Failing after 54m2s
1f320b45ec
typosaurus merged commit b5fb6436d0 into master 2026-07-26 23:27:59 +02:00
typosaurus deleted branch typosaurus/ticket-134 2026-07-26 23:28:12 +02:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: retoor/devplacepy#137
No description provided.