Skip to content

20.13.0: UI update (checkbox, slider, skins, layout, scrolling, shadows, bounce, keyboard/gamepad focus); gamepad plugin hover fix - #1808

Merged
obiot merged 16 commits into
masterfrom
claude/modest-johnson-ao5snz
Oct 31, 2026
Merged

obiot merged 16 commits into
masterfrom
claude/modest-johnson-ao5snz

Conversation

@obiot

@obiot obiot commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Description

  1. 20.13.0: bump the version. melonjs and .claude-plugin/plugin.json go from 20.12.0 to 20.13.0, together, as scripts/release.ts requires.
  2. UI widgets (UI: standardize the UI example's button, checkbox and panel into engine widgets, and add a slider #1722). The UI example's hand-made button, checkbox and panel become engine widgets, plus a slider.
  3. Review passes (bugs) and an API consistency pass against the existing UI widgets (UIBaseElement, UITextButton, UIPanel, ProgressBar), so one style object fits every widget.
  4. Drop shadows on UIPanel and ProgressBar.
  5. A bounce on every UIBaseElement: hoverScale and pressScale.
  6. Keyboard and gamepad focus, on the widgets themselves: focus().
  7. Gamepad plugin (Gamepad plugin: a touch on the controls still reaches the game as a hover (pointerover / pointerenter) #1805): a touch on the controls no longer reaches the game as a hover.

New widgets

  • UICheckbox: a box with its label (label, or labelOn / labelOff, both settable later). Clicking the label toggles it too.
    • Drawn: boxSize, boxColor, boxHoverColor, checkColor, borderColor, borderWidth, radius.
    • Skinned: skin: { atlas, on, off, hoverOn?, hoverOff?, disabledOn?, disabledOff? }.
    • checked and toggle() from code never call onChange(checked, checkbox); only the user does.
    • With a group, it is a radio button: one checked, drawn round. UICheckbox.checkedIn(group) returns the checked one, and changing group moves it at once.
  • UISlider:
    • min, max, step (all settable; they re-clamp silently), value, ratio, horizontal or vertical.
    • Drag the thumb (it keeps following off the track), click the track to jump, use the wheel, or the arrows with the focus.
    • onChange(value, slider) while it moves and onChangeEnd once on release. Neither fires from code.
    • Caption and value text with valueFormat(value, ratio).
    • Drawn (trackColor, fillColor, thumbColor, thumbHoverColor, thumbBorderColor, thumbBorderWidth), or skinned ({ atlas, track, fill?, thumb, thumbHover? }).

Keyboard and gamepad focus

For a game played without a mouse or a touch screen. There is no focus manager to set up: a widget takes the focus with focus().

  • From then on, the arrows or the D-pad move the focus to the nearest focusable widget that way, edge to edge.
  • Enter, Space or A press the focused widget as a click does. Left and right step a slider.
  • A ring (UIBaseElement.focusRingColor) shows the focus while the keyboard or a pad is used, and hides when the mouse moves. A focused widget in a scrolling panel scrolls into view.
  • Until a widget has the focus, nothing listens and the keys and the pad are the game's. blur(), or the focused widget leaving the scene, gives them back. The pad is read directly, real or virtual, so the game's pad bindings stay as they are.
  • On UIBaseElement: focus(), blur(), focused, focusable (on for buttons, checkboxes and sliders), onNavigate, and the static focusOwner.
  • Enter goes to the focused button: another button bound to Enter through bindKey waits while the ring shows elsewhere.

Changes to existing widgets

  • UITextButton:
    • an onClick setting (onClickCallback), called on a completed click: pointer, bindKey or focus accept; never a press dragged off, cancelled or turned into a scroll.
    • skin: { atlas, normal, pressed?, hover?, disabled? } as nine-slices, with pressed art drawn lowered.
    • pressedColor: left undefined, it follows hoverOnColor, so existing buttons look the same.
    • The names the other widgets use: width / height for its size, fontSize (pixels, also with a bitmap font), labelFillStyle, borderColor. The old borderWidth / borderHeight / size / fillStyle / borderStrokeColor still work.
    • Colours take any Paint. resize(). Settings are no longer written back, so one object can make several buttons.
    • A bitmap font is used as before (by name, fontData, or an image); any other font is drawn as a CSS font, where the button used to throw.
    • label is the text. bitmapText is deprecated but keeps its BitmapText type, so existing TypeScript code compiles.
  • UIPanel:
    • nine-slice skin, title (titleFont, titleFontSize, titleFillStyle), draggable (moved by its title or frame, never through a widget on it; comes to the front);
    • layout: column, row or grid, with padding, gap, align and autoSize. "stretch" only resizes buttons and panels.
    • scroll: cropped content, wheel, drag with momentum, scrollbar, scrollTo, scrollToChild(child, margin?), scrollX / scrollY, maxScrollX / maxScrollY, onScroll.
    • A drag starting on a button scrolls and cancels the press. A slider, or anything with keepsDrag, keeps its drags. A scrolling panel inside another scrolls alone.
  • Drop shadows, UIPanel and ProgressBar:
    • shadowColor (its alpha sets the darkness), shadowOffsetX, shadowOffsetY, shadowBlur.
    • The soft edge is stacked translucent rounded rectangles, the same on Canvas, WebGL and WebGPU.
    • It follows radius and goes under a skin. It is drawn outside the bounds, so it never takes the pointer.
  • UIBaseElement:
    • enabled (shared by every UI element), cancelPress() / onCancel(), keepsDrag.
    • hoverScale / pressScale, also a setting on every widget: an eased bounce under the pointer or the focus and while held, scaling the drawing only, not the hit area or the layout.
    • The focus methods above.
    • A draggable element tapped with no hover first (touch) no longer throws, and drags by touch. In the world it no longer jumps by the camera position.
  • ProgressBar: onChange also gets the bar.
  • Input:
    • A child cropped by a container with clipping, or scrolled out of a panel, no longer receives pointer events where it is not drawn (Container#clipContains).
    • Drags end on their own pointer's release only, in the event family the engine listens to.
    • A virtual gamepad in the same slot as a real pad is no longer hidden by it when the UI reads the pads.
  • Exported: UINavAction, UIJuiceSettings, UISkin, UILabel, Paint, and every widget's settings and skin types, all under @category UI.

Known limitation, documented in the skill: on WebGL, a scrolling panel inside another clipping container is cropped to its own area only.

Gamepad plugin (#1805)

A touch fires pointerover and pointerenter before its pointerdown, and pointerout and pointerleave after its pointerup. The plugin only kept down, move, up and cancel from the engine, so the widget under a button got onOver as it was pressed: the Alex 4 menu arrow jumped to the line under B.

The plugin now also captures the four hover events and stops them for a touch that lands on, or lifted from, a control. A mouse hovering over the controls is left alone. Changelog entry under [1.0.2] - unreleased; the package version is unchanged until it is released.

Example, docs

  • The UI example uses all of these:
    • a skinned options panel laid out as a column: music and sound FX checkboxes, volume sliders wired to audio, Accept / Cancel (Cancel restores from code, showing that onChange does not fire), and Video Options;
    • the progress bars;
    • a level list at the top right showing 16 of 30 levels and scrolling the rest, with the last six locked;
    • soft drop shadows, a bounce on the buttons and checkboxes, and keyboard / gamepad play starting on the first checkbox, with a hint line for the controls.
  • One shared { font, fontSize, labelFillStyle } style object goes to buttons, checkboxes and sliders alike.
  • melonjs-ui-and-text skill: sections per widget, panel art, shadows, layout and scrolling, the bounce, focus(), plus a symptom table.
  • Changelog under 20.13.0: Added, Changed, Deprecated, Fixed.

How it was checked

  • tests/ui-widgets.spec.js (120 tests): driven by real pointer, wheel, mouse, touch and keyboard events, and a virtual gamepad. It covers:
    • every widget's behaviour, drawn and skinned, horizontal and vertical;
    • layout and scrolling, including sideways and line-mode wheels, wheel pass-through at a panel's end, fling limits, grid stretch, row autoSize and clearChildren;
    • each review finding;
    • the API changes, with the real button instead of stub subclasses;
    • drop shadows, also under a faded parent, and scrollbar geometry;
    • the bounce, including its easing and that it doesn't change the hit area;
    • focus: nothing without focus(), arrows, accept on a button and a checkbox, slider steps, disabled and hidden widgets skipped, stuck presses called off, bindKey yielding, the ring drawn only while it shows, scroll into view, a gamepad's D-pad and A (and one already held), blur(), and the keys given back when the focused widget leaves;
    • clipping through a real container;
    • a draw pass of all four widgets on Canvas and WebGL.
  • A review of the tests for gaps found three bugs, now fixed, each with a test checked to fail without the fix:
    • a slider's default value text kept the old decimals after step changed;
    • Enter on a focused button the pointer already held clicked it on release;
    • a virtual gamepad sharing a slot with a real pad was not read.
  • UI, pointer, progress bar, container, draggable, gamepad, keyboard and input suites: 576 tests pass. Changed tests:
    • a button with no bitmap font no longer throws;
    • ProgressBar's onChange gets a third argument.
  • Gamepad plugin: 46 tests pass, including a new one for Gamepad plugin: a touch on the controls still reaches the game as a hover (pointerover / pointerenter) #1805, checked to fail without the fix.
  • tsc, eslint, biome and the build, including the declaration check, pass.
  • The example was driven in headless Chromium with mouse, touch and keyboard, and the published demo was run under a strict content security policy.

Type of change

  • Bug fix
  • New feature
  • Documentation update
  • Performance improvement
  • Refactoring (no functional changes)

Checklist

  • I have read the Contributing Guide
  • My code follows the existing code style (pnpm lint passes)
  • I have tested my changes locally: the UI, pointer, input, gamepad and container suites; CI runs the whole suite
  • I have added tests that cover my changes (if applicable)
  • The build succeeds (pnpm build)

Related issues

Closes #1722
Closes #1805

🤖 Generated with Claude Code

https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 03:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

- UICheckbox: a checkbox with its label, drawn or skinned, a radio button
  with a `group`; `onChange` only on user input
- UISlider: horizontal or vertical, drag, track click, wheel, step, caption
  and value text, drawn or skinned; `onChange` and `onChangeEnd`
- UITextButton: `onClick` setting on a completed click, atlas `skin` with
  lowered pressed art, `enabled`, `pressedColor`, CSS fonts
- UIPanel: nine-slice `skin`, `title`, `draggable`, `layout`
  (column/row/grid, padding, gap, align, autoSize) and `scroll` (wheel,
  drag with momentum, scrollbar, scrollTo/scrollToChild)
- UIBaseElement: cancelPress/onCancel, so a drag on a button in a
  scrolling panel scrolls instead of clicking
- Input: children cropped by a clipping container, or scrolled out of a
  panel, no longer get pointer events there
- The UI example uses the widgets, with volume sliders wired to audio and
  a scrolling level list; skill sections and changelog entries

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 03:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@obiot obiot changed the title 20.13.0: bump the version 20.13.0: version bump; UI checkbox, slider, skinned button, panel layout and scrolling Oct 31, 2026
- UIBaseElement: a draggable element pressed with no hover first, as a
  touch tap is, no longer throws, and drags by touch
- UIPanel: a draggable panel is moved by its title or frame, not through
  a widget on it, so dragging it by a button no longer clicks the button
- UIPanel: no fling while the pointer is still down; autoSize counts the
  title and frame from a zero height; a scrolling panel inside another
  scrolls alone; emptying or destroying a panel does not lay it out per
  child or call onScroll
- UISlider: the wheel to the right raises it; a drag also ends on a
  mouse or touch release, or a release over the slider
- UICheckbox: as wide as its longer label, whichever it is
- UITextButton: a font given as fontData, an image, or with only its
  image loaded is a bitmap font as before; pressedColor defaults to
  hoverOnColor; bitmapText can be assigned
- 10 regression tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 03:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

API, from a consistency review against the existing UI widgets:
- UITextButton: width/height, fontSize (pixels, bitmap fonts too),
  labelFillStyle and borderColor, the names the other widgets use; the old
  names still work. Settings are no longer written back. Colours take any
  Paint. pressedColor left undefined follows hoverOnColor. onClickCallback
  (was clickCallback). bitmapText keeps its BitmapText type, deprecated
- UICheckbox: boxSize, boxHoverColor; labelOn/labelOff settable and
  refitting; group changes apply at once; skin hoverOn/hoverOff and
  disabledOn/disabledOff
- UISlider: valueFormat(value, ratio) (was format), ratio, settable
  min/max/step, thumbHoverColor, thumbBorderColor, thumbBorderWidth
- UIBaseElement: enabled shared by every UI element; keepsDrag public
- ProgressBar: onChange also gets the bar
- Paint exported; @category UI on the UI settings types

Fixes:
- align "stretch" only resizes buttons and panels, not a BitmapText
  (whose resize is a scale) or a checkbox or slider
- a drag ends only on its own pointer's release, in the event family the
  engine listens to, not on another finger or button
- a non-blocking scrolling panel inside another scrolls alone
- a draggable panel is not moved through a widget at any depth, and the
  check no longer mixes coordinate spaces in the world
- a draggable element in the world no longer jumps by the camera position
- a stale scroll press is dropped; skin insets of 0 match the art
- slider steps in exponent notation, and a range that is not a whole
  number of steps, snap correctly

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

shadowColor, shadowOffsetX, shadowOffsetY and shadowBlur. The soft edge is
a few stacked translucent rounded rectangles, so it looks the same on
Canvas, WebGL and WebGPU; it follows the corner radius, goes under a skin
too, and is drawn outside the bounds so it never takes the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 05:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

…game (#1805)

A touch fires pointerover and pointerenter before its pointerdown, and
pointerout and pointerleave after its pointerup. The plugin only kept the
down, move, up and cancel from the engine, so the widget under a button
got onOver as the button was pressed (the Alex 4 menu arrow jumped to the
line under B). The plugin now also captures the four hover events and
stops them for a touch that lands on, or lifted from, a control. A mouse
hovering over the controls is left alone, as its moves are.

Fixes #1805

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@obiot obiot changed the title 20.13.0: version bump; UI checkbox, slider, skinned button, panel layout and scrolling 20.13.0: version bump; UI checkbox, slider, skinned button, panel layout, scrolling and shadows; gamepad plugin hover fix Oct 31, 2026
UIFocus (off until UIFocus.enable()): one widget has the focus; the arrows,
the D-pad or the left stick move it to the nearest widget that way, edge to
edge; Enter, Space or A press it as a click does; left/right step a slider;
Escape or B cancel. The pad is read directly (input.readGamepads, real or
virtual), so the game's pad bindings are untouched. The ring shows after
keyboard or pad input and hides when the mouse moves; the first key after
the mouse only shows it. A UIPanel with trapFocus keeps the focus in and
restores it after, with onBack on cancel. Focused widgets in a scrolling
panel scroll into view, with room for the ring. Any UIBaseElement can take
part: focusable, focusNeighbors, onNavigate, onFocus/onBlur,
focusPress/focusRelease. Buttons, checkboxes and sliders do.

hoverScale and pressScale on UIBaseElement, and as settings on every
widget: an eased bounce applied to the drawing only, so hit areas and
layouts stay put.

The UI example turns on both, with a hint line for the controls. Skill
sections and changelog entries; 13 new tests (87 in ui-widgets).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@obiot obiot changed the title 20.13.0: version bump; UI checkbox, slider, skinned button, panel layout, scrolling and shadows; gamepad plugin hover fix 20.13.0: complete UI update (checkbox, slider, skins, layout, scrolling, shadows, bounce, keyboard/gamepad focus); gamepad plugin hover fix Oct 31, 2026
Arrows or the D-pad move to the nearest widget, Enter, Space or A press
it, sliders step, a ring shows the focus, and a focused widget in a
scrolling panel scrolls into view. Removed: trapFocus/onBack, cancel,
focusNeighbors, onFocus/onBlur, hover moving the focus, the first-key
rule, the stick with repeat, configurable keys and ring sizes. Most games
use the mouse or touch; this covers a menu driven by keys or a pad.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

- a press held by Enter or A is called off when the focus moves, the
  widget is removed or navigation is disabled, instead of staying down
- a focused widget only bounces while the focus ring shows
- the bounce eases over about 0.2 s; it snapped in a frame
- Enter goes to the focused button: another bound to Enter waits while the
  ring shows elsewhere
- a pad's A held as navigation is enabled is not a press
- a widget made focusable after it was added takes part
- navigation skips widgets inside a hidden or transparent container
- an arrow from a focused widget disabled since moves on from where it is
- docs: the bounce is on UIBaseElement; Enter and bindKey; accept calls
  onClick() with no event

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

UIFocus is gone. A widget takes the keyboard and gamepad focus with
focus(); from then on the arrows or the D-pad move it, Enter, Space or A
press it, sliders step. Nothing listens until a widget has the focus, and
the listeners go when none does (blur(), or the focused widget leaving the
scene), so the keys and the pad are the game's until then. On
UIBaseElement: focus(), blur(), focused, focusable, onNavigate, the static
focusOwner and focusRingColor. The example focuses its first widget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 06:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@obiot obiot changed the title 20.13.0: complete UI update (checkbox, slider, skins, layout, scrolling, shadows, bounce, keyboard/gamepad focus); gamepad plugin hover fix 20.13.0: UI update (checkbox, slider, skins, layout, scrolling, shadows, bounce, keyboard/gamepad focus); gamepad plugin hover fix Oct 31, 2026
Three bugs the new tests caught:
- a slider's default value text kept the old decimals after `step` changed
- Enter on a focused button the pointer already held clicked it on release
- a virtual gamepad sharing a slot with a real one was not read

The stub-subclass tests now use the real button. New tests cover the
shadow under a faded parent, scrollbar geometry, vertical and skinned
sliders, cancelled and two-finger drags, skin regions and bitmap font
sizes, radio drawing and groups, sideways and line-mode wheel scrolling,
wheel pass-through at the end of a panel, fling limits, grid stretch,
row autoSize, clearChildren, the focus ring, and focus teardown. The
clipping test now clips through a real container.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JnzwA4xBNBw7cEZzG1bUru
Copilot AI balanced review requested due to automatic review settings October 31, 2026 07:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@obiot
obiot merged commit 62a12b7 into master Oct 31, 2026
6 checks passed
@obiot
obiot deleted the claude/modest-johnson-ao5snz branch October 31, 2026 07:18
@obiot obiot mentioned this pull request Oct 31, 2026
5 of 10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants