UI: Search Skin (#3552)

## Description:

Sorta fixes a visual bug:
<img width="1021" height="129" alt="image"
src="https://github.com/user-attachments/assets/2ea46fcd-d85c-4f46-a9b9-28c40b818269"
/>

By adding parity with the flag modal:

<img width="988" height="561" alt="image"
src="https://github.com/user-attachments/assets/29ca0b9f-3887-4867-b67b-8c35b026b021"
/>

(Parity
<img width="1032" height="342" alt="image"
src="https://github.com/user-attachments/assets/b9c551eb-047a-402f-8e7b-c207d967ff38"
/>
)

(code pretty much copy paste from flagmodal)

## 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
- [x] 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

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

w.o.n
This commit is contained in:
Ryan
2026-03-31 21:18:06 +01:00
committed by GitHub
parent a7d9652886
commit 9b4812f8b8
2 changed files with 35 additions and 1 deletions
+2 -1
View File
@@ -949,7 +949,8 @@
"default": "Default"
},
"select_skin": "Select Skin",
"selected": "selected"
"selected": "selected",
"search": "Search..."
},
"cosmetics": {
"artist_label": "Artist:"
+33
View File
@@ -22,6 +22,7 @@ export class TerritoryPatternsModal extends BaseModal {
@state() private selectedPattern: PlayerPattern | null;
@state() private selectedColor: string | null = null;
@state() private search = "";
private cosmetics: Cosmetics | null = null;
private userSettings: UserSettings = new UserSettings();
@@ -67,6 +68,15 @@ export class TerritoryPatternsModal extends BaseModal {
this.refresh();
}
private includedInSearch(name: string): boolean {
const displayName = name.replace(/_/g, " ");
return displayName.toLowerCase().includes(this.search.toLowerCase());
}
private handleSearch(event: Event) {
this.search = (event.target as HTMLInputElement).value;
}
private renderPatternGrid(): TemplateResult {
const buttons: TemplateResult[] = [];
const patterns: (Pattern | null)[] = [
@@ -74,6 +84,12 @@ export class TerritoryPatternsModal extends BaseModal {
...Object.values(this.cosmetics?.patterns ?? {}),
];
for (const pattern of patterns) {
if (pattern === null && this.search) {
continue;
}
if (pattern !== null && !this.includedInSearch(pattern.name)) {
continue;
}
const colorPalettes = pattern
? [...(pattern.colorPalettes ?? []), null]
: [null];
@@ -135,6 +151,19 @@ export class TerritoryPatternsModal extends BaseModal {
ariaLabel: translateText("common.back"),
rightContent: html`<not-logged-in-warning></not-logged-in-warning>`,
})}
<div class="md:flex items-center gap-2 justify-center mt-4">
<input
class="h-12 w-full max-w-md border border-white/10 bg-black/60
rounded-xl shadow-inner text-xl text-center focus:outline-none
focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500 text-white placeholder-white/30 transition-all"
type="text"
placeholder=${translateText("territory_patterns.search")}
.value=${this.search}
@change=${this.handleSearch}
@keyup=${this.handleSearch}
/>
</div>
</div>
<div class="flex justify-center py-3 shrink-0">
<button
@@ -176,6 +205,10 @@ export class TerritoryPatternsModal extends BaseModal {
await this.refresh();
}
protected onClose(): void {
this.search = "";
}
private selectPattern(pattern: PlayerPattern | null) {
this.selectedColor = null;
this.userSettings.setSelectedColor(undefined);