Skip to content

Refactor focus management in FocusElements using callback refs#9852

Merged
deleonio merged 18 commits intodevelopfrom
claude/fix-focus-elements-eIVnw
Mar 27, 2026
Merged

Refactor focus management in FocusElements using callback refs#9852
deleonio merged 18 commits intodevelopfrom
claude/fix-focus-elements-eIVnw

Conversation

@deleonio
Copy link
Copy Markdown
Contributor

Summary

Refactored the focus management logic in the FocusElements component to use a callback ref instead of useLayoutEffect with useRef. This improves the reliability of focus handling by ensuring focus is set whenever a component instance mounts.

Key Changes

  • Replaced useRef and useLayoutEffect with a useCallback ref that fires on component mount
  • Moved component lookup logic earlier in the render flow for better code organization
  • Memoized the Element component type using useMemo to prevent unnecessary unmount/remount cycles during re-renders
  • Removed unused imports (useLayoutEffect, useRef) and added useCallback

Implementation Details

  • The callback ref (focusRef) now directly receives the component instance when it mounts, eliminating the need for a separate effect hook
  • The 500ms timeout is preserved to prevent layout glitches in Playwright snapshots
  • Memoizing the Element component ensures it maintains referential equality across re-renders unless the underlying Component changes, preventing unnecessary component lifecycle cycles
  • This approach is more declarative and aligns better with React's ref callback semantics

https://claude.ai/code/session_01KMmPfsTZpdvhQ3BGDgp39M

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the focus management within the FocusElements component. The core change involves transitioning from a useRef and useLayoutEffect pattern to a more declarative useCallback ref. This change aims to enhance the reliability of focus setting upon component mounting. Additionally, the PR improves code organization by relocating component lookup logic and optimizes rendering performance by memoizing the dynamically created Element component type.

Highlights

  • Refactor Focus Management: Replaced useRef and useLayoutEffect with a useCallback ref for focus handling, ensuring focus is set reliably on component mount.
  • Code Organization: Moved component lookup logic earlier in the render flow for improved clarity and structure.
  • Performance Optimization: Memoized the Element component type using useMemo to prevent unnecessary unmount/remount cycles during re-renders.
  • Dependency Management: Removed unused imports (useLayoutEffect, useRef) and added useCallback to reflect the new implementation.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

🚀 MCP preview deployed to Vercel: https://kolibri-1uap4dkfn-public-ui-kolibri-mcp.vercel.app

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the FocusElements component by replacing useLayoutEffect and useRef with a useCallback ref for handling focus on dynamically rendered components. The review highlights a potential issue where the setTimeout within the focusRef callback is not properly cleaned up, which could lead to memory leaks or attempts to focus unmounted elements. It is suggested to use useRef to manage and clear the timeout.

Comment thread packages/samples/react/src/scenarios/focus-elements.tsx
Comment thread packages/samples/react/src/scenarios/focus-elements.tsx
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch 8 times, most recently from c48baeb to b2b6dc4 Compare March 24, 2026 12:55
@deleonio deleonio requested a review from BF150 March 24, 2026 13:08
Comment thread packages/components/src/components/badge/shadow.tsx Outdated
Comment thread packages/components/src/components/link/component.tsx Outdated
Comment thread packages/components/src/components/popover-button/component.tsx Outdated
Comment thread packages/components/src/components/select/component.tsx Outdated
Comment thread packages/components/src/components/table-stateless/component.tsx
Comment thread packages/components/src/components/popover/component.tsx Outdated
Comment thread packages/components/src/components/combobox/shadow.tsx Outdated
Comment thread packages/components/src/utils/element-focus.ts Outdated
Comment thread packages/components/src/components/toolbar/shadow.tsx
Comment thread packages/components/src/components/tree/shadow.tsx
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch 8 times, most recently from f6f734a to bc7c7a2 Compare March 25, 2026 04:27
@deleonio deleonio requested a review from Copilot March 25, 2026 04:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR broadens and refactors focus handling across the KoliBri component library and its sample/visual-test setup: it updates the React “FocusElements” scenario, introduces a shared delegateFocus helper for Stencil components, and adjusts several components’ focus() implementations (plus associated tests and snapshots) to make focus behavior more reliable in automated testing.

Changes:

  • Refactors sample app focus scenario to use callback refs and adds additional components (badge, popoverButton, skipNav, splitButton, tabs, toolbar, tree) to the focus test matrix.
  • Adds delegateFocus() utility and updates many components’ focus() methods to use/participate in the new focus delegation approach (incl. tree focus behavior and new focus-related E2E tests).
  • Updates visual-test routes and adds/updates theme snapshots for the newly covered focus scenarios.

