mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 15:30:43 +00:00
bd3db55a22
If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #2822 ## Description: Adds an attack ratio keybind increment setting with a new dropdown UI, wires keybinds to use the configured step, updates the attack ratio adjustment logic, and makes the select reflect stored settings. <img width="806" height="165" alt="スクリーンショット 2026-01-12 9 11 12" src="https://github.com/user-attachments/assets/c6eaa96d-e147-4927-b3ed-964e832ecc36" /> ## 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: aotumuri --------- Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Co-authored-by: iamlewis <lewismmmm@gmail.com>
91 lines
2.8 KiB
TypeScript
91 lines
2.8 KiB
TypeScript
import { LitElement, html } from "lit";
|
|
import { customElement, property } from "lit/decorators.js";
|
|
|
|
type SelectOption = {
|
|
value: number | string;
|
|
label: string;
|
|
};
|
|
|
|
@customElement("setting-select")
|
|
export class SettingSelect extends LitElement {
|
|
@property() label = "Setting";
|
|
@property() description = "";
|
|
@property({ type: Array }) options: SelectOption[] = [];
|
|
@property({ type: String }) value = "";
|
|
|
|
createRenderRoot() {
|
|
return this;
|
|
}
|
|
|
|
private handleChange(e: Event) {
|
|
const input = e.target as HTMLSelectElement;
|
|
const selected = this.options.find(
|
|
(option) => String(option.value) === input.value,
|
|
);
|
|
const selectedValue = selected?.value ?? input.value;
|
|
this.value = String(selectedValue);
|
|
|
|
this.dispatchEvent(
|
|
new CustomEvent("change", {
|
|
detail: { value: selectedValue },
|
|
bubbles: true,
|
|
composed: true,
|
|
}),
|
|
);
|
|
}
|
|
|
|
render() {
|
|
return html`
|
|
<div
|
|
class="flex flex-row items-center justify-between w-full p-4 bg-white/5 border border-white/10 rounded-xl hover:bg-white/10 transition-all gap-4"
|
|
>
|
|
<div class="flex flex-col flex-1 min-w-0 mr-4">
|
|
<label
|
|
class="text-white font-bold text-base block mb-1"
|
|
for="setting-select-input"
|
|
>${this.label}</label
|
|
>
|
|
<div class="text-white/50 text-sm leading-snug">
|
|
${this.description}
|
|
</div>
|
|
</div>
|
|
<div class="relative shrink-0 w-[200px]">
|
|
<select
|
|
id="setting-select-input"
|
|
class="w-full appearance-none py-2 pl-3 pr-9 border border-white/20 rounded-lg bg-black/40 text-white font-mono text-sm focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all"
|
|
.value=${String(this.value)}
|
|
@change=${this.handleChange}
|
|
>
|
|
${this.options.map(
|
|
(option) =>
|
|
html`<option
|
|
value=${String(option.value)}
|
|
?selected=${String(option.value) === String(this.value)}
|
|
>
|
|
${option.label}
|
|
</option>`,
|
|
)}
|
|
</select>
|
|
<span
|
|
class="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-white/60"
|
|
aria-hidden="true"
|
|
>
|
|
<svg
|
|
class="h-4 w-4"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
aria-hidden="true"
|
|
>
|
|
<path
|
|
fill-rule="evenodd"
|
|
d="M5.23 7.21a.75.75 0 0 1 1.06.02L10 10.94l3.71-3.71a.75.75 0 1 1 1.06 1.06l-4.24 4.24a.75.75 0 0 1-1.06 0L5.21 8.29a.75.75 0 0 1 .02-1.08z"
|
|
clip-rule="evenodd"
|
|
/>
|
|
</svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|