Skip to content

Feat: Name Layer text opacity setting#3450

Open
bijx wants to merge 9 commits intomainfrom
player-text-opacity
Open

Feat: Name Layer text opacity setting#3450
bijx wants to merge 9 commits intomainfrom
player-text-opacity

Conversation

@bijx
Copy link
Contributor

@bijx bijx commented Mar 17, 2026

Description:

It's really hard sometimes to see what buildings or features are under those big text letters of people's nametags and troop counts on the map (also reported by users on the Discord). This PR adds a setting for opacity of the name and troop count in the NameLayer, allowing users to change the opacity via a slider in both lobby settings and in-game settings. Setting the opacity to 0% will also hide the flag, but opacity changes do not change the opacity of a nation/player's flag since it already has transparency applied to it. This does not affect gameplay critical icons such as alliance break, incoming alliance request, alliance notification, nukes, crowns, emojis, etc. (see below)

Video Demo

Recording.2026-03-17.020418.mp4

Setting on Lobby Menu

Screen.Recording.2026-03-17.020514.mp4

Emojis and other icons intact (when hidden)

image image

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

bijx

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 264dddf9-850b-4fe4-91c7-7205ac4f1088

📥 Commits

Reviewing files that changed from the base of the PR and between f9b8f97 and f088835.

📒 Files selected for processing (1)
  • resources/lang/en.json
✅ Files skipped from review due to trivial changes (1)
  • resources/lang/en.json

Walkthrough

Adds a configurable player-name opacity: new translations, user settings getter/setter, slider UI in two modals, SettingSlider zero-label support, and rendering updates that apply per-player label opacity and hide flags when opacity is 0.

Changes

Cohort / File(s) Summary
Translations
resources/lang/en.json
Added main.user_setting.player_name_opacity_label, main.user_setting.player_name_opacity_desc, and main.user_setting.hidden.
User settings
src/core/game/UserSettings.ts
Added playerNameOpacity() and setPlayerNameOpacity() with rounding, clamping to [0,100], finite-value guarding, and persistence via existing storage API.
Slider component
src/client/components/baseComponents/setting/SettingSlider.ts
Added reactive zeroLabelKey property and valueText logic to render a translated label when value is 0 instead of showing 0%.
Settings UI / Modals
src/client/UserSettingModal.ts, src/client/graphics/layers/SettingsModal.ts
Added slider control and input handlers: sliderPlayerNameOpacity(...) in UserSettingModal and onPlayerNameOpacityChange(...) in SettingsModal, wired to userSettings getter/setter and UI updates.
Rendering / Name layer
src/client/graphics/layers/NameLayer.ts
On render, read userSettings.playerNameOpacity() (0–100), convert to 0..1, set nameSpan.style.opacity and troopsDiv.style.opacity, and set flagDiv.style.display = "none" when opacity is 0 (else reset). Guard DOM element access before updates.

Sequence Diagram(s)

sequenceDiagram
  participant UI as Client UI (slider)
  participant Settings as UserSettings
  participant Renderer as NameLayer / DOM

  UI->>Settings: setPlayerNameOpacity(value)
  Settings-->>UI: persist & acknowledge
  UI->>Renderer: request re-render
  Renderer->>Settings: playerNameOpacity()
  Settings-->>Renderer: current opacity (0-100)
  Renderer->>DOM: update nameSpan.style.opacity, troopsDiv.style.opacity
  alt opacity == 0
    Renderer->>DOM: set flagDiv.style.display = "none"
  else
    Renderer->>DOM: reset flagDiv.style.display
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A tiny slider, smooth and bright,
Numbers dim into the night,
When zero comes the flags retreat,
Names fade softly, small and neat,
Maps breathe easy — calm delight.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat: Name Layer text opacity setting' directly and clearly summarizes the main change: adding an opacity setting for the NameLayer text.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the motivation, implementation details, user-facing features, and testing completed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can enable review details to help with troubleshooting, context usage and more.

Enable the reviews.review_details setting to include review details such as the model used, the time taken for each step and more in the review comments.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/client/graphics/layers/SettingsModal.ts (1)

462-493: Prefer reusing <setting-slider> here to avoid logic drift.

This block duplicates slider rendering/value-label logic already implemented in src/client/components/baseComponents/setting/SettingSlider.ts (including the zero-value translated label). Reusing the shared component will keep behavior consistent between both settings modals.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/graphics/layers/SettingsModal.ts` around lines 462 - 493, This
block duplicates the slider and zero-value label logic; replace it with the
shared SettingSlider component (tag <setting-slider> / component implementation
in SettingSlider.ts) to avoid drift: render <setting-slider> bound to
this.userSettings.playerNameOpacity(), pass the same min/max (0/100), wire its
input/change handler to onPlayerNameOpacityChange (or use the component's change
event), and remove the duplicated percent/hidden label logic since SettingSlider
already handles zero-value translation via translateText; ensure value source
remains this.userSettings.playerNameOpacity() and event handler name matches the
existing method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/client/graphics/layers/NameLayer.ts`:
- Around line 342-345: Replace the unsafe innerHTML assignment for player names
with a safe text assignment: locate the code in NameLayer.ts where
nameDiv.querySelector(".player-name-span") is stored in span and currently calls
span.innerHTML = render.player.name(); and change it to set span.textContent (or
assign to (span as HTMLElement).textContent) while keeping the opacity logic
that uses nameOpacity intact; ensure you use render.player.name() only as text
(no HTML parsing) so player-controlled input cannot inject markup.

