Skip to content

feat/tab complete emnojis#67

Merged
ValwareIRC merged 7 commits into
mainfrom
feat/tab-complete-emnojis
Sep 29, 2025
Merged

feat/tab complete emnojis#67
ValwareIRC merged 7 commits into
mainfrom
feat/tab-complete-emnojis

Conversation

@matheusfillipe
Copy link
Copy Markdown
Contributor

@matheusfillipe matheusfillipe commented Sep 29, 2025

image

Summary by CodeRabbit

  • New Features

    • Emoji autocomplete in chat: type “:word” and press Tab to insert emojis.
    • Displays a dropdown with up to 10 matches, showing emoji, names, and category.
    • Keyboard support: Arrow Up/Down to navigate, Enter to select, Escape/Space to close; mouse hover/click supported.
    • Integrates with existing Tab completion and respects input cursor position.
  • Chores

    • Added emoji data dependency to support autocomplete.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 29, 2025

Walkthrough

Adds emoji autocomplete to the chat input. Introduces a new hook for emoji completion, a dropdown UI component for emoji suggestions, integrates keyboard handling in ChatArea, and adds the emoji-datasource dependency to supply emoji data.

Changes

Cohort / File(s) Summary
Dependency update
package.json
Adds emoji-datasource@^16.0.0 to dependencies.
ChatArea integration
src/components/layout/ChatArea.tsx
Integrates emoji completion: imports hook and dropdown, manages emoji-related UI state, augments key handling (Tab/Arrow/Enter/Escape), updates text and cursor during emoji matches, and renders EmojiAutocompleteDropdown.
Emoji completion hook
src/hooks/useEmojiCompletion.ts
New hook implementing colon-triggered emoji matching, cycling via Tab, replacement logic, state tracking, reset, and helpers. Processes data from emoji-datasource into match items.
Emoji dropdown UI
src/components/ui/EmojiAutocompleteDropdown.tsx
New dropdown component rendering up to 10 emoji matches with keyboard/mouse interaction, auto-scroll, positioning near the input, and selection/navigation/close handlers. Exports default.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant ChatArea
  participant useEmojiCompletion as useEmojiCompletion (hook)
  participant EmojiDropdown as EmojiAutocompleteDropdown

  User->>ChatArea: Type text (e.g., ":sm")
  ChatArea->>useEmojiCompletion: handleEmojiCompletion(prefix detection)
  useEmojiCompletion-->>ChatArea: matches, currentIndex, updated text/cursor
  ChatArea->>EmojiDropdown: render(isVisible, matches, currentIndex)

  alt User presses Tab
    ChatArea->>useEmojiCompletion: cycle to next match
    useEmojiCompletion-->>ChatArea: updated text/cursor, index
    ChatArea->>EmojiDropdown: update highlight
  end

  alt User presses Enter or clicks item
    User->>ChatArea: Select current match
    ChatArea->>useEmojiCompletion: finalize/reset
    ChatArea->>EmojiDropdown: close
  else User presses Escape or types non-matching
    ChatArea->>useEmojiCompletion: reset
    ChatArea->>EmojiDropdown: close
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ValwareIRC

Poem

A twitch of whiskers, a hop of delight,
I tab through icons, bright on the night.
From :sm to smile, my paws dance free—
A dropdown blooms with emoji glee.
Click, select—carrots for all!
Autocomplete answers the chatty call. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat/tab complete emnojis" is related to the main change in the changeset, which implements tab completion functionality for emojis across multiple files including a new hook, UI component, and integration in ChatArea. However, the title contains a typo ("emnojis" instead of "emojis") and uses what appears to be a branch naming convention ("feat/") as part of the title itself, which reduces clarity. While the core intent is clear and accurately describes the primary feature being added, the formatting and typo issues make it less polished than ideal for a pull request title that will appear in project history.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tab-complete-emnojis

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
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

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

@github-actions
Copy link
Copy Markdown

Pages Preview
Preview URL: https://feat-tab-complete-emnojis.obsidianirc.pages.dev

Automated deployment preview for the PR in the Cloudflare Pages.

