Skip to content

Conversation

@Innei
Copy link
Member

@Innei Innei commented Jan 7, 2026

πŸ“ Summary

Fixes the issue where the input field wasn't properly focused when renaming topics through the context menu.

Resolves LOBE-2838

πŸ” Changes

  • ✨ Created FocusableInput component that ensures input focus using queueMicrotask
  • πŸ”§ Replaced autoFocus prop with proper ref-based focus management
  • 🧹 Simplified onBlur handler logic
  • πŸ—‘οΈ Removed duplicate toggleEditing call from handleUpdate

πŸ’‘ Technical Details

The queueMicrotask approach ensures the focus happens after the Popover has fully rendered and positioned itself, which is necessary for the input to receive focus correctly in the context menu scenario.

βœ… Test Plan

  • Tested topic renaming via context menu - input now properly focuses
  • Verified blur behavior still works correctly
  • Confirmed Enter key submission still functions

Summary by Sourcery

Ensure topic rename inputs in the sidebar context menu receive focus reliably and streamline the editing lifecycle handling.

Bug Fixes:

  • Fix missing focus on the topic rename input when opened from the context menu.

Enhancements:

  • Introduce a reusable FocusableInput wrapper that manages focus via refs instead of relying on the autoFocus prop.
  • Simplify topic editing state transitions by centralizing blur and popover open-state handling and removing redundant toggle calls.

Fixes LOBE-2838

This commit resolves the issue where the input field wasn't properly focused when renaming topics through the context menu.

Changes:
- Created FocusableInput component that ensures input focus using queueMicrotask
- Replaced autoFocus prop with proper ref-based focus management
- Simplified onBlur handler logic
- Removed duplicate toggleEditing call from handleUpdate

The queueMicrotask approach ensures the focus happens after the Popover has fully rendered and positioned itself.
Copilot AI review requested due to automatic review settings January 7, 2026 14:50
@vercel
Copy link

vercel bot commented Jan 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
lobehub Ready Ready Preview, Comment Jan 8, 2026 7:02am

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 7, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refactors the topic renaming popover to use a new ref-based FocusableInput component with microtask-scheduled focusing, simplifies blur/update handling, and centralizes the toggleEditing lifecycle around popover open state.

Sequence diagram for topic renaming popover focus and lifecycle

sequenceDiagram
  actor User
  participant TopicItem
  participant Editing
  participant Popover
  participant FocusableInput
  participant EventLoop
  participant ChatStore

  User->>TopicItem: Open context menu and click Rename
  TopicItem->>Editing: set editing true
  Editing->>Popover: render with open true
  Popover->>FocusableInput: render input
  FocusableInput->>EventLoop: queueMicrotask(focusInput)
  EventLoop->>FocusableInput: run focusInput()
  FocusableInput->>FocusableInput: ref.current.input.focus()

  User->>FocusableInput: Type new title
  FocusableInput->>Editing: onChange(newValue)
  Editing->>Editing: setNewTitle(newValue)

  User->>Popover: Close popover or click outside
  Popover->>Editing: onOpenChange(false)
  Editing->>Editing: handleUpdate()
  alt title changed
    Editing->>ChatStore: updateTopicTitle(id, newTitle)
  end
  Editing->>Editing: toggleEditing(false)
Loading

Class diagram for FocusableInput and Editing components

classDiagram
  class FocusableInput {
    +InputProps props
    -InputRef ref
    +useEffectFocusWithQueueMicrotask()
  }

  class Editing {
    +string id
    +string title
    +function toggleEditing(visible)
    -string newTitle
    -boolean editing
    -function setNewTitle(value)
    -function handleUpdate()
  }

  class ChatStore {
    +function updateTopicTitle(id, newTitle)
  }

  class Popover {
    +boolean open
    +function onOpenChange(open)
    +FocusableInput content
  }

  class Input {
    +function focus()
  }

  FocusableInput --> Input : wraps
  Editing --> FocusableInput : renders
  Editing --> Popover : configures
  Editing --> ChatStore : uses
  Popover o--> FocusableInput : content
Loading

File-Level Changes

Change Details Files
Introduce a FocusableInput component that reliably focuses the input after the popover finishes rendering.
  • Create a FocusableInput wrapper around the existing Input component using a ref of type InputRef.
  • Use useEffect with queueMicrotask to focus the underlying input element once the component is mounted.
  • Forward all received props to the underlying Input while attaching the focus ref.
src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Editing.tsx
Switch from autoFocus to explicit ref-based focus management and simplify update/blur handling for topic renaming.
  • Replace the Input used in the popover content with FocusableInput and remove the autoFocus prop.
  • Simplify the onBlur handler to call handleUpdate only, removing inline logic and duplicate toggleEditing invocation.
  • Rely on Popover onOpenChange to both invoke handleUpdate when closing and call toggleEditing(open), removing the extra toggleEditing(false) call from handleUpdate.
