+
Drag a widget’s label to move it. Hidden and inactive widgets appear as placeholders. Use the list to show them again.
+
UI templates · 6 slots
+ {(["mobile", "pc"] as const).map((device) => )}
+ {ui.preferences.slots[tab].map((template, index) => )}
+
+
+
+
+
+
+ {tab !== ui.device && Load and save {tab === "pc" ? "PC" : "Mobile"} layouts on that device type. You can rename or export either set here.}
+
+
+
+
+
+ {
+ const chosen = event.target.files?.[0]; event.target.value = ""; if (!chosen) return;
+ if (chosen.size > 256_000) { setMessage("UI files must be smaller than 256 KB."); return; }
+ void chosen.text().then((text) => setPendingImport(importUiPreferences(text))).catch((error: Error) => setMessage(error.message));
+ }} />
+
+ {transferText !== null &&
+
+ Copy this text to transfer your UI, or paste an exported configuration to import it.
+
+
+
}
+ {pendingImport && Replace all six slots and both saved layouts with this file?
}
+ {session?.accessToken ? "Templates save to your account and upload with cloud saves. Sign in on another device to load them." : "Offline profile: saved on this device. Use export/import to transfer your UI."}
+
+
Elements · move / hide
+ {(Object.entries(HUD_ELEMENTS) as [HudElementId, string][]).filter(([id]) => !id.startsWith("bar-") || ui.device === "pc").map(([id, label]) =>
+
+
+
)}
+
+
+ {ui.device === "pc" &&
PC action bars
+
+ {draft.wowBars && <>
+
+ {draft.bars.slice(0, draft.barCount).map((bar, index) => Bar {index + 1}
+
+
+
)}
+
+ {ui.mode === "bindings" ? "Click a bar button, then press a key or modifier + key. Backspace/Delete clears it; Escape cancels selection. Bound keys take priority over game shortcuts." : "Click a bar button to assign an ability."}
+ {selected && Bar {selected.bar + 1} · Button {selected.slot + 1}{ui.mode === "bindings" ? " · Press a key…" : ""}
+
+
+
{abilities.filter((ability) => !ability.passive && ability.name.toLowerCase().includes(search.toLowerCase())).map((ability) => )}
+
}
+ >}
+ }
+
{message}
+ {session?.accessToken &&
{cloudSave.message}{cloudSave.state === "error" && }
}
+
}
+