@matheusfillipe matheusfillipe force-pushed the feat/tab-complete-emnojis branch from 8acfc98 to 7aab2cb Compare September 29, 2025 20:39
Copy link
Copy Markdown
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.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/hooks/useEmojiCompletion.ts (1)

113-127: Consider removing redundant length check (optional).

The regex pattern /:([a-zA-Z_]+)$/ already requires at least one character after the colon (the + quantifier), so the check on line 125 (if (emojiQuery.length === 0)) is redundant. However, this is harmless and may serve as defensive programming for future regex changes.

If you prefer a leaner implementation, you can remove lines 125-127:

-        if (emojiQuery.length === 0) {
-          return null;
-        }
-
src/components/ui/EmojiAutocompleteDropdown.tsx (1)

125-170: Consider adding accessibility attributes (recommended).

The dropdown renders correctly and handles user interactions well. To improve accessibility, consider adding ARIA attributes such as role="listbox", role="option", and aria-selected to support screen readers and keyboard-only navigation.

Example enhancement:

     <div
       ref={dropdownRef}
+      role="listbox"
       className="fixed z-[9999] bg-discord-dark-300 border border-discord-dark-500 rounded-md shadow-xl max-w-xs min-w-48"
       style={{
         top: position.top,
         left: position.left,
       }}
     >
       <div className="py-1 max-h-60 overflow-y-auto">
         <div className="px-3 py-1 text-xs text-discord-text-muted font-semibold uppercase tracking-wide border-b border-discord-dark-500">
           Emojis
         </div>
         {displayEmojis.map((emojiItem, index) => (
           <div
             key={`${emojiItem.unified}-${index}`}
             data-emoji-index={index}
+            role="option"
+            aria-selected={index === selectedIndex}
             className={`px-3 py-2 cursor-pointer flex items-center gap-2 transition-colors duration-150 ${
               index === selectedIndex
                 ? "bg-discord-text-link text-white"
                 : "text-discord-text-normal hover:bg-discord-dark-200 hover:text-white"
             }`}
             onClick={() => onSelect(emojiItem.emoji)}
             onMouseEnter={() => setSelectedIndex(index)}
           >
src/components/layout/ChatArea.tsx (1)

354-371: Consider aligning regex patterns for consistency (optional).

The Tab key handling logic is sound. However, line 363 uses the regex /:([a-zA-Z_]*)$/ (allowing zero characters after colon), while the hook uses /:([a-zA-Z_]+)$/ (requiring at least one character). This inconsistency means typing just : and pressing Tab will attempt emoji completion here but the hook will return null. While this doesn't break functionality, aligning the patterns improves clarity.

Consider changing line 363 to match the hook's pattern:

-        const emojiMatch = textBeforeCursor.match(/:([a-zA-Z_]*)$/);
+        const emojiMatch = textBeforeCursor.match(/:([a-zA-Z_]+)$/);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0427a0e and 5569293.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • src/components/layout/ChatArea.tsx (9 hunks)
  • src/components/ui/EmojiAutocompleteDropdown.tsx (1 hunks)
  • src/hooks/useEmojiCompletion.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/layout/ChatArea.tsx (2)
src/hooks/useEmojiCompletion.ts (1)
  • useEmojiCompletion (59-200)
src/components/ui/EmojiAutocompleteDropdown.tsx (1)
  • EmojiAutocompleteDropdown (23-171)
🔇 Additional comments (16)
package.json (1)

33-33: LGTM! Dependency addition looks good.

The emoji-datasource package at version ^16.0.0 is correctly added to support the new emoji completion feature. Based on learnings, this version provides Unicode Emoji 16.x support with updated emoji metadata and image sets.

src/hooks/useEmojiCompletion.ts (5)

1-57: LGTM! Type definitions and emoji data processing are well-structured.

The interfaces clearly define the data flow, and the processedEmojiData transformation correctly converts Unicode hex sequences to rendered emoji characters using String.fromCodePoint. Computing this once at module load is efficient.


59-91: LGTM! State management and helper callbacks are correctly implemented.

The hook uses useState for completion state and useRef to track the previous text for manual edit detection. All callbacks are properly memoized with useCallback and have correct dependency arrays.


130-140: LGTM! Emoji matching logic is sound.

The filter correctly checks if any short_name contains the query (case-insensitive) and limits results to 10 matches. Returning null when no matches are found is appropriate.


142-183: LGTM! Text replacement and cycling logic are correctly implemented.

Both the initial emoji insertion and subsequent cycling through matches correctly construct the new text, update cursor position, and maintain internal state. The use of modulo arithmetic for wrapping is appropriate.


188-200: LGTM! Hook return value is complete and well-typed.

All state properties and helper functions are correctly exposed, matching the EmojiCompletionResult interface definition.

src/components/ui/EmojiAutocompleteDropdown.tsx (4)

1-35: LGTM! Component structure and props are well-defined.

The EmojiAutocompleteDropdownProps interface clearly defines all necessary props, with sensible defaults for optional properties. The component signature is clean and follows React best practices.


36-57: LGTM! State and scroll effects are correctly implemented.

The component properly syncs selectedIndex with external currentMatchIndex and smoothly scrolls the selected item into view. While using querySelector could be replaced with refs for better performance, the impact is negligible for a maximum of 10 items.


59-103: Verify Space key behavior for UX.

The keyboard handler correctly prevents default actions and manages navigation. However, the Space key (line 93) closes the dropdown. This might be unexpected if a user wants to exit emoji completion by typing a space (e.g., after :smile ). Consider whether Space should close the dropdown or simply reset completion and insert a space.

Additionally, the document-level event listener with capture: true is necessary to intercept events before other handlers, but be aware it can interfere with other components. The cleanup is correctly implemented, so this is just a note for maintainability.


109-121: LGTM! Position calculation is appropriate for chat UI.

The dropdown is positioned above the input, which is correct for typical chat interfaces where the input is at the bottom of the viewport. However, note that if the input is near the top of the viewport, the dropdown might render off-screen. This is an edge case and unlikely in the typical chat layout, but consider adding viewport boundary checks if this becomes an issue in testing.

src/components/layout/ChatArea.tsx (6)

22-22: LGTM! Imports and hook initialization are correct.

The new useEmojiCompletion hook and EmojiAutocompleteDropdown component are properly imported, and the showEmojiAutocomplete state is added to manage dropdown visibility. The hook is initialized alongside the existing tabCompletion hook, maintaining consistency.

Also applies to: 39-39, 87-87, 131-132


376-382: LGTM! Autocomplete key handling correctly extended.

The condition now properly checks for both showAutocomplete and showEmojiAutocomplete, allowing either dropdown to handle navigation keys without interference.


460-489: LGTM! Emoji completion handler mirrors tab completion flow.

The handleEmojiCompletion function correctly integrates the emoji completion hook, updates the message text and cursor position, and manages dropdown visibility. The pattern is consistent with the existing handleTabCompletion function, which aids maintainability.


491-512: LGTM! Input change handler correctly resets emoji completion.

The handleInputChange function properly resets both tab and emoji completion states when the user types, and hides both dropdowns. This maintains consistent behavior across completion types.


585-662: LGTM! Emoji autocomplete handlers are correctly implemented.

All three handlers (handleEmojiAutocompleteSelect, handleEmojiAutocompleteClose, handleEmojiAutocompleteNavigate) correctly manage text replacement, cursor positioning, and state synchronization. The call to updatePreviousText in the navigate handler is crucial for preventing false resets during navigation.


1193-1203: LGTM! EmojiAutocompleteDropdown integration is complete.

The dropdown is correctly rendered with all necessary props, and the visibility condition (showEmojiAutocomplete || emojiCompletion.isActive) ensures it displays at the appropriate times. The integration is consistent with the existing AutocompleteDropdown pattern.

@ValwareIRC ValwareIRC merged commit 1047b45 into main Sep 29, 2025
4 checks passed
zocram4cc pushed a commit to zocram4cc/ObsidianIRC that referenced this pull request Feb 17, 2026
* Improved emoji dialog

And click again to just add

* DRY types in ircclient

* Split and refactor chat area a little

* lint fix

* Use same emoji picker everywhere

* tab complete emojis
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.

2 participants