Skip to content

Standardise ledger scrolling when using keyboard shortcuts#7283

Open
JSkinnerUK wants to merge 4 commits intoactualbudget:masterfrom
JSkinnerUK:ledger-scrolling
Open

Standardise ledger scrolling when using keyboard shortcuts#7283
JSkinnerUK wants to merge 4 commits intoactualbudget:masterfrom
JSkinnerUK:ledger-scrolling

Conversation

@JSkinnerUK
Copy link
Contributor

@JSkinnerUK JSkinnerUK commented Mar 25, 2026

Description

Depending on whether navigating with the arrow keys, or k/j, the scrolling would be inconsistent, due to the arrow keys interacting with the browsers scroll. e.preventDefault() was already used in the other navigation cases, and applying to all cases will give consistent behaviour.

Related issue(s)

Fixes #940

Testing

Recreating steps are in #940. I tested navigating with up and down arrows, k/j, enter and shift enter, and tab and shift tab.

Checklist

  • Release notes added (see link above)
  • No obvious regressions in affected areas
  • Self-review has been performed - I understand what each change in the code does and why it is needed

Bundle Stats

Bundle Files count Total bundle size % Changed
desktop-client 27 12.11 MB → 12.11 MB (+94 B) +0.00%
loot-core 1 4.83 MB 0%
api 4 4.06 MB 0%
cli 1 7.88 MB 0%
View detailed bundle stats

desktop-client

Total

Files count Total bundle size % Changed
27 12.11 MB → 12.11 MB (+94 B) +0.00%
Changeset
File Δ Size
src/components/table.tsx 📈 +94 B (+0.24%) 37.63 kB → 37.72 kB
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger

Asset File Size % Changed
static/js/useTransactionBatchActions.js 4.29 MB → 4.29 MB (+94 B) +0.00%

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
static/js/index.js 3.23 MB 0%
static/js/BackgroundImage.js 119.98 kB 0%
static/js/FormulaEditor.js 846.44 kB 0%
static/js/ReportRouter.js 1.02 MB 0%
static/js/TransactionList.js 81.29 kB 0%
static/js/ca.js 185.57 kB 0%
static/js/da.js 104.66 kB 0%
static/js/de.js 177.58 kB 0%
static/js/en-GB.js 7.16 kB 0%
static/js/en.js 170.76 kB 0%
static/js/es.js 184.81 kB 0%
static/js/fr.js 177.61 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.46 kB 0%
static/js/it.js 168.97 kB 0%
static/js/narrow.js 354.27 kB 0%
static/js/nb-NO.js 154.72 kB 0%
static/js/nl.js 111.58 kB 0%
static/js/pl.js 88.34 kB 0%
static/js/pt-BR.js 180.5 kB 0%
static/js/resize-observer.js 18.03 kB 0%
static/js/sv.js 80.58 kB 0%
static/js/th.js 179.94 kB 0%
static/js/theme.js 30.68 kB 0%
static/js/uk.js 213.14 kB 0%
static/js/wide.js 418 B 0%
static/js/workbox-window.prod.es5.js 7.28 kB 0%

loot-core

Total

Files count Total bundle size % Changed
1 4.83 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.Bq2rqD2u.js 4.83 MB 0%

api

Total

Files count Total bundle size % Changed
4 4.06 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
index.js 3.84 MB 0%
from-Bl-Hslp4.js 167.73 kB 0%
multipart-parser-BnDysoMr.js 8.1 kB 0%
src-iMkUmuwR.js 43.64 kB 0%

cli

Total

Files count Total bundle size % Changed
1 7.88 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
cli.js 7.88 MB 0%

@actual-github-bot actual-github-bot bot changed the title Standardise ledger scrolling when using keyboard shortcuts [WIP] Standardise ledger scrolling when using keyboard shortcuts Mar 25, 2026
@netlify
Copy link

netlify bot commented Mar 25, 2026

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit e291ad6
🔍 Latest deploy log https://app.netlify.com/projects/actualbudget/deploys/69c41d2e63d66b000807ee7d
😎 Deploy Preview https://deploy-preview-7283.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Contributor

