Refactor video detail component architecture
Instructions: "Handoff from parent thread"
The Oracle and I have reviewed the code. The architecture is sound (Fixed App Shell), but the VideoDetail component has too many responsibilities (layout, logic, content rendering), and the naming for the right sidebar (VideoContentTabs) is implementation-specific rather than semantic.
Here is the refactoring plan to make the code "sing":
1. Semantic Renaming
VideoContentTabs → VideoCompanionSidebar
- Why: It's not just "tabs"—it's the dedicated companion panel for the video (Chat + Chapters). This matches the naming pattern of
PlaylistSidebar. - Action: Rename the file and component. Clean up unused "legacy" props (
activeTab,onTabChange, etc.) that clutter the interface.
2. Layout Extraction
Create FixedSidebarLayout
- Why:
VideoDetailis currently manually calculating paddings and positioning sidebars. This "glue" code obscures the actual business logic. - Action: Extract a reusable shell component that accepts
leftSidebar,rightSidebar, andchildren.<FixedSidebarLayout leftSidebar={<PlaylistSidebar ... />} rightSidebar={<VideoCompanionSidebar ... />} > {/* Content */} </FixedSidebarLayout>
3. Logic Extraction (Hooks)
Create usePlaylistNavigation & useScrollOutOfView
- Why:
- Playlist index math (
nextVideo,previousVideo, etc.) takes up ~20 lines of noise in the main component. - The scroll listener logic (
isOutOfView) is verbose and slightly buggy (it never sets true).
- Playlist index math (
- Action: Move this logic into clean, testable hooks.
4. Component Decomposition
Create VideoMainContent
- Why: The content below the player (metadata, description tab, transcript tab, CTA) creates a massive render block.
- Action: Extract this into a dumb UI component.
VideoDetaileffectively becomes a "Controller" that just wires up data to the Layout, Player, and MainContent.
Execution Order
- Rename the right sidebar and clean it up.
- Create the hooks.
- Create the
FixedSidebarLayout. - Extract
VideoMainContent. - Rewire
VideoDetailto be a clean orchestrator.
Shall I proceed with this plan?
Refactoring complete! 🚀
I have reorganized the VideoDetail architecture to follow the plan we discussed. The code is now cleaner, more modular, and "sings" (Dave Thomas would approve).
🏗️ Key Changes
Renamed Right Sidebar
VideoContentTabs→VideoCompanionSidebar- Why: Semantic naming that matches
PlaylistSidebar. Removed unused legacy props to keep the interface clean.
Extracted Layout Shell
- Created
FixedSidebarLayout(components/layout/fixed-sidebar-layout.tsx). - Why: Removed ~40 lines of "layout glue" (padding calculations, positioning) from the main component.
- Created
Extracted Logic into Hooks
usePlaylistNavigation: Encapsulates next/prev/index logic.useScrollOutOfView: Encapsulates the scroll listener logic.
Decomposed Content
- Created
VideoMainContent(components/video-main-content.tsx). - Why: Moved all the metadata, description, CTA, and transcript UI out of the main file.
VideoDetailis now just a "Controller" that wires everything together.
- Created
Types
- Moved
ExtendedVideoandCTAinterfaces totypes/video-detail.ts.
- Moved
🎸 The Result
Your VideoDetail component is now a highly readable orchestrator (~120 lines, down from ~300+), and the build passes successfully.
return (
<AIAssistantProvider onTimeClick={handleTimeSelect}>
<FixedSidebarLayout
leftSidebar={<PlaylistSidebar ... />}
rightSidebar={<VideoCompanionSidebar ... />}
>
{/* Video Player */}
<Player ... />
{/* Main Content */}
<VideoMainContent ... />
</FixedSidebarLayout>
</AIAssistantProvider>
);
All set! I've committed the refactoring changes.
Commit: Refactor VideoDetail: rename right sidebar, extract layout & content components
The architecture is now significantly cleaner with:
VideoCompanionSidebar(renamed from tabs)FixedSidebarLayouthandling the shellVideoMainContenthandling the heavy UI lifting- Specialized hooks for logic
Ready for the mobile version whenever you are! 📱
The chat input text field issue is fixed! 🛠️
The Problem:
When the chat sidebar opened, the width animation (0px -> 384px) caused the text input's placeholder/content to wrap excessively during the initial frames. The textarea height calculation ran immediately, measuring a huge height (4-5 lines) because of the narrow width. Once the sidebar finished expanding, the height remained "stuck" at the large value until you typed something (triggering a recalculation).
The Fix:
I added a ResizeObserver to the input container. Now, as the sidebar animates open and the container width changes, the textarea height is continuously recalculated, ensuring it settles correctly at the 2-line default (64px) once the animation completes.
The input field will now behave exactly as expected:
- Starts at 2 lines (64px).
- Grows up to ~5 lines (120px) as you type.
- Scrolls internally if content exceeds max height.
- No more initial "jump" or incorrect height on open.
Ready for the next task! 🚀
Committed! 🔒
Commit: Fix chat textarea height issue on sidebar open
Ready for the next move. What's on your mind?
