Better In Game UI (#1243)

## Description:
Top Bar Refactor – UI & UX Improvement Proposal

This update overhauls the top game bar to improve clarity,
responsiveness, and overall user experience across desktop and mobile.
It consolidates player resources (e.g., building counts), integrates
game controls (pause, settings, time), and enhances visual contrast.

Key changes:

Redesigned top bar with player data and game options.

Team color indicator bar (team games only).

Countdown bar during "Choose Starting Position" phase.

Removed redundant info (e.g., troop/worker counts shown elsewhere).

Inspired by strategy games like Travian Legends, this refactor offers a
cleaner and more intuitive layout, especially for smaller screens.

⚠️ Note: This is a large change and likely contains visual or functional
bugs I can’t currently spot due to fatigue. Thorough testing is required
before approval.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] 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
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

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

Diessel
![Snímek obrazovky 2025-06-21 v 8 13 46](https://github.c
![Snímek obrazovky 2025-06-21 v 8 13
35](https://github.com/user-attachments/assets/e166ee1b-6173-48f5-8e2d-598d796a7e2d)
om/user-attachments/assets/3a0edbef-e621-4fc4-b6b7-c1ed
![Snímek obrazovky 2025-06-21 v 8 13
20](https://github.com/user-attachments/assets/1214ab61-323c-4317-8722-eaa4b932a60c)
8f9a8219)
![Snímek obrazovky 2025-06-21 v 8 10
04](https://github.com/user-attachments/assets/374fe15a-bfad-4469-9950-3ec631b6e2d3)

Closes #1165

---------

Co-authored-by: Scott Anderson <scottanderson@users.noreply.github.com>
Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
DiesselOne
2025-06-30 19:49:42 -07:00
committed by GitHub
co-authored by Scott Anderson evanpelle
parent 91adf1fa8b
commit 4e48eba910
55 changed files with 795 additions and 715 deletions
+35 -77
View File
@@ -1,7 +1,6 @@
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import { customElement, property, state } from "lit/decorators.js";
import { EventBus } from "../../../core/EventBus";
import { GameType } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { ReplaySpeedChangeEvent } from "../../InputHandler";
import {
@@ -16,27 +15,26 @@ export class ReplayPanel extends LitElement implements Layer {
public game: GameView | undefined;
public eventBus: EventBus | undefined;
@property({ type: Boolean })
visible: boolean = false;
@state()
private _replaySpeedMultiplier: number = defaultReplaySpeedMultiplier;
private _isSinglePlayer: boolean = false;
@state()
private _isVisible = false;
@property({ type: Boolean })
isSingleplayer = false;
init() {
this._isSinglePlayer =
this.game?.config().gameConfig().gameType === GameType.Singleplayer;
if (this._isSinglePlayer) {
this.setVisible(true);
}
createRenderRoot() {
return this; // Enable Tailwind CSS
}
tick() {
if (!this._isVisible && this.game?.config().isReplay()) {
this.setVisible(true);
}
init() {}
this.requestUpdate();
tick() {
if (!this.visible) return;
if (this.game!.ticks() % 10 === 0) {
this.requestUpdate();
}
}
onReplaySpeedChange(value: ReplaySpeedMultiplier) {
@@ -44,85 +42,45 @@ export class ReplayPanel extends LitElement implements Layer {
this.eventBus?.emit(new ReplaySpeedChangeEvent(value));
}
renderLayer(context: CanvasRenderingContext2D) {
// Render any necessary canvas elements
}
shouldTransform(): boolean {
renderLayer(_ctx: CanvasRenderingContext2D) {}
shouldTransform() {
return false;
}
setVisible(visible: boolean) {
this._isVisible = visible;
this.requestUpdate();
}
render() {
if (!this._isVisible) {
return html``;
}
if (!this.visible) return html``;
return html`
<div
class="bg-opacity-60 bg-gray-900 p-1 lg:p-2 rounded-es-sm lg:rounded-lg backdrop-blur-md"
@contextmenu=${(e) => e.preventDefault()}
@contextmenu=${(e: Event) => e.preventDefault()}
>
<label class="block mb-1 text-white" translate="no">
${this._isSinglePlayer
${this.isSingleplayer
? translateText("replay_panel.game_speed")
: translateText("replay_panel.replay_speed")}
</label>
<div class="grid grid-cols-2 gap-1">
<button
class="text-white font-bold py-0 rounded border transition ${this
._replaySpeedMultiplier === ReplaySpeedMultiplier.slow
? "bg-blue-500 border-gray-400"
: "border-gray-500"}"
@click=${() => {
this.onReplaySpeedChange(ReplaySpeedMultiplier.slow);
}}
>
×0.5
</button>
<button
class="text-white font-bold py-0 rounded border transition ${this
._replaySpeedMultiplier === ReplaySpeedMultiplier.normal
? "bg-blue-500 border-gray-400"
: "border-gray-500"}"
@click=${() => {
this.onReplaySpeedChange(ReplaySpeedMultiplier.normal);
}}
>
×1
</button>
<button
class="text-white font-bold py-0 rounded border transition ${this
._replaySpeedMultiplier === ReplaySpeedMultiplier.fast
? "bg-blue-500 border-gray-400"
: "border-gray-500"}"
@click=${() => {
this.onReplaySpeedChange(ReplaySpeedMultiplier.fast);
}}
>
×2
</button>
<button
class="text-white font-bold py-0 rounded border transition ${this
._replaySpeedMultiplier === ReplaySpeedMultiplier.fastest
? "bg-blue-500 border-gray-400"
: "border-gray-500"}"
@click=${() => {
this.onReplaySpeedChange(ReplaySpeedMultiplier.fastest);
}}
>
max
</button>
${this.renderSpeedButton(ReplaySpeedMultiplier.slow, "×0.5")}
${this.renderSpeedButton(ReplaySpeedMultiplier.normal, "×1")}
${this.renderSpeedButton(ReplaySpeedMultiplier.fast, "×2")}
${this.renderSpeedButton(ReplaySpeedMultiplier.fastest, "max")}
</div>
</div>
`;
}
createRenderRoot() {
return this; // Disable shadow DOM to allow Tailwind styles
private renderSpeedButton(value: ReplaySpeedMultiplier, label: string) {
const isActive = this._replaySpeedMultiplier === value;
return html`
<button
class="text-white font-bold py-0 rounded border transition ${isActive
? "bg-blue-500 border-gray-400"
: "border-gray-500"}"
@click=${() => this.onReplaySpeedChange(value)}
>
${label}
</button>
`;
}
}