feat(playground): full-width scroll with floating input - #1490
Conversation
Move scrollbar to the window edge in single chat mode by removing the max-w-4xl constraint from the scroll container and using a floating sticky input. Comparison mode retains per-panel scrolling. Fix double scrollbar by changing Conversation overflow to hidden (StickToBottom handles scrolling internally). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use uniform p-4 padding on the comparison grid and ensure extra panels stretch to full height for consistent layout. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Increase pb-24 to pb-36 so messages don't overlap the floating input area. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove floating/absolute input positioning which caused overlap when textarea expanded. Use a simple flex layout with shrink-0 input at the bottom and scrollable messages above. The scrollbar remains at the window edge since the grid container has no max-width constraint. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use ResizeObserver to measure the input area height and set matching bottom padding on messages. This prevents overlap regardless of textarea expansion while keeping the floating input design. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use solid bg-background instead of semi-transparent background with backdrop-blur which was creating a dark shadow over the scrollbar area. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use floatingInput prop to differentiate single mode (absolute positioned input with dynamic padding) from comparison mode (shrink-0 fixed input). Move bg-background from the full-width absolute wrapper to the inner max-w-4xl content div to avoid a dark band over the scrollbar area. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add global CSS rule to apply cursor-pointer to all buttons, links, selects, and role=button elements. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughAdds a floating input layout to ChatUI with dynamic input-height tracking, adjusts chat page grid/layout and panel heights, changes a conversation wrapper overflow behavior, and adds global cursor-pointer rules for interactive controls. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ChatPage
participant ChatUI
participant ResizeObserver
participant API
participant Conversation
User->>ChatPage: open chat page
ChatPage->>ChatUI: render (floatingInput=true/false)
ChatUI->>ResizeObserver: observe inputRef (if floatingInput)
ResizeObserver-->>ChatUI: report inputHeight updates
ChatUI->>ChatUI: apply bottom padding / position input area
User->>ChatUI: submit prompt
ChatUI->>API: send message
API-->>ChatUI: response
ChatUI->>Conversation: append messages
Conversation-->>User: display updated content
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@apps/playground/src/components/playground/chat-ui.tsx`:
- Around line 583-598: The floating-mode layout applies duplicate horizontal and
bottom safe-area padding in the inputArea: when floatingInput is true both the
outer div (ref={inputRef}) and the inner wrapper add "px-4" and
"pb-[max(env(safe-area-inset-bottom),0.75rem)]"; remove those from the inner
wrapper so it only provides layout (e.g., "max-w-4xl mx-auto pt-2
bg-background") when floatingInput is true. Update the inner wrapper conditional
className in the inputArea JSX (the element inside inputArea that currently uses
floatingInput ? "max-w-4xl mx-auto px-4 pb-[max(...)] pt-2 bg-background" :
undefined) to drop px-4 and pb[...] while keeping the rest.
🧹 Nitpick comments (1)
apps/playground/src/components/playground/chat-ui.tsx (1)
420-427: ResizeObserver may miss observing whenfloatingInputchanges dynamically.The effect captures
inputRef.currentat mount time, but the ref is only assigned whenfloatingInputis true (line 585). IffloatingInputchanges fromfalsetotrueafter mount, the observer won't observe the newly rendered input container because the effect doesn't re-run.Consider adding
floatingInputto the dependency array to ensure the observer is set up correctly when the mode changes.♻️ Suggested fix
useEffect(() => { updateInputHeight(); const observer = new ResizeObserver(updateInputHeight); if (inputRef.current) { observer.observe(inputRef.current); } return () => observer.disconnect(); - }, [updateInputHeight]); + }, [updateInputHeight, floatingInput]);
| const inputArea = ( | ||
| <div | ||
| ref={floatingInput ? inputRef : undefined} | ||
| className={ | ||
| floatingInput | ||
| ? "absolute bottom-0 left-0 right-0 z-10 px-4 pb-[max(env(safe-area-inset-bottom),0.75rem)]" | ||
| : "shrink-0 px-4 pb-[max(env(safe-area-inset-bottom),1rem)] pt-2 bg-background border-t" | ||
| } | ||
| > | ||
| <div | ||
| className={ | ||
| floatingInput | ||
| ? "max-w-4xl mx-auto px-4 pb-[max(env(safe-area-inset-bottom),0.75rem)] pt-2 bg-background" | ||
| : undefined | ||
| } | ||
| > |
There was a problem hiding this comment.
Duplicate padding in floating mode causes excessive spacing.
In floating mode, both the outer container (line 588) and inner wrapper (line 595) apply px-4 and pb-[max(env(safe-area-inset-bottom),0.75rem)]. This results in double horizontal padding (32px total) and double bottom safe-area padding.
🐛 Suggested fix: Remove duplicate padding from inner wrapper
<div
className={
floatingInput
- ? "max-w-4xl mx-auto px-4 pb-[max(env(safe-area-inset-bottom),0.75rem)] pt-2 bg-background"
+ ? "max-w-4xl mx-auto pt-2 bg-background"
: undefined
}
>🤖 Prompt for AI Agents
In `@apps/playground/src/components/playground/chat-ui.tsx` around lines 583 -
598, The floating-mode layout applies duplicate horizontal and bottom safe-area
padding in the inputArea: when floatingInput is true both the outer div
(ref={inputRef}) and the inner wrapper add "px-4" and
"pb-[max(env(safe-area-inset-bottom),0.75rem)]"; remove those from the inner
wrapper so it only provides layout (e.g., "max-w-4xl mx-auto pt-2
bg-background") when floatingInput is true. Update the inner wrapper conditional
className in the inputArea JSX (the element inside inputArea that currently uses
floatingInput ? "max-w-4xl mx-auto px-4 pb-[max(...)] pt-2 bg-background" :
undefined) to drop px-4 and pb[...] while keeping the rest.


Summary
max-w-4xlfrom the scroll container and applying it only to inner contentcursor-pointerto all interactive elements globallyTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Refactor
Style
✏️ Tip: You can customize this high-level summary in your review settings.