Skip to content

Conversation

@ammar-agent
Copy link
Collaborator

@ammar-agent ammar-agent commented Oct 24, 2025

Problem

Chat controls under ChatInput (ModelSelector, ThinkingSlider, Context1MCheckbox, mode toggles) don't adapt properly to constrained viewports, causing horizontal overflow or awkward wrapping.

Root Cause

The individual control components have hardcoded left margins (ThinkingSlider has ml-5, Context1MCheckbox has ml-2) that are part of their content size. These margins prevent proper flex wrapping behavior.

Solution

Changed from a wrapping approach to progressive hiding with overflow scrolling as a fallback:

Container

  • overflow-x-auto - allows horizontal scroll as last resort
  • overflow-y-hidden - prevents vertical scroll

Progressive Hiding (using container queries)

Controls are hidden based on viewport width, from least to most critical:

  1. Mode toggles (max-@[700px]:hidden) - hide below 700px (existing)
  2. ThinkingSlider (max-@[600px]:hidden) - hide below 600px (new)
  3. Context1M (max-@[500px]:hidden) - hide below 500px (new)
  4. ModelSelector - always visible (most critical)

Benefits

  • ✅ Works WITH existing component layouts (respects hardcoded margins)
  • ✅ Gracefully removes less critical controls on narrow viewports
  • ✅ Horizontal scroll available if viewport is extremely constrained
  • ✅ No awkward wrapping to multiple lines
  • ✅ Each component has data-component attribute for easy debugging

Changes

  • Modified controls container in ChatInput.tsx
  • Replaced flex-wrap with overflow-x-auto
  • Added container query breakpoints for progressive hiding
  • Removed min-w-0 flex hacks (no longer needed)

Generated with cmux

@ammar-agent
Copy link
Collaborator Author

Updated the fix to decompose the ChatToggles component into individual groups with explicit flex behavior:

  • ModelSelectorGroup: flex shrink - can compress on narrow viewports
  • ThinkingSliderGroup: flex shrink-0 - fixed width
  • Context1MGroup: flex shrink-0 - fixed width
  • Mode toggles: ml-auto - stays on right

Each component now has data-component attributes for easier debugging in DevTools. The parent container uses flex-wrap with proper horizontal and vertical gaps (gap-x-3 gap-y-1).

@ammar-agent
Copy link
Collaborator Author

Added min-w-0 to all flex containers and items. This overrides the default min-width: auto behavior that was preventing items from shrinking below their content size, which was blocking the flex-wrap from triggering.

@ammar-agent
Copy link
Collaborator Author

Changed approach completely - instead of trying to make items wrap (which fights against the hardcoded margins in ThinkingSlider ml-5 and Context1MCheckbox ml-2), I'm now using:

  1. overflow-x-auto - allows horizontal scroll as a last resort
  2. Progressive hiding - remove less critical controls at smaller viewport widths:
    • ThinkingSlider: hidden below 600px container width
    • Context1M: hidden below 500px container width
    • Mode toggles: hidden below 700px (existing behavior)
    • ModelSelector: always visible (most important)

This approach works WITH the existing component layouts instead of fighting against them.

Added flex-wrap to the chat controls row to prevent overflow on narrow
viewports. Controls (ModelSelector, ThinkingSlider, Context1MCheckbox,
and mode toggles) now wrap to multiple lines when space is constrained
instead of overflowing horizontally.

Changes:
- Added flex-wrap and gap-y-1 to controls container
- Controls maintain proper alignment while allowing responsive wrapping
Removed ChatToggles wrapper and decomposed into individual components with
explicit flex behavior:

- ModelSelectorGroup: flex shrink (can compress)
- ThinkingSliderGroup: flex shrink-0 (fixed width)
- Context1MGroup: flex shrink-0 (fixed width)
- Mode toggles: ml-auto (pushes to right)

Each component now has:
- data-component attribute for debugging
- Explicit shrink behavior (shrink vs shrink-0)
- Proper gap-x-3 spacing between items
- gap-y-1 for wrapped rows

This allows proper wrapping and compression on constrained viewports.
Added min-w-0 to all flex container and items to override the default
min-width:auto behavior that prevents flex items from shrinking below
their content size.

Without min-w-0:
- Flex items have min-width: auto (content-based minimum)
- Items can't shrink below their content width
- flex-wrap doesn't trigger because items won't compress

With min-w-0:
- Flex items can shrink below content size
- Wrapping triggers when container width is constrained
- Items properly respond to viewport constraints
Changed approach from flex-wrap to overflow scrolling with progressive
hiding of controls on smaller viewports:

- Parent container: overflow-x-auto (allows horizontal scroll as last resort)
- ModelSelector: always visible, pr-3 spacing
- ThinkingSlider: hidden below 600px (@container width)
- Context1M: hidden below 500px (@container width)
- Mode toggles: hidden below 700px (@container width, existing)

This approach:
- Prevents awkward wrapping with hardcoded component margins (ml-5, ml-2)
- Progressively removes less critical controls on narrow viewports
- Allows horizontal scroll if all else fails
- Respects existing component layouts
Remove hardcoded margins from ThinkingSlider and Context1MCheckbox,
let parent container handle spacing with gap-3. This makes the layout
more responsive and easier to reason about.

- ThinkingSlider: ml-5 → handled by parent gap
- Context1MCheckbox: ml-2 → handled by parent gap
- ChatInput: pr-3 on child → gap-3 on parent
Replace horizontal scrolling with proper flex wrapping:
- Parent: overflow-x-auto → flex-wrap
- Children: Remove shrink-0 (allows natural sizing)
- Mode toggles: Remove ml-auto (prevents overlap when wrapping)

This ensures controls wrap to new lines instead of overlapping content.
- Add justify-between to spread controls across available width
- Remove wrapper div internal gaps (parent gap-3 handles all spacing)
- Remove 'Thinking:' label from slider (tooltip clarifies purpose)

Controls now distribute evenly across the width with consistent gaps.
Use plain flex with gap-3 for natural, consistent spacing.
No layout magic needed.
Push mode toggles to the right edge, making controls spread
across the available space instead of hugging the left.
All controls now have consistent gap-3 spacing with no special rules.
Mode toggles container has ToggleGroup + HelpIndicator, needs
internal gap for spacing between them (like other wrappers).
Controls now spread across full width with even spacing between them.
Replaces fixed gap-3 with dynamic justify-between spacing.
Slider now shows just the level (OFF/LOW/MEDIUM/HIGH).
Tooltip explains it's the thinking level with keybind.
Added aria-label for accessibility.
Changed from 'Thinking:' to 'Thinking level' to match the
updated component aria-label.
@ammar-agent ammar-agent force-pushed the fix-chat-controls-shrinking branch from 85db394 to f75bb50 Compare October 24, 2025 17:20
- Replace justify-between with gap-x-3 gap-y-2 for consistent spacing
- gap-y-2 adds vertical spacing when controls wrap to new lines
- Restore ml-auto on mode toggles to push them to the right
- Model-related controls (selector, thinking, context) group naturally on left
@ammario ammario merged commit 824e131 into main Oct 24, 2025
12 of 13 checks passed
@ammario ammario deleted the fix-chat-controls-shrinking branch October 24, 2025 17:32
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