Skip to content

feat: Implement expandable chat input with double-click detection and gradient tooltip#62

Merged
shantur merged 10 commits intoNeuralNomadsAI:devfrom
bizzkoot:feat/expand-chat-input
Jan 14, 2026
Merged

feat: Implement expandable chat input with double-click detection and gradient tooltip#62
shantur merged 10 commits intoNeuralNomadsAI:devfrom
bizzkoot:feat/expand-chat-input

Conversation

@bizzkoot
Copy link
Contributor

feat: Implement expandable chat input with double-click detection and gradient tooltip

Summary

This PR adds an expand/minimize button to the chat input that allows users to toggle between 3 height states: normal (default/original), 50%, and 80% of available space. The feature includes smart double-click detection for quick navigation between states and a polished tooltip with gradient background for better visibility.

Changes

1. Expand Button Component (packages/ui/src/components/expand-button.tsx)

  • Created new component with Maximize2/Minimize2 icons
  • Implemented smart double-click detection (300ms threshold)
    • Single-click: normal → 50%, expanded → normal
    • Double-click: normal → 80%, fifty → eighty, eighty → fifty
  • Comprehensive tooltip text for all states
  • Reactive state management with SolidJS signals

2. Prompt Input Enhancements (packages/ui/src/components/prompt-input.tsx)

  • Added expandState signal with 3 states: "normal" | "fifty" | "eighty"
  • Implemented calculateExpandedHeight() function:
    • Calculates available input space based on .session-view height
    • Reserves 200px minimum space for message section
    • Example: 768px total - 200px = 568px available for input
  • Created expandedHeight memo for reactive height updates
  • Added handleExpandToggle() function with textarea focus preservation
  • Modified .prompt-input-field-container to use reactive height
  • Updated textarea overflow handling (auto when expanded, visible when normal)

3. Styling (packages/ui/src/styles/messaging/prompt-input.css)

  • Added .prompt-expand-top positioning (top: 0.3rem, right: 3.5rem)
  • Created .prompt-expand-button styles with hover/active states
  • Custom gradient tooltip with:
    • Dark gradient background: linear-gradient(135deg, rgba(30, 41, 59, 0.95) 0%, rgba(15, 23, 42, 0.98) 100%)
    • Backdrop blur filter for better readability over content
    • Enhanced box-shadow with border highlight
    • Smooth fade-in animation (0.2s)
  • Updated .prompt-input-actions from justify-between to justify-start
  • Added margin-top: auto to .send-button to anchor at bottom
  • Added height transition to .prompt-input-field-container

Technical Details

Height Calculation Logic

const availableForInput = sessionViewHeight - MIN_MESSAGE_SPACE(200px)
// Example: 768px - 200px = 568px available
// 50% state: 284px height
// 80% state: 454px height

Double-Click Detection Algorithm

  1. First click: Record timestamp, start 300ms timer
  2. Second click within 300ms: Cancel timer, execute double-click action immediately
  3. Timer expires (no second click): Execute single-click action

State Transitions

Normal:
  Single-click → 50%
  Double-click → 80%

50% (fifty):
  Single-click → Normal
  Double-click → 80%

80% (eighty):
  Single-click → Normal
  Double-click → 50%

Tooltip Text by State

  • Normal: "Click to expand (50%) • Double-click to expand further (80%)"
  • 50%: "Double-click to expand to 80% • Click to minimize"
  • 80%: "Click to minimize • Double-click to reduce to 50%"

Behavior Notes

  1. Send button anchoring: The Send button stays at the bottom of the action bar using margin-top: auto. Stop and Arrow buttons move with height changes (accepted behavior).

  2. Scrollbar support: When expanded, the textarea gets overflow-y: auto to handle content overflow gracefully.

  3. Focus preservation: Expanding/collapsing keeps focus on the textarea for seamless typing.

  4. Smooth transitions: All height changes animate over 250ms; tooltip fade-in is 200ms.

  5. Tooltip positioning: The tooltip uses CSS ::after pseudo-element with data-tooltip attribute for instant hover feedback (no 1-2s delay like native title).

Testing Instructions

  1. Basic expansion:

    • Click expand button once → input expands to 50%
    • Click again → returns to normal height
    • Click again → back to 50%
  2. Double-click navigation:

    • Double-click from normal → jumps to 80%
    • Double-click from 50% → jumps to 80%
    • Double-click from 80% → reduces to 50%
  3. Tooltip testing:

    • Hover over expand button at each state
    • Verify tooltip text is accurate and readable
    • Check gradient background ensures visibility over content
  4. Content testing:

    • Type long text to verify scrollbar appears when expanded
    • Verify all existing buttons (Stop, Send, Arrow-up) remain functional
    • Test with attachments present
  5. Keyboard shortcuts:

    • Press Cmd+Enter to send while expanded
    • Test Esc to exit shell mode (if applicable)
    • Verify ↑↓ for history navigation still works

