# UI Built on top of [HyUI](https://github.com/Elliesaur/HyUI), a third-party library that wraps Hytale's native Custom UI API in an HTML-like markup (HYUIML). HyUI is bundled into the Staff jar via the shade plugin so you don't need it installed separately. ## Reading the source Each page lives in [src/main/java/net/kewwbec/staff/ui/](../src/main/java/net/kewwbec/staff/ui/). Pages don't extend the SDK's `InteractiveCustomUIPage` anymore - they're plain classes that build a `PageBuilder` and expose an `open(store)` method. Navigation between pages is `new OtherPage(...).open(store)`. ## Page flow ``` /staffui | v [StaffHubPage] | +-> Player Lookup -> [PlayerLookupPage] (text search, click result for detail) | v [PlayerDetailPage] | +-> Ban / TempBan / Mute / TempMute / Kick / Warn --> [PunishFormPage] +-> Unban / Unmute (applied inline, page re-opens) +-> History --> [HistoryPage] ``` Every non-hub page has a Back button. ESC always closes (lifetime is `CanDismiss`). ## Page reference | Page | Purpose | |---|---| | [StaffHubPage](../src/main/java/net/kewwbec/staff/ui/StaffHubPage.java) | Top-level menu. Currently just routes to Player Lookup; add buttons here for new sections. | | [PlayerLookupPage](../src/main/java/net/kewwbec/staff/ui/PlayerLookupPage.java) | Text input + Search button. Online players are listed first; if you type a name not online, the players_seen table is consulted. Click a result to open detail. | | [PlayerDetailPage](../src/main/java/net/kewwbec/staff/ui/PlayerDetailPage.java) | Player info + active ban/mute lines + action buttons. Unban / Unmute fire immediately (no form); the page reopens with refreshed data. | | [PunishFormPage](../src/main/java/net/kewwbec/staff/ui/PunishFormPage.java) | Reason field, plus duration field for timed types. Validation errors re-open the same page with the entered values and a red error line. | | [HistoryPage](../src/main/java/net/kewwbec/staff/ui/HistoryPage.java) | Last 50 entries for the target. Read-only. | ## HyUI patterns we use All pages follow the same skeleton: ```java public final class SomePage { private final PlayerRef playerRef; private final StaffUIContext sCtx; private final PageBuilder page; public SomePage(PlayerRef playerRef, StaffUIContext sCtx, ...args) { this.playerRef = playerRef; this.sCtx = sCtx; // Build the HYUIML based on constructor state String html = """
"""; this.page = PageBuilder.pageForPlayer(playerRef) .withLifetime(CustomPageLifetime.CanDismiss) .fromHtml(html); // Wire listeners by element id page.addEventListener("someBtn", CustomUIEventBindingType.Activating, (ignored, pCtx) -> { // pCtx.getValue("inputId", String.class).orElse("") to read input values // Navigate by opening a new page instance }); } public void open(Store