Extend keybinds with navigation#67
Extend keybinds with navigation#67MartinBozhilov-coh wants to merge 2 commits intonavigation-componentfrom
Conversation
| '0': Icon.gamepad.ps5.cross, | ||
| '1': Icon.gamepad.ps5.circle, | ||
| '2': <Icon.gamepad.ps5.square style={{width: '5vmax', height: '5vmax'}} />, | ||
| '3': <img src={customGlyphIcon} />, |
There was a problem hiding this comment.
Add comments with // to showcase the different ways to use the Icon
There was a problem hiding this comment.
Pull request overview
This pull request extends the Keybinds component with gamepad support and integrates it with the Navigation component system. The changes enable developers to bind gamepad buttons in addition to keyboard/mouse inputs, with proper visual glyph representation.
Changes:
- Added gamepad mode support to Keybinds/Keybind components with configurable glyph overrides
- Implemented pauseInput/resumeInput methods in Navigation for global action input control
- Updated import paths for interaction-manager types to use a unified entry point
- Added comprehensive tests and documentation for gamepad functionality
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/src/components/Keybinds/KeybindsTest.tsx | Added test scenarios for gamepad mode with Navigation integration and custom glyph overrides |
| tests/specs/keybinds.spec.js | Added test suite for gamepad mode including glyph rendering, rebinding, and action pause behavior |
| tests/shared/keybinds/keybinds-selectors.json | Added selector for action test element |
| tests/shared/keybinds/glyph-mappings.json | New file with gamepad button mappings for test data |
| src/components/Utility/Navigation/types.ts | Consolidated imports from interaction-manager into single entry point |
| src/components/Utility/Navigation/areaMethods/useAreaMethods.ts | Updated import path for KeyName type |
| src/components/Utility/Navigation/areaMethods/areaMethods.types.ts | Updated import path for KeyName type |
| src/components/Utility/Navigation/actionMethods/useActionMethods.ts | Implemented pauseInput/resumeInput methods with snapshot logic for paused action states |
| src/components/Utility/Navigation/actionMethods/actionMethods.types.ts | Added JSDoc documentation for pauseInput/resumeInput methods |
| src/components/Media/Icon/Icon.tsx | Added optional chaining for props.class to prevent potential undefined errors |
| src/components/Basic/Keybinds/util/glyphs.ts | New file defining default gamepad button-to-glyph mappings using Xbox layout |
| src/components/Basic/Keybinds/Keybinds.tsx | Added gamepad mode support, button input sanitization, and glyph override functionality |
| src/components/Basic/Keybinds/Keybinds.module.scss | Extended hover styles to include focus state for keyboard/gamepad navigation |
| src/components/Basic/Keybinds/Keybind.tsx | Implemented gamepad listening logic with button polling and axis detection |
| package.json | Updated coherent-gameface-interaction-manager from 2.6.0 to 2.8.0 |
| docs/src/content/docs/components/Utility/Navigation.mdx | Documented new pauseInput/resumeInput API methods |
| docs/src/content/docs/components/Basic/keybinds.mdx | Added comprehensive gamepad support documentation with usage examples |
| docs/src/content/docs/changelog/index.mdx | Added changelog entry for Keybind navigation actions and gamepad guide |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| See the [Glyphs object](#glyphs-object) table for the full list of supported gamepad button codes and axis aliases. | ||
|
|
||
| For easier readibility, you can use the same button codes and axis aliases used by the [Interaction Manager Gamepad Class](https://frontend-tools.coherent-labs.com/interaction-manager/features/gamepad/#options). | ||
| The will resolve to the correct button indices internally. |
There was a problem hiding this comment.
Grammar error: "The will resolve" should be "They will resolve" or "These will resolve".
| The will resolve to the correct button indices internally. | |
| These will resolve to the correct button indices internally. |
| - <Badge text="New" variant="tip" size="small" /> [GridTile](/components/layout/grid-tile) - Provide [a guide](/components/layout/grid-tile/#making-grid-tiles-navigable) on how to initialize grid tiles as navigable elements within a [Navigation](/components/utility/Navigation/) area. | ||
|
|
||
| ## 1.2.0 :badge[Latest]{variant="note"} | ||
| - <Badge text="New" variant="tip" size="small" /> [Keybinds](/components/basic/keybinds) - Provide [an extend overview](/components/basic/keybinds#gamepad-support) on gamepad support. |
There was a problem hiding this comment.
Grammar error: "an extend overview" should be "an extended overview".
| - <Badge text="New" variant="tip" size="small" /> [Keybinds](/components/basic/keybinds) - Provide [an extend overview](/components/basic/keybinds#gamepad-support) on gamepad support. | |
| - <Badge text="New" variant="tip" size="small" /> [Keybinds](/components/basic/keybinds) - Provide [an extended overview](/components/basic/keybinds#gamepad-support) on gamepad support. |
| @@ -0,0 +1,54 @@ | |||
| import { Icon } from "@components/Media/Icon/Icon"; | |||
| import { GamepadMappings } from "coherent-gameface-interaction-manager"; | |||
There was a problem hiding this comment.
Unused import: GamepadMappings is imported but never used in this file.
| import { GamepadMappings } from "coherent-gameface-interaction-manager"; |
| const registeredCallbacks: Record<string, () => void> = {}; | ||
|
|
||
| const stopAllListeners = () => { | ||
| clearInterval(pollInterval); |
There was a problem hiding this comment.
Variable used before declaration: The pollInterval variable is referenced in stopAllListeners() on line 74 before it's declared on line 117. This will cause a ReferenceError at runtime when stopAllListeners() is called. The variable should be declared at the function scope level before being used.
| clearInterval(pollInterval); |
| while the axes are identified by custom aliases (e.g., `left.joystick.up`, `right.joystick.left`, etc.). | ||
| See the [Glyphs object](#glyphs-object) table for the full list of supported gamepad button codes and axis aliases. | ||
|
|
||
| For easier readibility, you can use the same button codes and axis aliases used by the [Interaction Manager Gamepad Class](https://frontend-tools.coherent-labs.com/interaction-manager/features/gamepad/#options). |
There was a problem hiding this comment.
Typo: "readibility" should be "readability".
| For easier readibility, you can use the same button codes and axis aliases used by the [Interaction Manager Gamepad Class](https://frontend-tools.coherent-labs.com/interaction-manager/features/gamepad/#options). | |
| For easier readability, you can use the same button codes and axis aliases used by the [Interaction Manager Gamepad Class](https://frontend-tools.coherent-labs.com/interaction-manager/features/gamepad/#options). |
| { label: "Change placeholder text", action: () => { setPlaceholder(selectors["placeholder-text"]) } }, | ||
| { label: "Change styles", action: () => { setTest('blue') } }, | ||
| { label: "Reset defaults - alternate", action: () => { keybindsRefWithDefault.reset() } }, | ||
| { label: "Focus keybind nav area", action: () => { nav.focusFirst('keybinds') } }, |
There was a problem hiding this comment.
The base expression of this property access is always undefined.
|
|
||
| props.componentClasses = style.keybind; | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs } = useBaseComponent(props); | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs, navigationActions } = useBaseComponent(props); |
There was a problem hiding this comment.
Unused variable forwardEvents.
|
|
||
| props.componentClasses = style.keybind; | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs } = useBaseComponent(props); | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs, navigationActions } = useBaseComponent(props); |
There was a problem hiding this comment.
Unused variable forwardAttrs.
| const { className, inlineStyles, forwardEvents, forwardAttrs, navigationActions } = useBaseComponent(props); | |
| const { className, inlineStyles, navigationActions } = useBaseComponent(props); |
|
|
||
| props.componentClasses = style.keybind; | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs } = useBaseComponent(props); | ||
| const { className, inlineStyles, forwardEvents, forwardAttrs, navigationActions } = useBaseComponent(props); |
There was a problem hiding this comment.
Unused variable navigationActions.
| const { className, inlineStyles, forwardEvents, forwardAttrs, navigationActions } = useBaseComponent(props); | |
| const { className, inlineStyles, forwardEvents, forwardAttrs } = useBaseComponent(props); |
| if (0 <= num && num <= 16) return String(input); | ||
| else { | ||
| console.warn(`${input} is not a valid gamepad button. Please ensure the number is between 0 and 16`); | ||
| return null |
There was a problem hiding this comment.
Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
| return null | |
| return null; |
No description provided.