Browser Compatibility

This implementation uses standard CSS features:

  • backdrop-filter for blur effect (supported in Chrome 76+, Firefox 103+, Safari 9+)
  • CSS custom properties for theming
  • CSS transitions for animations
  • No browser-specific prefixes required for modern browsers

Screenshots

Screen Recording 2026-01-11 at 10 16 20 PM

  • Normal state with Maximize2 icon
  • 50% expanded state with Minimize2 icon
  • 80% expanded state with scrollbar
  • Tooltip hover effect

Checklist

  • Expand button positioned correctly
  • 3-state height management working
  • Double-click detection functional
  • Tooltip with gradient background visible
  • Send button anchored at bottom
  • Smooth transitions applied
  • All debug logs removed
  • No TypeScript errors
  • Existing functionality preserved

Related Issues

  1. So far, the 'Arrow UP' and 'STOP' button will move together with the top chat height

Breaking Changes

None. This is a new feature that doesn't modify existing behavior.

… gradient tooltip

- Add expand button with Maximize2/Minimize2 icons
- Implement 3-state height management (normal/50%/80%)
- Smart double-click detection with 300ms delay
- Height calculation based on session-view - 200px message space
- Custom CSS tooltip with dark gradient background and backdrop blur
- Send button anchored at bottom via margin-top: auto
- Smooth CSS transitions throughout
- Double-click at 80% now reduces to 50% (not normal)
- Removed all debug console.log statements
@bizzkoot bizzkoot marked this pull request as ready for review January 11, 2026 14:21
@bizzkoot bizzkoot marked this pull request as draft January 11, 2026 14:31
@bizzkoot bizzkoot force-pushed the feat/expand-chat-input branch from d68d0cf to 0d8a844 Compare January 11, 2026 14:33
@bizzkoot bizzkoot marked this pull request as ready for review January 11, 2026 14:34
@shantur
Copy link
Collaborator

shantur commented Jan 12, 2026

Hi @bizzkoot ,

Thanks for the PR.
How does it behave on phones?
I think it would be enough to have 2 states instead of 3.

As of now the calculation is around 4 lines, maybe one state could be 15 lines.

Let me know what you think

Thanks

…izations

- Add platform detection (Electron vs Web) for expand behavior
  - Electron: 3-state (normal → 50% → 80%) with double-click
  - Web/Mobile: 2-state (normal → expanded) with instant single tap
- Implement fixed 15-line height for web/mobile (360px, capped)
- Add orientation-aware height calculation (landscape vs portrait)
- Remove tooltip on web/mobile, keep for Electron desktop
- Add responsive placeholder text to prevent overlap on mobile
  - Desktop: "Type your message, @file, @agent, or paste images and text..."
  - Mobile (≤640px): "Type message, @file, @agent..."
- Delete dev-docs/expand-chat-input.md per upstream feedback

Addresses PR feedback to simplify from 3-state to 2-state for web/mobile
while maintaining rich desktop experience in Electron app.
@bizzkoot
Copy link
Contributor Author

Hi @shantur ,

I did a short test before doing the PR, seems workable. But I do agree with your idea. So I implemented it (but limited to web/mobile usage).

Screen_Recording_20260112_203154_Chrome

I did saw the text is behind the maximize / minimize button, so I just make it shorter directly for web/mobile.

Screenshot_20260112_205348_Chrome

I hope this meets your criteria.

Thank you

@shantur
Copy link
Collaborator

shantur commented Jan 12, 2026

Thanks for updating.

  1. Sorry, I may not be clear, we don't need to have 3 states for any screen sizes.
    We need to keep it simple and only 1 approach.
  2. I see that expand button is overlapping the text. Maybe we can move the expand button on the side ( in line with previous / next button ).

The less logic in the app the better.

… layout

- Remove 3-state logic (normal/50%/80%) - now only normal/expanded
- Remove double-click detection and tooltips for simplicity
- Remove platform-specific behavior (same UX for Electron and web)
- Optimize button layout: reduce from 36px to 28px to fit 3 buttons
- Position expand button above history buttons in vertical stack
- Keep 15-line expanded height (360px, capped to available space)

Per upstream dev feedback to keep it simple with one approach
- Remove isMobileWidth signal and updateMobileWidth resize listener
- Use same placeholder text for all devices/platforms
- "Type your message, @file, @agent, or paste images and text..."

Simplifies implementation per dev feedback - one approach for all
@bizzkoot
Copy link
Contributor Author

Done

Screen.Recording.2026-01-13.at.6.49.52.AM.mov
Screen_Recording_20260113_065103_Chrome.mp4

@shantur shantur merged commit 3ab14e8 into NeuralNomadsAI:dev Jan 14, 2026
This was referenced Jan 14, 2026
@bizzkoot bizzkoot deleted the feat/expand-chat-input branch January 16, 2026 11:56
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

Comments