Reviewed changes

Copilot reviewed 47 out of 61 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/tools/visual-tests/tests/sample-app.routes.js Adds visual-test routes for additional focus-elements scenarios.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-tree-firefox-linux.png New kern theme snapshot for tree focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-toolbar-firefox-linux.png New kern theme snapshot for toolbar focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-tabs-firefox-linux.png New kern theme snapshot for tabs focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-splitButton-firefox-linux.png New kern theme snapshot for splitButton focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-skipNav-firefox-linux.png New kern theme snapshot for skipNav focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-popoverButton-firefox-linux.png New kern theme snapshot for popoverButton focus scenario.
packages/themes/kern/snapshots/theme-kern_v2/snapshot-for-scenarios-focus-elements-component-badge-firefox-linux.png New kern theme snapshot for badge focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-tree-firefox-linux.png New default theme snapshot for tree focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-toolbar-firefox-linux.png New default theme snapshot for toolbar focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-tabs-firefox-linux.png New default theme snapshot for tabs focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-splitButton-firefox-linux.png New default theme snapshot for splitButton focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-skipNav-firefox-linux.png New default theme snapshot for skipNav focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-popoverButton-firefox-linux.png New default theme snapshot for popoverButton focus scenario.
packages/themes/default/snapshots/theme-default/snapshot-for-scenarios-focus-elements-component-badge-firefox-linux.png New default theme snapshot for badge focus scenario.
packages/samples/react/src/scenarios/focus-elements.tsx Refactors focus handling using callback refs; expands tested components list.
packages/components/src/utils/element-focus.ts Introduces delegateFocus() helper for themed/ready focus delegation.
packages/components/src/functional-components/Button/tests/snapshot.test.tsx Updates button focus snapshot test to use new focus behavior/signature.
packages/components/src/components/tree/tree.e2e.ts Adds tree focus E2E test validating focus lands on first item.
packages/components/src/components/tree/test/snapshots/snapshot.spec.tsx.snap Updates tree snapshot to reflect tabindex changes.
packages/components/src/components/tree/shadow.tsx Adds focus method to kol-tree delegating focus through theming readiness.
packages/components/src/components/tree/component.tsx Adds focus behavior/caching changes and tabindex for kol-tree-wc.
packages/components/src/components/tree-item/component.tsx Updates tree-item focus interactions and cache invalidation hooks.
packages/components/src/components/tooltip/component.tsx Minor typing change (readonly host).
packages/components/src/components/toolbar/toolbar.e2e.ts Adds toolbar focus() method E2E coverage.
packages/components/src/components/toolbar/shadow.tsx Adds focus() method for toolbar to focus current active item.
packages/components/src/components/textarea/shadow.tsx Switches textarea focus() to use delegateFocus().
packages/components/src/components/tabs/shadow.tsx Implements focus() for tabs (focus current selected tab button).
packages/components/src/components/table-stateless/test/snapshot.spec.tsx Updates snapshot test to new renamed WC class.
packages/components/src/components/table-stateless/component.tsx Renames WC class to KolTableStatelessWc.
packages/components/src/components/split-button/shadow.tsx Updates split-button focus() to delegate via host.
packages/components/src/components/skip-nav/shadow.tsx Updates skip-nav focus() to delegate via host.
packages/components/src/components/single-select/shadow.tsx Switches single-select focus() to use delegateFocus().
packages/components/src/components/select/shadow.tsx Updates select focus() to delegate to WC focus with host.
packages/components/src/components/select/component.tsx Changes select-wc focus signature to use delegateFocus(host, ...).
packages/components/src/components/popover-button/shadow.tsx Updates popover-button focus() delegation via host.
packages/components/src/components/popover-button/component.tsx Renames WC class and updates focus signature to accept host.
packages/components/src/components/link/shadow.tsx Updates link focus() to delegate via host.
packages/components/src/components/link/component.tsx Changes link-wc focus signature to use delegateFocus(host, ...).
packages/components/src/components/link-button/shadow.tsx Updates link-button focus() delegation via host.
packages/components/src/components/input-text/shadow.tsx Switches input-text focus() to use delegateFocus().
packages/components/src/components/input-range/shadow.tsx Switches input-range focus() to use delegateFocus().
packages/components/src/components/input-radio/shadow.tsx Switches input-radio focus() to use delegateFocus().
packages/components/src/components/input-password/shadow.tsx Switches input-password focus() to use delegateFocus().
packages/components/src/components/input-number/shadow.tsx Switches input-number focus() to use delegateFocus().
packages/components/src/components/input-file/shadow.tsx Switches input-file focus() to use delegateFocus().
packages/components/src/components/input-email/shadow.tsx Switches input-email focus() to use delegateFocus().
packages/components/src/components/input-date/shadow.tsx Switches input-date focus() to use delegateFocus().
packages/components/src/components/input-color/shadow.tsx Switches input-color focus() to use delegateFocus().
packages/components/src/components/input-checkbox/shadow.tsx Switches input-checkbox focus() to use delegateFocus() and adjusts keydown wiring.
packages/components/src/components/input-checkbox/input-checkbox.e2e.ts Adds E2E coverage for focus() and focus delegation behavior.
packages/components/src/components/form/shadow.tsx Fixes host typing; adjusts first-link ref typing/cast.
packages/components/src/components/details/shadow.tsx Updates details focus() to delegate via host.
packages/components/src/components/combobox/shadow.tsx Switches combobox focus() to use delegateFocus().
packages/components/src/components/button/shadow.tsx Updates button focus() to delegate via host.
packages/components/src/components/button/component.tsx Changes button-wc focus signature to use delegateFocus(host, ...) and adjusts event dispatch typing.
packages/components/src/components/button-link/shadow.tsx Updates button-link focus() to delegate via host.
packages/components/src/components/badge/shadow.tsx Updates badge focus() to delegate via host.
packages/components/src/components/alert/component.tsx Minor event dispatch typing simplification.
packages/components/src/components/accordion/shadow.tsx Updates accordion focus() to delegate via host.
packages/adapters/hydrate/test/snapshots/components.spec.js.mocha-snapshot Updates hydrate snapshots to reflect tree tabindex changes.

