Skip to content

refactor(ai): improve workspace navigation layout#75

Merged
imuniqueshiv merged 1 commit into
mainfrom
refactor/workspace-navigation
Jul 8, 2026
Merged

refactor(ai): improve workspace navigation layout#75
imuniqueshiv merged 1 commit into
mainfrom
refactor/workspace-navigation

Conversation

@imuniqueshiv

@imuniqueshiv imuniqueshiv commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Pull Request

Summary

Refactor the Hyper AI Workspace layout to improve navigation structure and prepare the workspace for a cleaner, more maintainable UI architecture.


Related Issue

N/A


Type of Change

  • Feature
  • Bug Fix
  • Documentation
  • Refactor
  • Performance Improvement
  • CI / Build
  • Other

What Changed?

  • Refactored the Hyper AI Workspace layout and navigation structure.
  • Improved component organization to support future workspace UI enhancements.
  • Cleaned up workspace-related components while preserving existing AI functionality.
  • Updated breadcrumb, navbar, and workspace layout implementation.
  • No changes to AI generation, backend APIs, caching, or business logic.

Screenshots (UI Changes Only)

Updated Hyper AI Workspace navigation and layout.
NA


Testing

Verified the changes locally by running:

  • npm run format:check
  • npm run lint
  • npm run typecheck
  • npm run build

The application was also tested locally to ensure the workspace renders correctly without affecting existing functionality.


Checklist

  • My branch is up to date with the latest main.
  • My code follows the project's coding standards.
  • I have formatted the modified files (npx prettier --write <file>).
  • npm run format:check passes.
  • npm run lint passes.
  • npm run typecheck passes.
  • npm run build passes.
  • I have updated documentation if required.
  • I have tested my changes locally.
  • This Pull Request focuses on a single feature or fix.

Additional Notes

This PR focuses solely on restructuring the Hyper AI Workspace UI. It does not modify AI generation, API routes, caching, markdown rendering, or any backend functionality.

Summary by CodeRabbit

  • New Features

    • Added a streamlined AI workspace experience with a simpler chat-focused layout, suggested follow-ups, and breadcrumb navigation on relevant pages.
    • Introduced a compact header for workspace-focused pages to reduce distractions.
  • Bug Fixes

    • Improved page layout sizing and spacing so content fills the available space more reliably.
    • Updated message bubble sizing for better readability on smaller screens.

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyper-learning-tech Ready Ready Preview, Comment Jul 8, 2026 11:19am

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a focused, distraction-free workspace layout for the RGPV AI chat route. The AI subject page is simplified to render only the chat loader, workspace-chat component state and UI are reworked (sidebar, collapsible follow-ups, breadcrumbs), and Breadcrumbs/Navbar/layout components gain route-detection logic to render minimal headers on that route.

Changes

Workspace focus AI chat redesign

Layer / File(s) Summary
Global layout adjustments
app/layout.tsx, app/rgpv/layout.tsx
Adds min-h-0 to the root main container and restructures RGPV layout into nested flex wrappers around Breadcrumbs and children.
AI subject page simplification
app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx
Removes the hero/marketing layout and follow-up ideas panel, shortens welcome message text, and renders only WorkspaceChatLoader with new contextLabel/prompt props.
Workspace chat state and contract updates
components/ai/workspace-chat.tsx
Adds contextLabel prop, updates imports, removes showContinueLearning state, adjusts cached-explanation state, and adds sidebar/suggestions UI flags.
Workspace chat behavior and render rework
components/ai/workspace-chat.tsx
Removes scroll-to-bottom and continue-learning wiring, updates loadExplanation/sendMessage, and rewrites JSX with breadcrumbs, responsive sidebar/overlay, and collapsible follow-ups.
Message bubble styling
components/ai/workspace-message.tsx
Adjusts message bubble max-width and padding classNames for responsiveness.
Route-conditional breadcrumbs and navbar
components/breadcrumbs.tsx, components/navbar.tsx
Adds workspace-focus route detection to suppress/adjust breadcrumbs and render a minimal sticky navbar header on the AI chat route.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: RamuuXfree

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the refactor of the workspace navigation/layout experience.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/workspace-navigation

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
components/ai/workspace-chat.tsx (2)

45-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

explanationCached prop is declared but never consumed.

explanationCached remains in WorkspaceChatProps (line 47) but is no longer destructured in the component (lines 127–141). The AI page still computes and passes it (explanationCached={explanationCached} at line 84 of ai/page.tsx), making the variable assignment, prop, and interface field all dead code.

♻️ Proposed cleanup

