Skip to content

feat(playground): full-width scroll with floating input - #1490

Merged
smakosh merged 10 commits into
mainfrom
feat/playground-fullwidth-scroll
Jan 23, 2026
Merged

smakosh merged 10 commits into
mainfrom
feat/playground-fullwidth-scroll

Conversation

@rcogal

@rcogal rcogal commented Jan 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Moves the scrollbar from the center of the playground chat to the window edge by removing max-w-4xl from the scroll container and applying it only to inner content
  • Adds a floating input that uses absolute positioning with dynamic padding (ResizeObserver) to prevent message overlap
  • Applies the floating input style (rounded corners, border, shadow) to both single and comparison mode panels
  • Adds cursor-pointer to all interactive elements globally

Test plan

  • Verify single chat mode: scrollbar at window edge, input floats at bottom with rounded style
  • Verify comparison mode (2-3 panels): each panel has its own floating input with rounded style
  • Verify long messages don't overlap the floating input (dynamic padding adjusts)
  • Verify expanding textarea doesn't overlap messages
  • Verify no dark shadow/background artifact near the scrollbar
  • Verify clickable elements show cursor-pointer

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an optional floating input area for the chat interface for a persistent input experience.
  • Refactor

    • Simplified chat grid/layout logic for improved responsiveness and multi-panel handling.
    • Changed conversation container scrolling behavior (vertical auto-scrolling removed).
  • Style

    • Unified pointer/cursor styling for interactive controls for clearer affordances.

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

rcogal and others added 9 commits January 24, 2026 01:01
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>
@coderabbitai

coderabbitai Bot commented Jan 23, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds 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

Cohort / File(s) Summary
Global Styling
apps/playground/src/app/globals.css
Adds CSS rule applying cursor-pointer to interactive controls (buttons, links, selects, inputs) in base layers.
Conversation overflow
apps/playground/src/components/ai-elements/conversation.tsx
Replaces overflow-y-auto with overflow-hidden on the conversation container.
Chat page layout & usages
apps/playground/src/components/playground/chat-page-client.tsx
Simplifies grid layout conditional, makes extra panels full-height (h-full), and passes new floatingInput prop to ChatUI instances.
Chat UI floating input feature
apps/playground/src/components/playground/chat-ui.tsx
Adds optional floatingInput?: boolean prop, introduces inputRef + inputHeight with ResizeObserver, conditional floating vs standard layouts, and adjusts content padding to account for measured input height.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • steebchen
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: enabling full-width scroll layout and adding a floating input feature, which are the core objectives of this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@rcogal

rcogal commented Jan 23, 2026

Copy link
Copy Markdown
Collaborator Author

Example update:

image image

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 when floatingInput changes dynamically.

The effect captures inputRef.current at mount time, but the ref is only assigned when floatingInput is true (line 585). If floatingInput changes from false to true after mount, the observer won't observe the newly rendered input container because the effect doesn't re-run.

Consider adding floatingInput to 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]);

Comment on lines +583 to +598
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
}
>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

@rcogal
rcogal requested review from smakosh and steebchen January 23, 2026 18:15
@smakosh
smakosh added this pull request to the merge queue Jan 23, 2026
Merged via the queue into main with commit a233db7 Jan 23, 2026
8 checks passed
@smakosh
smakosh deleted the feat/playground-fullwidth-scroll branch January 23, 2026 19:41
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