👋 Hello contributor!

We would love to review your PR! Before we can do that, please make sure:

  • ✅ All CI checks pass
  • ✅ The PR is moved from draft to open (if applicable)
  • ✅ The "[WIP]" prefix is removed from the PR title
  • ✅ All CodeRabbit code review comments are resolved (if you disagree with anything - reply to the bot with your reasoning so we can read through it). The bot will eventually approve the PR.

We do this to reduce the TOIL the core contributor team has to go through for each PR and to allow for speedy reviews and merges.

For more information, please see our Contributing Guide.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

Updated the table navigator's keydown handler to call e.preventDefault() for ArrowUp/ArrowDown and j/k branches that invoke onMove('up'|'down') (still skipped for input elements). Enter/Tab handling and propagation gating remain unchanged.

Changes

Cohort / File(s) Summary
Table Navigation Standardization
packages/desktop-client/src/components/table.tsx
Added e.preventDefault() to the ArrowUp/ArrowDown and j/k branches that call `onMove('up'
Release Notes
upcoming-release-notes/7283.md
New bugfix release note added documenting standardized ledger scrolling when using keyboard shortcuts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 I pat the keys with nimble feet,
Up and down the rows now meet.
No more jumps, the ledger sails,
Steady hops and softer tails.
Cheers — a rabbit's tiny beat.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The code changes directly address the root cause of issue #940: applying e.preventDefault() to arrow key navigation branches so they no longer trigger browser scroll, making behavior consistent with j/k navigation.
Out of Scope Changes check ✅ Passed All changes are in scope: table.tsx modification fixes the keyboard navigation issue and the release notes file documents the fix, with no unrelated alterations.
Title check ✅ Passed The title directly matches the main change: applying preventDefault() to arrow key navigation to standardize scrolling behavior with k/j navigation, fixing the inconsistent ledger scrolling issue #940.
Description check ✅ Passed The PR description clearly explains the inconsistent scrolling issue, the rationale for applying e.preventDefault() consistently, and references the related issue #940.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/desktop-client/src/components/table.tsx (1)

1366-1398: ⚠️ Potential issue | 🟠 Major

Scope preventDefault() to handled navigation keys only.

At Line 1366, preventDefault() now runs for every key that reaches the table handler, which can suppress unrelated default keyboard behavior while focus is inside the table. This broadens behavior beyond the navigation fix.

Suggested patch
       onKeyDown: e => {
         userProps?.onKeyDown?.(e);
         if (e.isPropagationStopped()) {
           return;
         }

-        e.preventDefault();
+        const shouldPreventDefault =
+          e.key === 'ArrowUp' ||
+          e.key === 'ArrowDown' ||
+          e.key === 'k' ||
+          e.key === 'j' ||
+          e.key === 'Enter' ||
+          e.key === 'Tab';
+        if (shouldPreventDefault) {
+          e.preventDefault();
+        }

         switch (e.key) {
           case 'ArrowUp':
           case 'k':
             if (e.target.tagName !== 'INPUT') {
               onMove('up');
             }
             break;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/desktop-client/src/components/table.tsx` around lines 1366 - 1398,