Remove explanationCached from the interface:

 export interface WorkspaceChatProps {
   subjectCode: string;
   branch?: string;
   semester?: string;
   topicId?: string;
   topicTitle?: string;
   moduleTitle?: string;
   contextLabel?: string;
   cachedExplanation?: string;
-  explanationCached?: boolean;
   initialPrompts?: Array<{
     prompt: string;
     topicId?: string;
     action?: string;
   }>;

And remove the dead variable + prop in app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx:

 let cachedExplanation: string | undefined;
-let explanationCached: boolean | undefined;

 if (isTopicMode && topicId) {
   try {
     const result = await generateTopicAnswer({
       branch,
       semester,
       topicId,
       subjectCode: subject.toUpperCase(),
       action: "EXPLAIN",
     });
     cachedExplanation = result.answer;
-    explanationCached = result.cached;
   } catch (error) {
             cachedExplanation={cachedExplanation}
-            explanationCached={explanationCached}
             initialPrompts={isTopicMode ? followupPrompts : generalPrompts}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/ai/workspace-chat.tsx` around lines 45 - 47, `explanationCached`
is dead state in the chat flow: it is still declared in `WorkspaceChatProps` and
passed from the AI page, but `WorkspaceChat` no longer reads it. Remove the
unused `explanationCached` field from the `WorkspaceChatProps` interface and
delete the corresponding variable/prop wiring in `ai/page.tsx`, keeping only the
values that are actually consumed by `WorkspaceChat`.

778-835: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

SidebarDetails defined inside WorkspaceChat causes unnecessary remounts.

SidebarDetails is declared as a nested function component and rendered as <SidebarDetails /> (lines 509, 522). On every WorkspaceChat render — including every keystroke — React sees a new component type and unmounts/remounts the entire subtree. This breaks the progress bar's motion.div width animation (it jumps instead of animating) and can cause badge flicker.

♻️ Proposed fix: extract SidebarDetails outside WorkspaceChat

Move SidebarDetails above WorkspaceChat and pass the needed values as props:

function SidebarDetails({
  sessionSaved,
  isTopicContextReady,
  topicTitle,
  moduleTitle,
  contextLabel,
  followupStatusLabel,
  progressPercent,
  lastStudied,
}: {
  sessionSaved: boolean;
  isTopicContextReady: boolean;
  topicTitle?: string;
  moduleTitle?: string;
  contextLabel?: string;
  followupStatusLabel: string;
  progressPercent: number;
  lastStudied: { prefix: string; detail?: string } | null;
}) {
  return (
    <div className="space-y-4">
      {/* ... existing JSX unchanged ... */}
    </div>
  );
}

Then update the two call sites:

-              <SidebarDetails />
+              <SidebarDetails
+                sessionSaved={sessionSaved}
+                isTopicContextReady={isTopicContextReady}
+                topicTitle={topicTitle}
+                moduleTitle={moduleTitle}
+                contextLabel={contextLabel}
+                followupStatusLabel={followupStatusLabel}
+                progressPercent={progressPercent}
+                lastStudied={lastStudied}
+              />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/ai/workspace-chat.tsx` around lines 778 - 835, `SidebarDetails` is
defined as an inner component inside `WorkspaceChat`, which makes React treat it
as a new component type on each render and remount the subtree. Extract
`SidebarDetails` to module scope and pass the values it needs (`sessionSaved`,
`isTopicContextReady`, `topicTitle`, `moduleTitle`, `contextLabel`,
`followupStatusLabel`, `progressPercent`, `lastStudied`) as props, then update
the existing `<SidebarDetails />` call sites in `WorkspaceChat` to use the new
prop-based component so the progress animation and badges stay mounted.
components/breadcrumbs.tsx (1)

22-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unreachable isWorkspaceFocusRoute ternaries after early return.

After if (isWorkspaceFocusRoute) return null; (lines 14–16), isWorkspaceFocusRoute is always false in the remaining JSX. The ternaries on lines 24, 28, 31, 40, 46, and 75 will always evaluate to the non-workspace branch, making the workspace-focus styling dead code that could mislead future developers.

♻️ Proposed simplification
     <div
-      className={`mx-auto w-full ${isWorkspaceFocusRoute ? "max-w-[1500px] px-4 sm:px-4 lg:px-6" : "max-w-7xl px-6 lg:px-8"}`}
+      className="mx-auto w-full max-w-7xl px-6 lg:px-8"
     >
       <nav
         aria-label="breadcrumb"
-        className={isWorkspaceFocusRoute ? "py-2" : "py-4"}
+        className="py-4"
       >
         <ol
-          className={`flex flex-wrap items-center gap-1.5 text-muted-foreground ${isWorkspaceFocusRoute ? "text-xs" : "text-sm"}`}
+          className="flex flex-wrap items-center gap-1.5 text-muted-foreground text-sm"
         >
           <li>
             <Link
               href="/"
               className="flex items-center transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded"
               aria-label="Home"
             >
-              <Home
-                className={isWorkspaceFocusRoute ? "h-3.5 w-3.5" : "h-4 w-4"}
-              />
+              <Home className="h-4 w-4" />
             </Link>
           </li>
           {pathNames.length > 0 && (
-            <ChevronRight
-              className={isWorkspaceFocusRoute ? "h-3.5 w-3.5" : "h-4 w-4"}
-            />
+            <ChevronRight className="h-4 w-4" />
           )}

And similarly for the per-segment ChevronRight at line 73–77:

-                    <ChevronRight
-                      className={
-                        isWorkspaceFocusRoute ? "h-3.5 w-3.5" : "h-4 w-4"
-                      }
-                    />
+                    <ChevronRight className="h-4 w-4" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/breadcrumbs.tsx` around lines 22 - 86, The `Breadcrumbs` component
has dead `isWorkspaceFocusRoute` ternaries after the early return, so the
remaining JSX in `Breadcrumbs` only ever uses the non-workspace branch. Simplify
the conditional styling in `Breadcrumbs` by removing those unreachable
workspace-focus checks and keeping only the active branch for the rendered
breadcrumb markup, including the wrapper, `nav`, `ol`, `Home`, and
`ChevronRight` elements.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/ai/workspace-chat.tsx`:
- Around line 593-667: The chat view in workspace-chat.tsx is missing the
auto-scroll behavior because the removed messagesEndRef/scrollToBottom logic was
not replaced, so new conversation updates can stay out of view. Restore
scrolling by adding a ref and effect in workspace-chat.tsx that tracks the
latest message/loading state and scrolls the message list to the bottom when
conversationMessages, explanationMessage, or loading changes. Attach that ref to
the overflow-y-auto container that wraps the message list so the latest
WorkspaceMessage entries are always visible.

---

Nitpick comments:
In `@components/ai/workspace-chat.tsx`:
- Around line 45-47: `explanationCached` is dead state in the chat flow: it is
still declared in `WorkspaceChatProps` and passed from the AI page, but
`WorkspaceChat` no longer reads it. Remove the unused `explanationCached` field
from the `WorkspaceChatProps` interface and delete the corresponding
variable/prop wiring in `ai/page.tsx`, keeping only the values that are actually
consumed by `WorkspaceChat`.
- Around line 778-835: `SidebarDetails` is defined as an inner component inside
`WorkspaceChat`, which makes React treat it as a new component type on each
render and remount the subtree. Extract `SidebarDetails` to module scope and
pass the values it needs (`sessionSaved`, `isTopicContextReady`, `topicTitle`,
`moduleTitle`, `contextLabel`, `followupStatusLabel`, `progressPercent`,
`lastStudied`) as props, then update the existing `<SidebarDetails />` call
sites in `WorkspaceChat` to use the new prop-based component so the progress
animation and badges stay mounted.

In `@components/breadcrumbs.tsx`:
- Around line 22-86: The `Breadcrumbs` component has dead
`isWorkspaceFocusRoute` ternaries after the early return, so the remaining JSX
in `Breadcrumbs` only ever uses the non-workspace branch. Simplify the
conditional styling in `Breadcrumbs` by removing those unreachable
workspace-focus checks and keeping only the active branch for the rendered
breadcrumb markup, including the wrapper, `nav`, `ol`, `Home`, and
`ChevronRight` elements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d5bbc28a-7439-4668-a4bb-7f09c062340a

📥 Commits

Reviewing files that changed from the base of the PR and between 8c68636 and 984f7f9.

📒 Files selected for processing (7)
  • app/layout.tsx
  • app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx
  • app/rgpv/layout.tsx
  • components/ai/workspace-chat.tsx
  • components/ai/workspace-message.tsx
  • components/breadcrumbs.tsx
  • components/navbar.tsx

Comment on lines +593 to +667
<div className="min-h-0 flex-1 overflow-y-auto px-2.5 py-2 sm:px-4">
{!isTopicContextReady && messages.length === 0 ? (
<div className="flex min-h-full flex-col items-center justify-center py-8 text-center">
<div className="mb-4 rounded-full bg-blue-500/10 p-4">
<Sparkles className="h-8 w-8 text-blue-600 dark:text-blue-400" />
</div>
)}
<h3 className="text-lg font-semibold text-foreground">
Welcome to Hyper AI Workspace
</h3>
<p className="mt-2 max-w-md text-sm text-muted-foreground">
{welcomeMessage}
</p>
</div>
) : (
<div className="space-y-3 pb-2">
{explanationLoading && !explanationMessage && (
<div className="flex items-center justify-center py-8">
<Loader2 className="h-6 w-6 animate-spin text-blue-600 dark:text-blue-400" />
</div>
)}

<AnimatePresence initial={false}>
{messages.map((message, index) => (
<motion.div
key={message.id}
initial={false}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.3,
delay: index === messages.length - 1 ? 0 : 0.05,
}}
>
<WorkspaceMessage
answer={message.content}
role={message.role}
timestamp={message.timestamp}
/>
</motion.div>
))}
{loading && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="flex items-start gap-3"
>
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-blue-500/10">
<Sparkles className="h-4 w-4 text-blue-600 dark:text-blue-400" />
</div>
<div className="rounded-2xl rounded-tl-md border border-border bg-muted/30 px-4 py-3">
<Loader2 className="h-5 w-5 animate-spin text-blue-600 dark:text-blue-400" />
</div>
</motion.div>
{explanationMessage && (
<WorkspaceMessage
answer={explanationMessage.content}
role={explanationMessage.role}
timestamp={explanationMessage.timestamp}
/>
)}
</AnimatePresence>

{isFollowupMode &&
!hasConversation &&
!explanationLoading &&
!limitReached && (
<div className="rounded-2xl border border-dashed border-border bg-muted/10 p-4 text-center">
<p className="text-sm text-foreground">
Start asking questions about this topic.
</p>
<p className="mt-1 text-xs text-muted-foreground">
Your progress will be remembered on this device.

<AnimatePresence initial={false}>
{conversationMessages.map((message, index) => (
<motion.div
key={message.id}
initial={false}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.3,
delay:
index === conversationMessages.length - 1 ? 0 : 0.05,
}}
>
<WorkspaceMessage
answer={message.content}
role={message.role}
timestamp={message.timestamp}
/>
</motion.div>
))}
{loading && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="flex items-start gap-3"
>
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-blue-500/10">
<Sparkles className="h-4 w-4 text-blue-600 dark:text-blue-400" />
</div>
<div className="rounded-2xl rounded-tl-md border border-border bg-muted/30 px-4 py-3">
<Loader2 className="h-5 w-5 animate-spin text-blue-600 dark:text-blue-400" />
</div>
</motion.div>
)}
</AnimatePresence>

{error && (
<div className="flex items-start gap-2 rounded-xl border border-red-500/20 bg-red-500/10 p-3">
<AlertCircle className="h-4 w-4 flex-shrink-0 text-red-500" />
<p className="text-sm text-red-600 dark:text-red-400">
{error}
</p>
</div>
)}
</div>
)}
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Missing auto-scroll to latest message — chat UX regression.