Comment thread packages/samples/react/src/scenarios/focus-elements.tsx
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch from c4dd31e to 78a6915 Compare March 25, 2026 06:48
- Added focus method to KolTreeWc to set focus on the first focusable tree item.
- Implemented cache invalidation for open tree items to improve performance.
- Introduced requestAnimationFrame for debouncing tree change handling.
- Updated KolTree to delegate focus to KolTreeWc and handle focus events.
- Enhanced keyboard navigation for tree items to improve user experience.
- Added end-to-end tests for focus management and performance stability.
- Updated snapshots for various components to reflect new focus behavior.
- Introduced utility function for delegating focus to ensure elements are ready.
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch from 78a6915 to 90334b2 Compare March 25, 2026 06:52
@laske185 laske185 added v4 and removed v2 v3 v4 labels Mar 26, 2026
@deleonio deleonio mentioned this pull request Mar 26, 2026
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch from 8a41354 to c9aab5a Compare March 26, 2026 16:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 46 out of 60 changed files in this pull request and generated 15 comments.

Comment thread packages/components/src/components/tabs/shadow.tsx
Comment thread packages/components/src/components/button-link/shadow.tsx
Comment thread packages/components/src/components/popover-button/shadow.tsx
Comment thread packages/components/src/components/skip-nav/shadow.tsx
Comment thread packages/components/src/components/select/shadow.tsx
Comment thread packages/components/src/components/badge/shadow.tsx
Comment thread packages/components/src/components/button/shadow.tsx
Comment thread packages/components/src/components/link-button/shadow.tsx
Comment thread packages/components/src/components/link/shadow.tsx
Comment thread packages/components/src/components/split-button/shadow.tsx
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch from ee9a0d5 to 18b7a60 Compare March 26, 2026 16:34
@deleonio deleonio moved this from 🏗 In progress to 🔍 Review in KoliBri Board Mar 27, 2026
@deleonio deleonio removed this from KoliBri Board Mar 27, 2026
@deleonio deleonio force-pushed the claude/fix-focus-elements-eIVnw branch from 802dbfe to 2a3e4ee Compare March 27, 2026 07:19
@deleonio deleonio merged commit f4bd861 into develop Mar 27, 2026
11 checks passed
@deleonio deleonio deleted the claude/fix-focus-elements-eIVnw branch March 27, 2026 09:52
@publicuibot publicuibot bot locked and limited conversation to collaborators Mar 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fokus-Management bei dynamisch gerenderten Input-Feldern: Unerwartetes Focus-Stealing

4 participants