In `@src/core/game/UserSettings.ts`:
- Around line 249-252: setPlayerNameOpacity currently allows NaN through into
clampedOpacity and then setFloat which persists and emits "NaN"; guard against
non-finite inputs by validating the incoming opacity with
Number.isFinite(opacity) (or isFinite) before rounding and clamping, and if it's
not finite either return early (no save/emit) or default to a safe value (e.g.,
0), then compute const clampedOpacity = Math.max(0, Math.min(100,
Math.round(opacity))) and call this.setFloat("settings.playerNameOpacity",
clampedOpacity).

---

Nitpick comments:
In `@src/client/graphics/layers/SettingsModal.ts`:
- Around line 462-493: This block duplicates the slider and zero-value label
logic; replace it with the shared SettingSlider component (tag <setting-slider>
/ component implementation in SettingSlider.ts) to avoid drift: render
<setting-slider> bound to this.userSettings.playerNameOpacity(), pass the same
min/max (0/100), wire its input/change handler to onPlayerNameOpacityChange (or
use the component's change event), and remove the duplicated percent/hidden
label logic since SettingSlider already handles zero-value translation via
translateText; ensure value source remains this.userSettings.playerNameOpacity()
and event handler name matches the existing method.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 229ede9c-496a-4d1e-bee2-868e0c5e57d9

📥 Commits

Reviewing files that changed from the base of the PR and between f356f09 and 0c0c50a.

📒 Files selected for processing (6)
  • resources/lang/en.json
  • src/client/UserSettingModal.ts
  • src/client/components/baseComponents/setting/SettingSlider.ts
  • src/client/graphics/layers/NameLayer.ts
  • src/client/graphics/layers/SettingsModal.ts
  • src/core/game/UserSettings.ts

@github-project-automation github-project-automation bot moved this from Triage to Development in OpenFront Release Management Mar 17, 2026
@bijx bijx requested a review from a team as a code owner March 20, 2026 17:13
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 20, 2026
@bijx bijx added this to the v31 milestone Mar 20, 2026
@bijx bijx added the UI/UX UI/UX changes including assets, menus, QoL, etc. label Mar 20, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/client/graphics/layers/SettingsModal.ts (1)

490-520: UI section looks good, consider a more descriptive icon.

The slider control follows the same structure as other settings in this modal. The conditional display showing "Hidden" at 0% is a nice touch for clarity.

One small note: you're using the generic settingsIcon here. If there's a more specific icon available (like a text/label icon), it might help users visually locate this setting faster. Not a blocker.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/graphics/layers/SettingsModal.ts` around lines 490 - 520, Replace
the generic settingsIcon used in the player name opacity row with a more
specific label/text icon to improve discoverability: locate the SettingsModal
component where settingsIcon is used (the block rendering
this.userSettings.playerNameOpacity() and the input with
`@input`=${this.onPlayerNameOpacityChange}) and swap settingsIcon for a more
descriptive symbol (e.g., labelIcon or textIcon) from your existing icon set; if
that icon is not yet imported, add the appropriate import and use the specific
icon name so the UI shows a text/label glyph instead of the generic settings
gear.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/client/graphics/layers/SettingsModal.ts`:
- Around line 490-520: Replace the generic settingsIcon used in the player name
opacity row with a more specific label/text icon to improve discoverability:
locate the SettingsModal component where settingsIcon is used (the block
rendering this.userSettings.playerNameOpacity() and the input with
`@input`=${this.onPlayerNameOpacityChange}) and swap settingsIcon for a more
descriptive symbol (e.g., labelIcon or textIcon) from your existing icon set; if
that icon is not yet imported, add the appropriate import and use the specific
icon name so the UI shows a text/label glyph instead of the generic settings
gear.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93ff8954-ff31-4d75-9f20-3a8f750533d8

📥 Commits

Reviewing files that changed from the base of the PR and between 01c4e6d and ece32f4.

📒 Files selected for processing (4)
  • resources/lang/en.json
  • src/client/graphics/layers/NameLayer.ts
  • src/client/graphics/layers/SettingsModal.ts
  • src/core/game/UserSettings.ts
✅ Files skipped from review due to trivial changes (1)
  • src/client/graphics/layers/NameLayer.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • resources/lang/en.json

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

UI/UX UI/UX changes including assets, menus, QoL, etc.

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

1 participant