src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Editing.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jan 7, 2026
@gru-agent
Copy link
Contributor

gru-agent bot commented Jan 7, 2026

TestGru Assignment

Summary

Link CommitId Status Reason
Detail 6ff461b 🚫 Skipped No files need to be tested {"src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Editing.tsx":"File path does not match include patterns."}

History Assignment

Tip

You can @gru-agent and leave your feedback. TestGru will make adjustments based on your input

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In FocusableInput, you’re unconditionally setting ref={ref}, which means any ref passed in via InputProps will be ignored; if you intend this to be reusable, consider using forwardRef and focusing the forwarded ref instead so callers can still access the input ref.
  • The handleUpdate callback still lists toggleEditing in its dependency array even though it no longer uses it; you can safely remove that dependency to avoid unnecessary re-creations.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `FocusableInput`, you’re unconditionally setting `ref={ref}`, which means any `ref` passed in via `InputProps` will be ignored; if you intend this to be reusable, consider using `forwardRef` and focusing the forwarded ref instead so callers can still access the input ref.
- The `handleUpdate` callback still lists `toggleEditing` in its dependency array even though it no longer uses it; you can safely remove that dependency to avoid unnecessary re-creations.

## Individual Comments

### Comment 1
<location> `src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Editing.tsx:64-67` </location>
<code_context>
-            handleUpdate();
-            toggleEditing(false);
-          }}
+          onBlur={handleUpdate}
           onChange={(e) => setNewTitle(e.target.value)}
           onClick={(e) => e.stopPropagation()}
</code_context>

<issue_to_address>
**issue (bug_risk):** `handleUpdate` is now invoked from both `onBlur` and `onOpenChange`, which can lead to duplicated updates.

When the input blurs, the popover will likely close and fire `onOpenChange(false)`, causing `handleUpdate` to run twice while `editing` is still `true`. This can result in duplicate `updateTopicTitle` calls for a single edit. To avoid this, either restore `toggleEditing(false)` inside `handleUpdate`, remove the `handleUpdate` call from `onOpenChange` and rely solely on `onBlur`, or make `handleUpdate` idempotent for a given `newTitle` (e.g., by updating local `editing` state or memoizing).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click πŸ‘ or πŸ‘Ž on each comment and I'll use the feedback to improve your reviews.

Copy link
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 fixes an input focus issue when renaming topics through the context menu by implementing a custom FocusableInput component that uses queueMicrotask to ensure focus is applied after the Popover has fully rendered.

  • Created FocusableInput component with ref-based focus management using queueMicrotask
  • Simplified event handlers by removing duplicate toggleEditing(false) calls
  • Cleaned up the onBlur handler to only call handleUpdate

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
}
toggleEditing(false);
}, [newTitle, title, id, updateTopicTitle, toggleEditing]);
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

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

toggleEditing is included in the dependency array but is never used within the handleUpdate function. This can be removed from the dependency array to avoid unnecessary re-creation of the callback.

Suggested change
}, [newTitle, title, id, updateTopicTitle, toggleEditing]);
}, [newTitle, title, id, updateTopicTitle]);

Copilot uses AI. Check for mistakes.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ff461bef2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +62 to 65
<FocusableInput
defaultValue={title}
onBlur={() => {
handleUpdate();
toggleEditing(false);
}}
onBlur={handleUpdate}
onChange={(e) => setNewTitle(e.target.value)}

Choose a reason for hiding this comment

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

P2 Badge Close rename popover on blur to avoid stuck editing

In Editing.tsx, onBlur now only runs handleUpdate without closing editing. If the user tabs away or focus is moved programmatically (no outside click), onOpenChange won’t fire and topicRenamingId stays set, leaving the Popover open and the item disabled until a click occurs. This is a regression from the previous blur behavior and is especially noticeable for keyboard users; consider calling toggleEditing(false) on blur or otherwise closing on focus loss.

Useful? React with πŸ‘Β / πŸ‘Ž.

@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

βœ… All modified and coverable lines are covered by tests.
βœ… Project coverage is 76.10%. Comparing base (e80b073) to head (cd78f00).
⚠️ Report is 8 commits behind head on next.

Additional details and impacted files
@@            Coverage Diff            @@
##             next   #11323     +/-   ##
=========================================
  Coverage   76.10%   76.10%             
=========================================
  Files        1128     1128             
  Lines       86332    86332             
  Branches    12138     9784   -2354     
=========================================
  Hits        65699    65699             
  Misses      20557    20557             
  Partials       76       76             
