Skip to content

Minor fixes 0802 #1279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 3, 2025
Merged

Minor fixes 0802 #1279

merged 4 commits into from
Aug 3, 2025

Conversation

duckduckhero
Copy link
Collaborator

@duckduckhero duckduckhero commented Aug 3, 2025

Summary by cubic

Added keyboard navigation support to event, participant, and tag chips for faster selection and improved accessibility.

  • UI Improvements
    • Users can now use arrow keys and Enter to navigate and select items in event, participant, and tag dropdowns.
    • Input focus and selection states are managed for a smoother experience.

Copy link

coderabbitai bot commented Aug 3, 2025

📝 Walkthrough

Walkthrough

Keyboard navigation and focus management were added to the event, participant, and tag selection UIs in the desktop app, including new state variables, input refs, and keyboard event handlers. Localization files were updated to reflect shifted line numbers. An additional guideline was added to a template asset regarding markdown formatting.

Changes

Cohort / File(s) Change Summary
Event Keyboard Navigation
apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx
Added keyboard navigation and improved input focus to the event selection tab. Introduced selectedIndex state, inputRef, and keyboard event listeners for arrow keys, Enter, and Escape. Updated UI to highlight selected events and refactored event selection logic for accessibility and consistency.
Participant Keyboard Navigation
apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx
Refactored participant add and candidate components to support keyboard navigation. Added selectedIndex state, input refs, and keyboard event listeners. Updated component signatures to pass selection state and handlers. UI now highlights the selected candidate or create option, and click/keyboard handlers manage mutations and focus.
Tag Keyboard Navigation
apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx
Enhanced tag add control with keyboard navigation for dropdown suggestions. Added selectedIndex state, input ref, and global keyboard event handling for navigation and selection. Dropdown UI highlights the selected tag or create option, and input focus is managed programmatically.
Localization Reference Updates (EN)
apps/desktop/src/locales/en/messages.po
Updated source code reference line numbers for multiple translation entries to reflect codebase changes. No changes to message content or logic.
Localization Reference Updates (KO)
apps/desktop/src/locales/ko/messages.po
Updated source code reference line numbers for several translation entries to match shifted source files. No changes to message content or logic.
Template Guideline Update
crates/template/assets/enhance.system.jinja
Added a line explicitly prohibiting the use of markdown code blocks in the enhanced note format instructions.

Sequence Diagram(s)

Keyboard Navigation for Event/Participant/Tag Selection

sequenceDiagram
    participant User
    participant InputField
    participant DropdownList
    participant AppState

    User->>InputField: Focus input
    User->>InputField: Type search query
    InputField->>DropdownList: Show filtered options
    User->>InputField: Press ArrowUp/ArrowDown
    InputField->>AppState: Update selectedIndex
    AppState->>DropdownList: Highlight selected option
    User->>InputField: Press Enter
    alt Option selected
        AppState->>DropdownList: Trigger selection handler
        DropdownList->>InputField: Clear input, close dropdown
        InputField->>InputField: Refocus input
    else No option selected
        InputField->>AppState: Create new entry
        AppState->>DropdownList: Update list
    end
    User->>InputField: Press Escape
    InputField->>AppState: Reset selection
    AppState->>InputField: Refocus input
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • Note date change #1236: The main PR enhances keyboard navigation and input focus management specifically within the EventTab component inside event-chip.tsx, which is a subcomponent introduced and refactored in the retrieved PR Note date change #1236 that added the EventTab and related event selection UI; thus, the main PR builds directly on the component structure and functionality established in the retrieved PR.

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch minor-fixes-0802

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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.

Actionable comments posted: 0

🧹 Nitpick comments (3)
crates/template/assets/enhance.system.jinja (1)

70-70: Improve clarity and conciseness of the added guideline.

The new instruction is repetitive and could be more professional. The existing guidelines already cover this requirement adequately.

Consider this more concise alternative:

-- Never use markdown code block. Just use markdown. Never code block. Never use ```.
+- Avoid using markdown code blocks (```). Use plain markdown formatting only.
apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx (1)

423-429: Remove duplicate error handling

