Familiar web shapes, rebuilt around what a game needs from them.
GoRewardCalendar — daily attendance
A date picker is almost never useful in a game. A calendar shape is — for attendance rewards, where what matters is which day you are on, not which date it is.
var attendance := GoRewardCalendar.make(days, claimed_until)
attendance.claimed.connect(func(day: int) -> void: server.claim_day(day))
Only today's cell can be pressed — a button that does nothing when pressed reads as broken. Claimed, today and future differ by three things at once: a tick glyph, an accent border and dimming.
GoRadar and GoDonut — stats at a glance
var stats := GoRadar.make({"STR": 0.85, "AGI": 0.5, "INT": 0.3, "VIT": 0.7, "LUK": 0.45})
stats.set_compare(with_new_sword) # a dashed overlay
var share := GoDonut.make([{"label": "Physical", "value": 620}, {"label": "Magic", "value": 340}])
card.add_child(share.legend())
Radar values are 0–1 because what counts as full is a game decision — raw 120 STR beside 45 INT would draw a lie. Donut values are raw and it divides for you; past five slices it collapses the rest, since a sixth slice is a thread nobody can read. The comparison line is dashed, not just another colour, and the legend prints the percentage in words.
GoCarousel — banners and character select
banners.set_pages([promo, event, pack])
banners.autoplay_seconds = 5.0 # off by default
It does not advance on its own unless you ask, and five seconds is the floor: a banner that changes
every three takes the text away before it is read. Touching it resets the timer, and with
reduce_motion on it never advances by itself. The dots are pressable at the touch minimum
even though the drawn dot is small.
GoKbd — key hints that do not lie
hint.add_child(GoKbd.for_action(&"interact")) # reads the real binding
A hard-coded "Press F" keeps saying F after the player rebinds — the most common lie in a PC UI.
for_action() reads InputMap; if the action is bound to a pad instead, it returns
empty and the widget hides, because "None" would be its own lie. On Android and iOS it hides itself.