Flag Coverage Ξ”
app 70.02% <ΓΈ> (ΓΈ)
database 94.08% <ΓΈ> (ΓΈ)
packages/agent-runtime 89.08% <ΓΈ> (ΓΈ)
packages/context-engine 83.19% <ΓΈ> (ΓΈ)
packages/conversation-flow 92.41% <ΓΈ> (ΓΈ)
packages/file-loaders 88.66% <ΓΈ> (ΓΈ)
packages/memory-user-memory 55.64% <ΓΈ> (ΓΈ)
packages/model-bank 100.00% <ΓΈ> (ΓΈ)
packages/model-runtime 86.88% <ΓΈ> (ΓΈ)
packages/prompts 76.23% <ΓΈ> (ΓΈ)
packages/python-interpreter 92.90% <ΓΈ> (ΓΈ)
packages/ssrf-safe-fetch 0.00% <ΓΈ> (ΓΈ)
packages/utils 92.88% <ΓΈ> (ΓΈ)
packages/web-crawler 95.62% <ΓΈ> (ΓΈ)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Ξ”
Store 68.45% <ΓΈ> (ΓΈ)
Services 54.01% <ΓΈ> (ΓΈ)
Server 73.33% <ΓΈ> (ΓΈ)
Libs 41.28% <ΓΈ> (ΓΈ)
Utils 94.40% <ΓΈ> (ΓΈ)
πŸš€ New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • πŸ“¦ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Innei Innei merged commit dd065fc into next Jan 8, 2026
36 checks passed
@Innei Innei deleted the lobe-2838-contextmenu-η»„δ»Άι‡ε‘½εδΈη”Ÿζ•ˆ branch January 8, 2026 07:35
@lobehubbot
Copy link
Member

❀️ Great PR @Innei ❀️

The growth of project is inseparable from user feedback and contribution, thanks for your contribution! If you are interesting with the lobehub developer community, please join our discord and then dm @arvinxx or @canisminor1990. They will invite you to our private developer channel. We are talking about the lobe-chat development or sharing ai newsletter around the world.

lobehubbot pushed a commit that referenced this pull request Jan 8, 2026
## [Version&nbsp;2.0.0-next.238](v2.0.0-next.237...v2.0.0-next.238)
<sup>Released on **2026-01-08**</sup>

#### ✨ Features

- **misc**: Change the klavis Linear to LobeHub oauth Linear.

#### πŸ› Bug Fixes