The keydown handler currently calls e.preventDefault() unconditionally at the
top, which blocks all default behaviors; restrict preventDefault() to only the
navigation keys handled in the switch (the 'ArrowUp'/'k', 'ArrowDown'/'j',
'Enter', and 'Tab' cases). Move or add e.preventDefault() into each handled
branch (or just before calling onMove) so that only when you invoke
onMove('up'|'down'|'left'|'right') the default is prevented; leave other keys
untouched. Use the existing symbols (the keydown handler that references e.key
and onMove) to locate where to limit preventDefault().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/desktop-client/src/components/table.tsx`:
- Around line 1366-1398: The keydown handler currently calls e.preventDefault()
unconditionally at the top, which blocks all default behaviors; restrict
preventDefault() to only the navigation keys handled in the switch (the
'ArrowUp'/'k', 'ArrowDown'/'j', 'Enter', and 'Tab' cases). Move or add
e.preventDefault() into each handled branch (or just before calling onMove) so
that only when you invoke onMove('up'|'down'|'left'|'right') the default is
prevented; leave other keys untouched. Use the existing symbols (the keydown
handler that references e.key and onMove) to locate where to limit
preventDefault().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 49580719-f778-4a20-8e4b-e333ad2a91ca

📥 Commits

Reviewing files that changed from the base of the PR and between c5fe29d and eaf8034.

📒 Files selected for processing (2)
  • packages/desktop-client/src/components/table.tsx
  • upcoming-release-notes/7283.md

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 25, 2026
@github-actions
Copy link
Contributor

VRT tests ❌ failed. View the test report.

To update the VRT screenshots, comment /update-vrt on this PR. The VRT update operation takes about 50 minutes.

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 25, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/desktop-client/src/components/table.tsx (1)

1366-1400: ⚠️ Potential issue | 🟠 Major

Unconditional preventDefault is over-broad and can suppress unrelated keyboard behavior

Line 1366 cancels default behavior for every key event that reaches this handler, including keys not handled in the switch (default case). Scope preventDefault() to only the navigation keys you actually process.

🔧 Suggested fix
       onKeyDown: e => {
         userProps?.onKeyDown?.(e);
         if (e.isPropagationStopped()) {
           return;
         }
-
-        e.preventDefault();

         switch (e.key) {
           case 'ArrowUp':
           case 'k':
             if (e.target.tagName !== 'INPUT') {
               e.preventDefault();
               onMove('up');
             }
             break;

           case 'ArrowDown':
           case 'j':
             if (e.target.tagName !== 'INPUT') {
               e.preventDefault();
               onMove('down');
             }
             break;

           case 'Enter':
           case 'Tab':
+            e.preventDefault();
             e.stopPropagation();

             onMove(
               e.key === 'Enter'
                 ? e.shiftKey
                   ? 'up'
                   : 'down'
                 : e.shiftKey
                   ? 'left'
                   : 'right',
             );
             break;
           default:
+            return;
         }
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/desktop-client/src/components/table.tsx` around lines 1366 - 1400,
The current handler calls e.preventDefault() unconditionally which suppresses
unrelated key behavior; remove the top-level e.preventDefault() and instead
invoke e.preventDefault() only inside the handled branches (the ArrowUp/'k' and
ArrowDown/'j' branches when e.target.tagName !== 'INPUT', and for Enter/Tab
before calling onMove), preserving the existing e.stopPropagation() on Enter/Tab
and the existing direction logic that uses onMove; update the switch in the
table key handler so the default case does nothing and only navigation keys
prevent default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/desktop-client/src/components/table.tsx`:
- Around line 1366-1400: The current handler calls e.preventDefault()
unconditionally which suppresses unrelated key behavior; remove the top-level
e.preventDefault() and instead invoke e.preventDefault() only inside the handled
branches (the ArrowUp/'k' and ArrowDown/'j' branches when e.target.tagName !==
'INPUT', and for Enter/Tab before calling onMove), preserving the existing
e.stopPropagation() on Enter/Tab and the existing direction logic that uses
onMove; update the switch in the table key handler so the default case does
nothing and only navigation keys prevent default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 481f6dac-f151-4589-899e-12e3765b90ad

📥 Commits

Reviewing files that changed from the base of the PR and between b23bd2b and af1f216.

📒 Files selected for processing (1)
  • packages/desktop-client/src/components/table.tsx

@JSkinnerUK JSkinnerUK force-pushed the ledger-scrolling branch 2 times, most recently from 8a8db1a to 733c6d9 Compare March 25, 2026 14:10
@coderabbitai coderabbitai bot removed the size small label Mar 25, 2026
@JSkinnerUK JSkinnerUK changed the title [WIP] Standardise ledger scrolling when using keyboard shortcuts Standardise ledger scrolling when using keyboard shortcuts Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Inconsistent ledger scrolling when using keyboard shortcuts

2 participants