The previous messagesEndRef/scrollToBottom wiring was removed (per diff at lines 181–200) but no replacement was added. The message container at line 593 has overflow-y-auto but no ref or scroll effect, so new messages (both user and AI) won't be visible without manual scrolling — a core chat UX expectation.

🐛 Proposed fix: restore auto-scroll

Add a ref and effect to scroll to bottom when messages or loading state change:

 const inputRef = useRef<HTMLTextAreaElement>(null);
 const abortControllerRef = useRef<AbortController | null>(null);
 const explanationRequestedRef = useRef(initialWorkspace.explanationRequested);
 const skipPersistRef = useRef(initialWorkspace.skipPersist);
+const scrollRef = useRef<HTMLDivElement>(null);
 useEffect(() => {
   inputRef.current?.focus();
 }, []);

+useEffect(() => {
+  if (scrollRef.current) {
+    scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
+  }
+}, [messages, loading]);

Then attach the ref to the scroll container:

-        <div className="min-h-0 flex-1 overflow-y-auto px-2.5 py-2 sm:px-4">
+        <div ref={scrollRef} className="min-h-0 flex-1 overflow-y-auto px-2.5 py-2 sm:px-4">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="min-h-0 flex-1 overflow-y-auto px-2.5 py-2 sm:px-4">
{!isTopicContextReady && messages.length === 0 ? (
<div className="flex min-h-full flex-col items-center justify-center py-8 text-center">
<div className="mb-4 rounded-full bg-blue-500/10 p-4">
<Sparkles className="h-8 w-8 text-blue-600 dark:text-blue-400" />
</div>
)}
<h3 className="text-lg font-semibold text-foreground">
Welcome to Hyper AI Workspace
</h3>
<p className="mt-2 max-w-md text-sm text-muted-foreground">
{welcomeMessage}
</p>
</div>
) : (
<div className="space-y-3 pb-2">
{explanationLoading && !explanationMessage && (
<div className="flex items-center justify-center py-8">
<Loader2 className="h-6 w-6 animate-spin text-blue-600 dark:text-blue-400" />
</div>
)}
<AnimatePresence initial={false}>
{messages.map((message, index) => (
<motion.div
key={message.id}
initial={false}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.3,
delay: index === messages.length - 1 ? 0 : 0.05,
}}
>
<WorkspaceMessage
answer={message.content}
role={message.role}
timestamp={message.timestamp}
/>
</motion.div>
))}
{loading && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="flex items-start gap-3"
>
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-blue-500/10">
<Sparkles className="h-4 w-4 text-blue-600 dark:text-blue-400" />
</div>
<div className="rounded-2xl rounded-tl-md border border-border bg-muted/30 px-4 py-3">
<Loader2 className="h-5 w-5 animate-spin text-blue-600 dark:text-blue-400" />
</div>
</motion.div>
{explanationMessage && (
<WorkspaceMessage
answer={explanationMessage.content}
role={explanationMessage.role}
timestamp={explanationMessage.timestamp}
/>
)}
</AnimatePresence>
{isFollowupMode &&
!hasConversation &&
!explanationLoading &&
!limitReached && (
<div className="rounded-2xl border border-dashed border-border bg-muted/10 p-4 text-center">
<p className="text-sm text-foreground">
Start asking questions about this topic.
</p>
<p className="mt-1 text-xs text-muted-foreground">
Your progress will be remembered on this device.
<AnimatePresence initial={false}>
{conversationMessages.map((message, index) => (
<motion.div
key={message.id}
initial={false}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.3,
delay:
index === conversationMessages.length - 1 ? 0 : 0.05,
}}
>
<WorkspaceMessage
answer={message.content}
role={message.role}
timestamp={message.timestamp}
/>
</motion.div>
))}
{loading && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="flex items-start gap-3"
>
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-blue-500/10">
<Sparkles className="h-4 w-4 text-blue-600 dark:text-blue-400" />
</div>
<div className="rounded-2xl rounded-tl-md border border-border bg-muted/30 px-4 py-3">
<Loader2 className="h-5 w-5 animate-spin text-blue-600 dark:text-blue-400" />
</div>
</motion.div>
)}
</AnimatePresence>
{error && (
<div className="flex items-start gap-2 rounded-xl border border-red-500/20 bg-red-500/10 p-3">
<AlertCircle className="h-4 w-4 flex-shrink-0 text-red-500" />
<p className="text-sm text-red-600 dark:text-red-400">
{error}
</p>
</div>
)}
</div>
)}
</div>
const inputRef = useRef<HTMLTextAreaElement>(null);
const abortControllerRef = useRef<AbortController | null>(null);
const explanationRequestedRef = useRef(initialWorkspace.explanationRequested);
const skipPersistRef = useRef(initialWorkspace.skipPersist);
const scrollRef = useRef<HTMLDivElement>(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, [messages, loading]);
<div ref={scrollRef} className="min-h-0 flex-1 overflow-y-auto px-2.5 py-2 sm:px-4">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/ai/workspace-chat.tsx` around lines 593 - 667, The chat view in
workspace-chat.tsx is missing the auto-scroll behavior because the removed
messagesEndRef/scrollToBottom logic was not replaced, so new conversation
updates can stay out of view. Restore scrolling by adding a ref and effect in
workspace-chat.tsx that tracks the latest message/loading state and scrolls the
message list to the bottom when conversationMessages, explanationMessage, or
loading changes. Attach that ref to the overflow-y-auto container that wraps the
message list so the latest WorkspaceMessage entries are always visible.

@imuniqueshiv imuniqueshiv merged commit 11f81db into main Jul 8, 2026
5 checks passed
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🎉 Congratulations @imuniqueshiv!

Thank you for contributing to HyperLearningTech.

Your pull request has been successfully merged into main.

📦 Merge Summary

🚀 Keep Contributing

  • Follow the CONTRIBUTING.md guidelines.
  • Keep each Pull Request focused on a single feature or fix.
  • Run formatting, linting, type checking, and a production build before opening a PR.

Thank you for helping make HyperLearningTech better.

Happy Coding! 🚀

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.

1 participant