- **misc**: Topic renaming input focus issue in context menu.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Change the klavis Linear to LobeHub oauth Linear, closes [#11339](#11339) ([ec8ff26](ec8ff26))

#### What's fixed

* **misc**: Topic renaming input focus issue in context menu, closes [#11323](#11323) ([dd065fc](dd065fc))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
@lobehubbot
Copy link
Member

πŸŽ‰ This PR is included in version 2.0.0-next.238 πŸŽ‰

The release is available on:

Your semantic-release bot πŸ“¦πŸš€

JamieStivala pushed a commit to jaworldwideorg/OneJA-Bot that referenced this pull request Jan 8, 2026
## [Version&nbsp;1.150.0](v1.149.0...v1.150.0)
<sup>Released on **2026-01-08**</sup>

#### β™» Code Refactoring

- **memory-user-memory**: Migrated to use typescript module for prompts.

#### ✨ Features

- **image**: Improve image generation with new models and bug fixes.
- **notebook**: Add i18n, Inspector and Streaming components.
- **ui**: Move new topic button to navigation panel.
- **misc**: Add browser compatibility detection and fallback page, add the lobehub market tools servers, add the twitter lobehub skill, change the klavis Linear to LobeHub oauth Linear.

#### πŸ› Bug Fixes

- **editor**: Fix slash command codeblock not working.
- **onboarding**: Prevent step overflow and misc improvements.
- **provider-config**: Update isFetchOnClient Switch component.
- **misc**: Add separate border-radius for bottom-right corner on macOS 26 Chrome, correct BrandTextLoading position after removing SSG CSS-in-JS injection, fix edit rich render codeblock, topic renaming input focus issue in context menu, update desktop onboarding privacy description, update mobile topicRouter import path to lambda directory.

#### πŸ’„ Styles

- **misc**: Update i18n.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### Code refactoring

* **memory-user-memory**: Migrated to use typescript module for prompts, closes [lobehub#11344](https://github.com/jaworldwideorg/OneJA-Bot/issues/11344) ([902cfe5](902cfe5))

#### What's improved

* **image**: Improve image generation with new models and bug fixes, closes [lobehub#11311](https://github.com/jaworldwideorg/OneJA-Bot/issues/11311) ([4fc03bb](4fc03bb))
* **notebook**: Add i18n, Inspector and Streaming components, closes [lobehub#11212](https://github.com/jaworldwideorg/OneJA-Bot/issues/11212) ([f7dc54f](f7dc54f))
* **ui**: Move new topic button to navigation panel, closes [lobehub#11325](https://github.com/jaworldwideorg/OneJA-Bot/issues/11325) ([3d6b399](3d6b399))
* **misc**: Add browser compatibility detection and fallback page, closes [lobehub#11309](https://github.com/jaworldwideorg/OneJA-Bot/issues/11309) ([8be32c2](8be32c2))
* **misc**: Add the lobehub market tools servers, closes [lobehub#11315](https://github.com/jaworldwideorg/OneJA-Bot/issues/11315) ([a4003a3](a4003a3))
* **misc**: Add the twitter lobehub skill, closes [lobehub#11342](https://github.com/jaworldwideorg/OneJA-Bot/issues/11342) ([503acb3](503acb3))
* **misc**: Change the klavis Linear to LobeHub oauth Linear, closes [lobehub#11339](https://github.com/jaworldwideorg/OneJA-Bot/issues/11339) ([ec8ff26](ec8ff26))

#### What's fixed

* **editor**: Fix slash command codeblock not working, closes [lobehub#11321](https://github.com/jaworldwideorg/OneJA-Bot/issues/11321) ([f9a35eb](f9a35eb))
* **onboarding**: Prevent step overflow and misc improvements, closes [lobehub#11322](https://github.com/jaworldwideorg/OneJA-Bot/issues/11322) ([8586fd4](8586fd4))
* **provider-config**: Update isFetchOnClient Switch component, closes [lobehub#11215](https://github.com/jaworldwideorg/OneJA-Bot/issues/11215) ([5bb038b](5bb038b))
* **misc**: Add separate border-radius for bottom-right corner on macOS 26 Chrome, closes [lobehub#11287](https://github.com/jaworldwideorg/OneJA-Bot/issues/11287) ([544931a](544931a))
* **misc**: Correct BrandTextLoading position after removing SSG CSS-in-JS injection, closes [lobehub#11312](https://github.com/jaworldwideorg/OneJA-Bot/issues/11312) ([0de4eb8](0de4eb8))
* **misc**: Fix edit rich render codeblock, closes [lobehub#11303](https://github.com/jaworldwideorg/OneJA-Bot/issues/11303) ([5338170](5338170))
* **misc**: Topic renaming input focus issue in context menu, closes [lobehub#11323](https://github.com/jaworldwideorg/OneJA-Bot/issues/11323) ([dd065fc](dd065fc))
* **misc**: Update desktop onboarding privacy description, closes [lobehub#11307](https://github.com/jaworldwideorg/OneJA-Bot/issues/11307) [lobehub#11308](https://github.com/jaworldwideorg/OneJA-Bot/issues/11308) ([58b10a2](58b10a2))
* **misc**: Update mobile topicRouter import path to lambda directory, closes [lobehub#11261](https://github.com/jaworldwideorg/OneJA-Bot/issues/11261) ([f591b77](f591b77))

#### Styles

* **misc**: Update i18n, closes [lobehub#11297](https://github.com/jaworldwideorg/OneJA-Bot/issues/11297) ([4705abf](4705abf))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
lwshen pushed a commit to lwshen/lobe-chat that referenced this pull request Jan 8, 2026
Fixes LOBE-2838

This commit resolves the issue where the input field wasn't properly focused when renaming topics through the context menu.

Changes:
- Created FocusableInput component that ensures input focus using queueMicrotask
- Replaced autoFocus prop with proper ref-based focus management
- Simplified onBlur handler logic
- Removed duplicate toggleEditing call from handleUpdate

The queueMicrotask approach ensures the focus happens after the Popover has fully rendered and positioned itself.
lwshen pushed a commit to lwshen/lobe-chat that referenced this pull request Jan 8, 2026
## [Version&nbsp;2.0.0-next.238](lobehub/lobehub@v2.0.0-next.237...v2.0.0-next.238)
<sup>Released on **2026-01-08**</sup>

#### ✨ Features

- **misc**: Change the klavis Linear to LobeHub oauth Linear.

#### πŸ› Bug Fixes

- **misc**: Topic renaming input focus issue in context menu.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Change the klavis Linear to LobeHub oauth Linear, closes [lobehub#11339](lobehub#11339) ([ec8ff26](lobehub@ec8ff26))

#### What's fixed

* **misc**: Topic renaming input focus issue in context menu, closes [lobehub#11323](lobehub#11323) ([dd065fc](lobehub@dd065fc))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released on @next size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants