Skip to content

Bug fixes#601

Merged
feruzm merged 3 commits into
developfrom
fixes
Jan 2, 2026
Merged

Bug fixes#601
feruzm merged 3 commits into
developfrom
fixes

Conversation

@feruzm
Copy link
Copy Markdown
Member

@feruzm feruzm commented Jan 2, 2026

Summary by CodeRabbit

  • New Features

    • Emoji picker now uses state-driven visibility, improved positioning, focus/outside-click handling, and accepts a trigger ref for reliable placement.
    • GIF picker now refreshes results whenever filters change.
  • Bug Fixes

    • Polls: validation and defaults now require at least 1 choice; unspecified or falsy max-choices are normalized to 1.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Refactors EmojiPicker from anchor-based to parent-controlled visibility (show/changeState/buttonRef) across multiple consumers; replaces ClickAwayListener with pointerdown handling. Poll maxChoices defaulting now uses logical OR to coerce falsy values to 1. GIF picker refetch moved to useEffect on filter changes.

Changes

Cohort / File(s) Summary
Emoji Picker Core Refactor
apps/web/src/features/ui/emoji-picker/index.tsx
Replaced anchor prop and internal visibility with show, changeState, buttonRef, rootRef, style; moved positioning to compute from buttonRef; removed internal show state and isMounted, added pointerdown outside-click handler; onSelect now calls changeState(false).
Emoji Picker Consumers
apps/web/src/app/decks/_components/deck-settings/decks-settings.tsx, apps/web/src/app/decks/_components/deck-threads-form/deck-threads-form-emoji-picker.tsx, apps/web/src/app/publish/_components/publish-editor-toolbar.tsx, apps/web/src/features/chat/components/message-input.tsx, apps/web/src/features/shared/editor-toolbar/index.tsx, apps/web/src/features/waves/components/wave-form/wave-form-emoji-picker.tsx
Replaced anchor-based integration with local show/showEmojiPicker boolean state and buttonRef; toggle the picker via button onClick; render EmojiPicker conditionally with show, changeState, onSelect, and buttonRef; removed ClickAwayListener usage.
Poll maxChoices Defaulting & Validation
apps/web/src/features/entry-management/entry-metadata-manager/entry-metadata-builder.ts, apps/web/src/features/polls/components/poll-widget.tsx, apps/web/src/features/polls/components/polls-creation.tsx, apps/web/src/features/polls/hooks/use-entry-poll-extractor.ts
Replaced ?? 1 with `
GIF Picker Data Refresh
apps/web/src/app/publish/_components/publish-gif-picker-dialog.tsx, apps/web/src/features/ui/gif-picker/index.tsx
Replaced mount-only refresh with useEffect that calls refetch() when filter (and refetch) change, making data refresh reactive to filter updates.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant Parent as Parent Component
    participant EmojiPicker as EmojiPicker
    participant DOM as Document/Viewport

    rect rgb(220,240,200)
    note right of Parent: NEW STATE-DRIVEN FLOW
    User->>Parent: Click emoji button
    Parent->>Parent: Toggle show state (show = true)
    Parent->>EmojiPicker: Render with show=true, buttonRef, changeState
    EmojiPicker->>DOM: Compute position from buttonRef, render at coords
    User->>EmojiPicker: Select emoji
    EmojiPicker->>Parent: onSelect(...) then changeState(false)
    Parent->>Parent: Update show = false (unmount/hide)
    alt Click outside
      User->>DOM: pointerdown outside
      EmojiPicker->>Parent: changeState(false)
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble code and leap with glee,
New pickers free from anchors, you see.
One as default where zeros once slept,
GIFs now refetch when filters have crept.
Hooray — a tidy hop for me! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive The title 'Bug fixes' is extremely vague and does not convey what specific bugs were fixed or the main focus of the changeset. Replace with a specific title that describes the main changes, such as 'Refactor emoji picker to use state-driven visibility' or 'Fix emoji picker and poll configuration handling'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between accbb64 and 09c2ca5.

📒 Files selected for processing (5)
  • apps/web/public/sw.js
  • apps/web/src/app/publish/_components/publish-gif-picker-dialog.tsx
  • apps/web/src/features/polls/hooks/use-entry-poll-extractor.ts
  • apps/web/src/features/ui/emoji-picker/index.tsx
  • apps/web/src/features/ui/gif-picker/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/src/features/ui/gif-picker/index.tsx
  • apps/web/src/features/polls/hooks/use-entry-poll-extractor.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
apps/web/src/core/global-store/index.ts (1)
  • useGlobalStore (13-22)
🔇 Additional comments (5)
apps/web/src/features/ui/emoji-picker/index.tsx (4)

10-35: LGTM! Well-structured parent-controlled API.

The Props interface refactoring from anchor-based to parent-controlled visibility (show/changeState) is well designed. The ref fallback pattern and optional props provide good flexibility for consumers.


40-69: LGTM! Solid positioning logic with viewport clamping.

The position calculation correctly:

  • Aligns the picker to the button's right edge
  • Supports top/bottom placement via the position prop
  • Clamps coordinates to viewport bounds to prevent off-screen rendering
  • Recalculates when relevant dependencies change

72-103: LGTM! Outside-click handler correctly addresses previous feedback.

The pointerdown handler properly excludes clicks on both the picker itself and the trigger button (lines 89-93), which resolves the past review comment about toggle behavior. The pattern aligns with the migration away from ClickAwayListener across the codebase.


105-137: LGTM! Clean integration of positioning and selection flow.

The merged style correctly applies fixed positioning with calculated coordinates, and the onEmojiSelect handler properly closes the picker after selection. The use of native emoji set is a good choice to avoid sprite sheet dependencies.

apps/web/src/app/publish/_components/publish-gif-picker-dialog.tsx (1)

23-25: Remove the redundant refetch concern—this pattern is correct.

The default query configuration in this codebase sets refetchOnMount: false, so React Query will not auto-fetch on mount. The useEffect is the sole trigger for initial data loading and ensures the query refetches when the filter changes. This is intentional and proper design.

The debouncing suggestion remains valid as an optional optimization to prevent rapid successive API calls during typing, but it is not a bug fix.

Likely an incorrect or invalid review comment.


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

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: 6

🧹 Nitpick comments (2)
apps/web/src/features/ui/emoji-picker/index.tsx (2)

99-105: Consider guarding render until position is calculated.

When show becomes true, pickerPosition is initially null, so top and left will be undefined for one render frame. This may cause a brief visual flash before the picker moves to its calculated position.

🔎 Optional improvement
+  // Don't render until position is calculated to avoid flash
+  if (!pickerPosition) {
+    return null;
+  }
+
   const mergedStyle: CSSProperties = {
     position: "fixed",
-    top: pickerPosition?.top,
-    left: pickerPosition?.left,
+    top: pickerPosition.top,
+    left: pickerPosition.left,
     zIndex: 9999,
     ...style
   };

72-97: Add ref to the dependency array for completeness.

The effect uses ref.current but doesn't include ref in the dependency array. While refs are typically stable, including it satisfies the exhaustive-deps lint rule and makes the dependency explicit.

🔎 Proposed fix
-  }, [show, changeState]);
+  }, [show, changeState, ref, buttonRef]);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a27d4c9 and accbb64.

📒 Files selected for processing (14)
  • apps/web/public/sw.js
  • apps/web/src/app/decks/_components/deck-settings/decks-settings.tsx
  • apps/web/src/app/decks/_components/deck-threads-form/deck-threads-form-emoji-picker.tsx
  • apps/web/src/app/publish/_components/publish-editor-toolbar.tsx
  • apps/web/src/app/publish/_components/publish-gif-picker-dialog.tsx
  • apps/web/src/features/chat/components/message-input.tsx
  • apps/web/src/features/entry-management/entry-metadata-manager/entry-metadata-builder.ts
  • apps/web/src/features/polls/components/poll-widget.tsx
  • apps/web/src/features/polls/components/polls-creation.tsx
  • apps/web/src/features/polls/hooks/use-entry-poll-extractor.ts
  • apps/web/src/features/shared/editor-toolbar/index.tsx
  • apps/web/src/features/ui/emoji-picker/index.tsx
  • apps/web/src/features/ui/gif-picker/index.tsx
  • apps/web/src/features/waves/components/wave-form/wave-form-emoji-picker.tsx
🧰 Additional context used
🧬 Code graph analysis (6)
apps/web/src/features/waves/components/wave-form/wave-form-emoji-picker.tsx (2)
apps/web/src/features/ui/button/index.tsx (1)
  • Button (88-88)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
  • EmojiPicker (24-132)
apps/web/src/app/publish/_components/publish-editor-toolbar.tsx (2)
apps/web/src/features/ui/button/index.tsx (1)
  • Button (88-88)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
  • EmojiPicker (24-132)
apps/web/src/features/shared/editor-toolbar/index.tsx (2)
apps/web/src/features/ui/tooltip.tsx (1)
  • Tooltip (17-19)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
  • EmojiPicker (24-132)
apps/web/src/app/decks/_components/deck-threads-form/deck-threads-form-emoji-picker.tsx (2)
apps/web/src/features/ui/button/index.tsx (1)
  • Button (88-88)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
  • EmojiPicker (24-132)
apps/web/src/app/decks/_components/deck-settings/decks-settings.tsx (1)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
  • EmojiPicker (24-132)
apps/web/src/features/ui/emoji-picker/index.tsx (1)
apps/web/src/core/global-store/index.ts (1)
  • useGlobalStore (13-22)
🔇 Additional comments (14)
apps/web/src/features/entry-management/entry-metadata-manager/entry-metadata-builder.ts (1)

175-175: LGTM! Behavioral change ensures minimum of 1 choice.

The change from nullish coalescing (??) to logical OR (||) now treats 0 as a falsy value, defaulting it to 1. This prevents polls with 0 maximum choices, which aligns with poll semantics and is consistent with validation changes in other files.

apps/web/src/features/polls/components/polls-creation.tsx (2)

194-206: LGTM! Validation logic enforces minimum of 1 choice.

The updated validation logic correctly enforces a minimum of 1 for maxChoicesVoted, aligning with poll semantics and preventing invalid poll configurations. The min attribute and boundary checks are consistent.


304-304: LGTM! Consistent with other poll max choices changes.

The change from ?? to || ensures that falsy values (including 0) default to 1, consistent with the validation logic and changes in entry-metadata-builder.ts.

apps/web/src/features/chat/components/message-input.tsx (3)

1-1: LGTM: State management setup.

The addition of useState and the showEmojiPicker state properly support the refactored emoji picker pattern.

Also applies to: 143-143


398-402: LGTM: Click handler properly toggles picker.

The button click handler correctly prevents default behavior and propagation, then toggles the emoji picker visibility.


531-541: LGTM: EmojiPicker integration follows the new pattern.

The conditional rendering and prop passing (show, changeState, onSelect, buttonRef, position) align with the state-driven EmojiPicker API. The position="top" placement is appropriate for the bottom-anchored input.

apps/web/src/app/decks/_components/deck-threads-form/deck-threads-form-emoji-picker.tsx (2)

1-1: LGTM: State and ref setup.

The state management and ref declaration properly support the controlled emoji picker pattern.

Also applies to: 11-12


16-29: LGTM: Button and EmojiPicker refactor.

The refactored implementation correctly:

  • Forwards the ref to the Button
  • Toggles visibility on click
  • Conditionally renders EmojiPicker with the required props (show, changeState, onSelect, buttonRef)
apps/web/src/app/decks/_components/deck-settings/decks-settings.tsx (1)

128-137: LGTM: EmojiPicker integration updated correctly.

The conditional rendering and prop passing follow the state-driven pattern. The onSelect handler correctly delegates visibility control to changeState rather than manually toggling showEmoji.

apps/web/src/app/publish/_components/publish-editor-toolbar.tsx (2)

124-124: LGTM: State and ref setup for emoji picker.

The emojiButtonRef and showEmojiPicker state declarations properly support the controlled emoji picker pattern.

Also applies to: 140-140


339-357: LGTM: Emoji picker refactored to state-driven pattern.

The implementation correctly:

  • Wraps the button in a positioning container
  • Attaches the ref to the button
  • Toggles visibility on click
  • Conditionally renders EmojiPicker with proper props (show, changeState, onSelect, buttonRef)
  • Inserts selected emoji into the editor
apps/web/src/features/polls/components/poll-widget.tsx (1)

145-145: Remove this comment. The concern about || treating 0 as falsy does not apply here because the poll system explicitly validates that max_choices_voted must be greater than 0 (see use-entry-poll-extractor.ts), and the UI input enforces min={1}. Zero is not a valid value in this system, making || the appropriate operator. There is no evidence of a recent change from ?? to ||, and the current implementation is correct.

Likely an incorrect or invalid review comment.

apps/web/src/features/shared/editor-toolbar/index.tsx (1)

86-94: LGTM on the state-driven emoji picker refactor.

The transition from anchor-based to state-driven control aligns with the unified pattern being adopted across the codebase.

apps/web/src/features/ui/emoji-picker/index.tsx (1)

24-36: LGTM on the controlled visibility API.

The refactor to a controlled show/changeState pattern is clean and aligns well with React's controlled component conventions. The internal ref fallback pattern on lines 34-35 is a nice touch for flexibility.

Comment thread apps/web/src/app/publish/_components/publish-gif-picker-dialog.tsx
Comment thread apps/web/src/features/polls/hooks/use-entry-poll-extractor.ts Outdated
Comment thread apps/web/src/features/shared/editor-toolbar/index.tsx
Comment thread apps/web/src/features/ui/emoji-picker/index.tsx
Comment thread apps/web/src/features/ui/gif-picker/index.tsx
@feruzm feruzm merged commit e8cf1ad into develop Jan 2, 2026
1 check passed
@feruzm feruzm deleted the fixes branch January 2, 2026 22:05
@coderabbitai coderabbitai Bot mentioned this pull request Jan 27, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Mar 10, 2026
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