Skip to content

fix: make pixelhub fully responsive and touch-playable on phones#15

Merged
mateuseap merged 1 commit into
mainfrom
fix/mobile-responsiveness
Jul 26, 2026
Merged

fix: make pixelhub fully responsive and touch-playable on phones#15
mateuseap merged 1 commit into
mainfrom
fix/mobile-responsiveness

Conversation

@mateuseap

Copy link
Copy Markdown
Owner

The chat panel used a fixed 320px width inside a flex row, so on a 375-414px phone viewport it consumed nearly the entire screen and left the game canvas as a ~55px sliver. On top of that, WorldScene.readInput only ever read keyboard keys, so there was no way to move the avatar on a touchscreen at all. This fixes both, verified with headless Chrome touch emulation at 375x667, 414x896, and 812x375 (landscape).

Changes made

  • Chat panel becomes an off-canvas drawer below 700px width (or short landscape heights), toggled by a floating button (#chat-toggle) and closed via a tap on the backdrop, so the game canvas gets the full screen on phones instead of losing most of its width to a fixed sidebar.
  • Added an on-screen virtual joystick (client/src/ui/touchControls.ts), shown only on coarse-pointer (touch) devices via matchMedia('(pointer: coarse)'), that produces the same MovementInput shape the keyboard does. WorldScene.readInput now merges keyboard and touch sources, so nothing changes for desktop/keyboard play.
  • Bumped mobile tap targets (join button/input, chat send, voice toggle) to 44px and the chat input font-size to 16px to stop iOS Safari from auto-zooming the page on focus.
  • Added viewport-fit=cover and safe-area-inset padding so the joystick and chat drawer stay clear of notches/home indicators.
  • Updated the join-screen hint (shows "Use the on-screen joystick to move" on touch devices instead of the WASD hint) and two docs (ADR-002, system-design.md) that described input as keyboard-only.
  • Added unit tests for the joystick (deadzone, axis thresholds, diagonal drags, multi-touch guard) and the new chat drawer toggle/backdrop behavior.

Test plan

  • pnpm typecheck passes across shared/server/client
  • pnpm test passes (78 client tests, including 8 new joystick tests and 3 new drawer tests)
  • pnpm -r build succeeds
  • Headless Chrome + CDP touch emulation at 375x667: game fills the viewport, joystick drag scrolls the world (confirmed via before/after screenshot diff), chat toggle opens the drawer, chat message sent via touch tap arrives in the log
  • Same touch flow re-verified at 414x896 and 812x375 (landscape)
  • Desktop (1440x900) keyboard (arrow keys) still moves the avatar; sidebar layout unchanged, no joystick shown

The chat panel used a fixed 320px width inside a flex row, so on a
375-414px phone viewport it consumed nearly the entire screen and left
the game canvas as a sliver. On top of that, WorldScene only ever read
keyboard input, so there was no way to move the avatar on a touchscreen
at all.

#### Changes made
- Chat panel becomes an off-canvas drawer below 700px width (or short
  landscape heights), toggled by a floating button and closed via a
  backdrop tap, so the game canvas gets the full screen on phones.
- Added an on-screen virtual joystick (client/src/ui/touchControls.ts),
  shown only on coarse-pointer (touch) devices, that feeds the same
  MovementInput the keyboard produces so WorldScene.readInput merges
  both sources.
- Bumped mobile tap targets and chat input font-size to 16px to stop
  iOS Safari from auto-zooming on focus, and added viewport-fit=cover
  plus safe-area-inset padding for notched phones.
- Updated the join-screen hint and two docs (ADR-002, system-design)
  that described input as keyboard-only.
@mateuseap mateuseap self-assigned this Jul 26, 2026
@mateuseap
mateuseap merged commit 5a6591b into main Jul 26, 2026
1 check passed
@mateuseap
mateuseap deleted the fix/mobile-responsiveness branch July 26, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant