## Problem Tab navigation between input widgets was not working in Fixed Layout applications. Users reported that pressing the Tab key would not move focus to the next input widget in the expected order (top-to-bottom, left-to-right), instead following the browser's default DOM-based tab order. This issues was raised by an Enterprise user [here](https://theappsmith.slack.com/archives/C0341RERY4R/p1758112042665109) ## Root Cause The issue was caused by a **timing problem** in the `useWidgetFocus` hook: 1. The `useEffect` hook was running immediately when the component mounted 2. However, the canvas element ref (`ref.current`) was set later via the React ref callback 3. This caused the event listeners for Tab navigation to never be attached, as `ref.current` was `null` when `useEffect` ran 4. Without the custom Tab event listeners, the browser fell back to its default tab navigation behavior ## Solution Refactored the `useWidgetFocus` hook to attach event listeners **immediately when the ref is set**, rather than waiting for a `useEffect` that runs too early: ### Before (Broken): ```typescript useEffect(() => { if (!ref.current) return; // ❌ Always true - ref not set yet const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Tab") handleTab(event); }; ref.current.addEventListener("keydown", handleKeyDown); }, []); // ❌ Runs before ref is set ``` ### After (Fixed): ```typescript const setRef = useCallback((node: HTMLElement | null) => { if (node === null) return; if (ref.current === node) return; ref.current = node; attachEventListeners(node); // ✅ Attach immediately when ref is set }, [attachEventListeners]); ``` ## Why This Solution Works 1. **Correct Timing**: Event listeners are now attached immediately when React calls the ref callback with the DOM element 2. **No Race Conditions**: Eliminates the timing issue between `useEffect` and ref assignment 3. **Maintains Functionality**: Preserves all existing tab navigation logic (position-based sorting, modal focus trapping, etc.) 4. **Clean Architecture**: Separates event listener attachment logic into a reusable callback ## Testing - ✅ Tab navigation now works correctly in Fixed Layout applications - ✅ Maintains proper top-to-bottom, left-to-right tab order - ✅ Modal focus trapping continues to work - ✅ Auto Layout behavior unchanged (tab navigation disabled as intended) - ✅ No regressions in existing functionality ## Files Changed - `app/client/src/utils/hooks/useWidgetFocus/useWidgetFocus.tsx` - Fixed event listener timing - `app/client/src/utils/hooks/useWidgetFocus/handleTab.ts` - Cleaned up (no functional changes) - `app/client/src/utils/hooks/useWidgetFocus/tabbable.ts` - Cleaned up (no functional changes) ## Automation /ok-to-test tags="@tag.Widget" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/18034264649> > Commit: ab9af8404302eb19c243dea583160bc9e74f33aa > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=18034264649&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Widget` > Spec: > <hr>Fri, 26 Sep 2025 11:09:55 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved reliability of focusing widgets on click. * More consistent Tab key navigation across widgets. * Prevents unintended focus behavior in non–auto-layout mode. * **Refactor** * Streamlined event listener management for focus and keyboard interactions, improving stability and reducing potential memory leaks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|---|---|---|
| .cursor | ||
| .github | ||
| app | ||
| contributions | ||
| deploy | ||
| scripts | ||
| static | ||
| .coderabbit.yaml | ||
| .deepsource.toml | ||
| .editorconfig | ||
| .env.example | ||
| .gitignore | ||
| .imgbotconfig | ||
| .nojekyll | ||
| app.json | ||
| appsmith_events.md | ||
| appsmith_templates.md | ||
| ci-debug.sh | ||
| CODE_OF_CONDUCT.md | ||
| CODEOWNERS | ||
| CONTRIBUTING.md | ||
| depot.json | ||
| Dockerfile | ||
| heroku.yml | ||
| IssuesReport.md | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
Organizations build custom applications like dashboards, admin panels, customer 360, IT automation, and service management tools to help their teams work more efficiently and effectively. Appsmith is an open-source low-code platform that streamlines custom application development, deployment, and maintenance. Learn more on our website.
Installation
There are two ways to start using Appsmith:
- Signup on Appsmith Cloud.
- Install Appsmith on your machine. See the installation guides below.
| Installation Methods | Documentation |
|---|---|
| Docker (Recommended) | |
| Kubernetes | |
| AWS AMI |
For other deployment options, see the Installation Guides documentation.
Development
To build and run Appsmith in your local dev environment, see Setup for local development.
Learning Resources
Need Help?
Appsmith Agents
Introducing a new agentic AI platform that integrates the latest AI models with private and proprietary data at scale — inside the tools and systems that teams use every day. Appsmith Agents expands generative AI’s capabilities for the millions of knowledge workers in sales, support, customer success, human resources, and other business teams. By giving continuous context to AI models, Appsmith Agents lets teams ask questions and configure automations specific to their business without model fine-tuning or complex RAG implementations. Visit appsmith.com/ai to learn more.
Contributing
We ❤️ our contributors. We're committed to fostering an open, welcoming, and safe environment in the community.
📕 We expect everyone participating in the community to abide by our Code of Conduct. Please read and follow it.
🤝 If you'd like to contribute, start by reading our Contribution Guide.
👾 Explore some good first issues.
Let's build great software together.
Top Contributors
License
Appsmith is licensed under the terms of Apache License 2.0.