The error is already being logged in the assignEvent mutation definition (line 90). The error handling here is redundant.

 const handleSelectEvent = async (eventIdToLink: string) => {
-  assignEvent.mutate(eventIdToLink, {
-    onError: (error) => {
-      console.error("Failed to set session event:", error);
-    },
-  });
+  assignEvent.mutate(eventIdToLink);
 };
apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx (1)

445-456: Consider optimizing the keyboard handler dependencies

The dependency array is extensive and includes mutation objects that change on every render, potentially causing unnecessary effect re-runs.

Consider using useCallback for the mutation handlers to stabilize the references:

+ const handleAddParticipant = useCallback((participant: Human) => {
+   addParticipantByIdMutation.mutate({ id: participant.id });
+   onMutation();
+ }, [addParticipantByIdMutation, onMutation]);
+
+ const handleCreateParticipant = useCallback(() => {
+   addParticipantMutation.mutate({ name: query.trim() });
+   onMutation();
+ }, [addParticipantMutation, query, onMutation]);

Then use these stable callbacks in the keyboard handler instead of inline mutations.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b32ccd and c56a5cb.

📒 Files selected for processing (6)
  • apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx (4 hunks)
  • apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx (7 hunks)
  • apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx (8 hunks)
  • apps/desktop/src/locales/en/messages.po (7 hunks)
  • apps/desktop/src/locales/ko/messages.po (7 hunks)
  • crates/template/assets/enhance.system.jinja (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit Configuration File

**/*.{js,ts,tsx,rs}: 1. No error handling.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx
  • apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx
  • apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: ci (windows, windows-latest)
  • GitHub Check: ci (macos, macos-latest)
  • GitHub Check: ci
🔇 Additional comments (7)
apps/desktop/src/locales/ko/messages.po (1)

347-347: LGTM! Routine localization metadata updates.

The line number references have been correctly updated to reflect source code changes in the related UI components. These are standard maintenance updates required for proper i18n functionality.

Also applies to: 623-623, 903-903, 947-947, 1056-1056, 1251-1251, 1259-1259, 1554-1554

apps/desktop/src/locales/en/messages.po (1)

347-347: LGTM! Routine localization metadata updates.

The source code line references have been properly updated to match the recent changes in the UI components. This is standard maintenance for localization files.

Also applies to: 623-623, 903-903, 947-947, 1056-1056, 1251-1251, 1259-1259, 1554-1554

apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx (2)

310-317: Keyboard navigation state setup looks good!

The addition of selectedIndex for tracking selection and inputRef for focus management, along with the auto-focus on mount, provides a solid foundation for keyboard accessibility.


470-477: UI selection highlighting implemented correctly!

The visual feedback for keyboard navigation using clsx to conditionally apply the background color provides clear indication of the selected item.

apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx (2)

350-356: Proper Enter key handling delegation!

The conditional handling of Enter key based on selection state prevents conflicts between input submission and dropdown item selection.


396-434: Well-structured keyboard navigation for tag dropdown!

The implementation correctly handles navigation between existing tags and the create option, with proper boundary checks and focus management.

apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx (1)

509-534: Clean refactoring of ParticipantCandidate!

The component properly delegates mutation logic to the parent while maintaining visual selection state. This follows React best practices for controlled components.

Copy link

@cubic-dev-ai cubic-dev-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.

cubic analysis

4 issues found across 6 files • Review in cubic

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

@@ -376,9 +387,57 @@ function TagAddControl({ sessionId, allTags }: { sessionId: string; allTags: { i

const handleInputBlur = () => {
// Delay hiding dropdown to allow clicks on dropdown items
setTimeout(() => setShowDropdown(false), 200);
setTimeout(() => {
Copy link

Choose a reason for hiding this comment

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

The timeout created here is not cleared on component unmount; if the component unmounts within 200 ms, setState will be invoked after unmount, producing React warnings and potential memory leaks. Store the timer id in a ref and clear it in a cleanup function.

Prompt for AI agents
Address the following comment on apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx at line 390:

<comment>The timeout created here is not cleared on component unmount; if the component unmounts within 200 ms, setState will be invoked after unmount, producing React warnings and potential memory leaks. Store the timer id in a ref and clear it in a cleanup function.</comment>

<file context>
@@ -376,9 +387,57 @@ function TagAddControl({ sessionId, allTags }: { sessionId: string; allTags: { i
 
   const handleInputBlur = () =&gt; {
     // Delay hiding dropdown to allow clicks on dropdown items
-    setTimeout(() =&gt; setShowDropdown(false), 200);
+    setTimeout(() =&gt; {
+      setShowDropdown(false);
+      setSelectedIndex(-1);
</file context>


if (e.key === "ArrowDown") {
e.preventDefault();
setSelectedIndex(selectedIndex < totalDropdownItems - 1 ? selectedIndex + 1 : 0);
Copy link

Choose a reason for hiding this comment

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

setSelectedIndex is called using the currently-captured value of selectedIndex; if multiple ArrowDown events fire before React re-renders, the update will be computed from a stale value and some key presses will be ignored. Use the functional updater form so each update is based on the latest state.

Prompt for AI agents
Address the following comment on apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx at line 408:

<comment>setSelectedIndex is called using the currently-captured value of selectedIndex; if multiple ArrowDown events fire before React re-renders, the update will be computed from a stale value and some key presses will be ignored. Use the functional updater form so each update is based on the latest state.</comment>

<file context>
@@ -376,9 +387,57 @@ function TagAddControl({ sessionId, allTags }: { sessionId: string; allTags: { i
 
   const handleInputBlur = () =&gt; {
     // Delay hiding dropdown to allow clicks on dropdown items
-    setTimeout(() =&gt; setShowDropdown(false), 200);
+    setTimeout(() =&gt; {
+      setShowDropdown(false);
+      setSelectedIndex(-1);
+    }, 200);
   };
</file context>
Suggested change
setSelectedIndex(selectedIndex < totalDropdownItems - 1 ? selectedIndex + 1 : 0);
setSelectedIndex(prev => (prev < totalDropdownItems - 1 ? prev + 1 : 0));


if (e.key === "ArrowDown") {
e.preventDefault();
setSelectedIndex(selectedIndex < filteredEvents.length - 1 ? selectedIndex + 1 : 0);
Copy link

Choose a reason for hiding this comment

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

setSelectedIndex relies on the stale selectedIndex captured in the closure; use the functional updater to ensure the latest value is used.

Prompt for AI agents
Address the following comment on apps/desktop/src/components/editor-area/note-header/chips/event-chip.tsx at line 397:

<comment>setSelectedIndex relies on the stale selectedIndex captured in the closure; use the functional updater to ensure the latest value is used.</comment>

<file context>
@@ -385,17 +386,64 @@ function EventTab({
       return dateB.getTime() - dateA.getTime();
     });
 
+  useEffect(() =&gt; {
+    const handleKeyDown = (e: KeyboardEvent) =&gt; {
+      if (filteredEvents.length === 0) {
+        return;
+      }
+
</file context>
Suggested change
setSelectedIndex(selectedIndex < filteredEvents.length - 1 ? selectedIndex + 1 : 0);
setSelectedIndex((prev) => prev < filteredEvents.length - 1 ? prev + 1 : 0);

};

if (inputRef.current === document.activeElement && totalItems > 0) {
document.addEventListener("keydown", handleKeyDown);
Copy link

Choose a reason for hiding this comment

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

Keyboard listener attached to document may persist after the input loses focus, leading to unexpected global key handling and memory leaks

Prompt for AI agents
Address the following comment on apps/desktop/src/components/editor-area/note-header/chips/participants-chip.tsx at line 442:

<comment>Keyboard listener attached to document may persist after the input loses focus, leading to unexpected global key handling and memory leaks</comment>

<file context>
@@ -372,7 +396,70 @@ function ParticipantCandidates(
       }),
   });
 
-  const handleClick = () =&gt; {
+  const addParticipantByIdMutation = useMutation({
+    mutationFn: ({ id }: { id: string }) =&gt; dbCommands.sessionAddParticipant(sessionId, id),
+    onSuccess: () =&gt;
+      queryClient.invalidateQueries({
+        predicate: (query) =&gt; (query.queryKey[0] as string).includes(&quot;participants&quot;) &amp;&amp; query.queryKey[1] === sessionId,
</file context>

@duckduckhero duckduckhero merged commit ff0dc70 into main Aug 3, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant