Skip to content

feat: workspace instruction modal with glassmorphism UI#186

Merged
urjitc merged 3 commits into
mainfrom
codex/workspace-instruction-modal
Feb 8, 2026
Merged

feat: workspace instruction modal with glassmorphism UI#186
urjitc merged 3 commits into
mainfrom
codex/workspace-instruction-modal

Conversation

@ibraheemshaikh5

@ibraheemshaikh5 ibraheemshaikh5 commented Feb 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Added workspace instruction modal with carousel walkthrough for new users (5 feature slides with video demos)
  • Fixed 6 bugs: modal flash-close on new users, generating signal out of sync, carousel timer leaks, missing ESC handler, video preload leaks, stacking fade transitions
  • Simplified first-open trigger: modal now only shows for the user's very first workspace (based on workspace count), removing all localStorage tracking
  • Glassmorphism UI overhaul: translucent glass surfaces with backdrop-blur, backdrop-saturate, inset highlights, glass-styled chevrons/buttons, gradient orbs
  • Auto-advance carousel on video end, manual pause on user interaction
  • Cleaned up dead code: removed instruction-modal.ts, unused props, markNewWorkspaceInstruction calls

Test plan

  • Create a brand new user → first workspace → modal should appear in "first-open" mode with carousel
  • Close modal → should stay closed, should not reappear on navigation
  • Create a second workspace → modal should NOT appear
  • Autogen route (createFrom param) → modal should appear in "autogen" mode with generating banner
  • Verify glassmorphism styling in both light and dark mode
  • Verify video auto-advance and chevron navigation work correctly
  • ESC key should close modal when close button is visible

Important

Introduces a glassmorphism UI workspace instruction modal with simplified triggers and bug fixes, while cleaning up dead code.

  • Behavior:
    • Adds WorkspaceInstructionModal with a carousel walkthrough for new users in WorkspaceInstructionModal.tsx.
    • Simplifies modal trigger to show only for the first workspace in use-workspace-instruction-modal.ts.
    • Auto-advances carousel on video end, pauses on user interaction.
  • Bug Fixes:
    • Fixes modal flash-close, signal sync issues, timer leaks, ESC handler, video preload leaks, and fade transitions.
  • UI:
    • Implements glassmorphism UI with backdrop-blur, backdrop-saturate, and gradient orbs in WorkspaceInstructionModal.tsx.
  • Code Cleanup:
    • Removes instruction-modal.ts and related dead code.
    • Deletes unused CSS animations in globals.css.

This description was created by Ellipsis for 3d35b32. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Style

    • Removed shimmer animation from the workspace instruction modal.
  • Refactor

    • Simplified onboarding/modal initialization to detect first-workspace scenarios more reliably and removed some external configuration options.
  • Behavior

    • Onboarding flow no longer relies on session-based marking or persistent storage to track new workspaces, changing when the instruction modal is shown.

@vercel

vercel Bot commented Feb 8, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
thinkex Ready Ready Preview, Comment Feb 8, 2026 7:58am

@ellipsis-dev ellipsis-dev 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.

Important

Looks good to me! 👍

Reviewed everything up to 3d35b32 in 9 seconds. Click for details.
  • Reviewed 282 lines of code in 7 files
  • Skipped 0 files when reviewing.
  • Skipped posting 0 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.

Workflow ID: wflow_x5wB0Fr5vTHzbbOF

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@coderabbitai

coderabbitai Bot commented Feb 8, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Replaces localStorage/userId-based first-open detection with an isFirstWorkspace boolean derived from workspace context, removes glass-shimmer CSS and related shimmer JSX, drops localStorage utilities and markNewWorkspaceInstruction calls, and updates the instruction modal hook and props accordingly.

Changes

Cohort / File(s) Summary
Dashboard Integration
src/app/dashboard/page.tsx
Reads allWorkspaces and loadingAllWorkspaces from workspace context to compute isFirstWorkspace; passes boolean to WorkspaceInstructionModal and removes useStaticFallback.
Instruction modal & hook
src/components/onboarding/WorkspaceInstructionModal.tsx, src/hooks/workspace/use-workspace-instruction-modal.ts
Removed mediaSrc and useStaticFallback props; useCarousel no longer returns nextVideoSrc; hook API changed from userIdisFirstWorkspace; first-open detection moved from localStorage to an in-memory guard; shimmer markup removed.
LocalStorage utilities removed
src/lib/workspace/instruction-modal.ts
Deleted getNewWorkspaceInstructionKeys and markNewWorkspaceInstruction exports (localStorage-based persistence removed).
Workspace creation flows
src/components/home/HomeContent.tsx, src/components/workspace/CreateWorkspaceModal.tsx
Removed calls to markNewWorkspaceInstruction(...) from create-success handlers and removed session dependency where applicable.
Styling
src/app/globals.css
Removed the @keyframes glass-shimmer animation block; related shimmer visual was also removed from JSX.

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard as Dashboard
  participant WC as WorkspaceContext
  participant Hook as useWorkspaceInstructionModal
  participant Modal as WorkspaceInstructionModal

  Dashboard->>WC: request allWorkspaces, loadingAllWorkspaces
  WC-->>Dashboard: return allWorkspaces, loadingAllWorkspaces
  Dashboard->>Hook: init(workspaceId, isFirstWorkspace)
  Hook->>Hook: check hasShownFirstOpenRef (in-memory)
  alt isFirstWorkspace && not shown
    Hook->>Modal: open(mode="first-open", canClose=false, showFallback=...)
  else
    Hook->>Modal: normal/autogen initialization
  end
  Modal-->>Dashboard: user interacts / closes modal
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 A tiny hop, a gentle code-skip,
Shimmer gone, context now takes the trip,
In-memory guard keeps the first-open bright,
No storage crumbs left in the night. ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title claims the PR adds 'glassmorphism UI', but the changes actually remove the glass-shimmer animation and eliminate related glassmorphism props and CSS. Update the title to accurately reflect the main objective: simplifying the workspace instruction modal's first-open trigger logic and removing localStorage tracking, e.g., 'refactor: simplify workspace instruction modal first-open logic'.
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 (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/workspace-instruction-modal

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.

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 7 files

@greptile-apps

greptile-apps Bot commented Feb 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Overview

Greptile Summary

This PR refactors the workspace instruction modal with glassmorphism UI and simplifies the trigger mechanism from localStorage-based tracking to workspace count-based logic. The changes include:

Major changes:

  • Replaced localStorage tracking (markNewWorkspaceInstruction, getNewWorkspaceInstructionKeys) with simpler workspace count check (allWorkspaces.length <= 1)
  • Added glassmorphism UI styling with backdrop blur, translucent surfaces, and glass-styled controls
  • Removed shimmer animation overlay
  • Fixed carousel timer cleanup and video preload memory leaks
  • Added ESC key handler for modal dismissal
  • Removed unused props (useStaticFallback, mediaSrc)
  • Deleted src/lib/workspace/instruction-modal.ts entirely

Code quality improvements:

  • Cleaner trigger logic eliminates localStorage sync issues
  • Proper cleanup in useCarousel hook prevents memory leaks
  • Removed dead code and unused animations

Potential issues identified:

  • Race condition: allWorkspaces.length <= 1 check may incorrectly trigger modal when loadingAllWorkspaces is true but workspaces haven't loaded yet (line 118 in dashboard/page.tsx)
  • Session-scoped hasShownFirstOpenRef prevents modal from showing if user navigates between workspaces in same session, even if navigating to their actual first workspace

Confidence Score: 3/5

  • This PR has logical issues with the workspace count check that could cause incorrect modal behavior
  • Score reflects two critical logical flaws: (1) race condition where modal triggers incorrectly when workspaces are still loading, and (2) session-scoped ref preventing modal from showing when navigating between workspaces. The glassmorphism UI changes and cleanup improvements are solid, but the core trigger logic needs refinement
  • Pay close attention to src/app/dashboard/page.tsx line 118 and src/hooks/workspace/use-workspace-instruction-modal.ts lines 147-154 for the workspace count logic

Important Files Changed

Filename Overview
src/hooks/workspace/use-workspace-instruction-modal.ts Simplified modal trigger logic from localStorage-based to workspace count-based; proper cleanup of localStorage operations and fixed potential memory leaks
src/components/onboarding/WorkspaceInstructionModal.tsx Removed unused props and shimmer animation; improved carousel cleanup logic and ESC key handling
src/app/dashboard/page.tsx Changed modal trigger from userId to workspace count check; removed unused prop

Sequence Diagram

sequenceDiagram
    participant User
    participant Dashboard
    participant Hook as useWorkspaceInstructionModal
    participant Modal as WorkspaceInstructionModal
    participant Carousel as useCarousel
    
    User->>Dashboard: Navigate to workspace
    Dashboard->>Hook: workspaceId, isFirstWorkspace, assistantIsRunning
    
    alt isFirstWorkspace && !hasShownFirstOpenRef
        Hook->>Hook: hasShownFirstOpenRef = true
        Hook->>Hook: setOpen(true), setMode("first-open")
        Hook->>Modal: open=true, mode="first-open", canClose=false
        Modal->>Carousel: Initialize carousel (activeIndex=0)
        Carousel->>Carousel: Start video playback
        Hook->>Hook: Start 7s timer for canClose
        Hook-->>Hook: After 7s: setCanClose(true)
        Hook->>Modal: canClose=true
        User->>Modal: Click close button or ESC
        Modal->>Hook: onRequestClose()
        Hook->>Hook: closeInternal("manual")
    else isAutogenRoute
        Hook->>Hook: setOpen(true), setMode("autogen")
        Hook->>Modal: open=true, mode="autogen", isGenerating=true
        Hook->>Hook: Start 45s fallback timer
        alt assistantIsRunning becomes false
            Hook->>Hook: seenRunningInCurrentAutogenRef
            alt userInteractedRef is true
                Hook->>Hook: setGenerationComplete(true)
                Hook->>Modal: isGenerating=false
                User->>Modal: Click "Continue to workspace"
                Modal->>Hook: onFallbackContinue()
            else userInteractedRef is false
                Hook->>Hook: closeInternal("autogen_complete")
            end
        else 45s timeout
            Hook->>Hook: setShowFallback(true)
            Hook->>Modal: showFallback=true
            User->>Modal: Click "Continue to workspace"
            Modal->>Hook: onFallbackContinue()
        end
    end
    
    User->>Modal: Click chevron/dot navigation
    Modal->>Carousel: goTo(index) / goNext() / goPrev()
    Carousel->>Carousel: transitionTo(nextIndex)
    Carousel->>Carousel: setFading(true), wait 250ms
    Carousel->>Carousel: setActiveIndex(nextIndex), setFading(false)
    Modal->>Hook: onUserInteracted()
    Hook->>Hook: userInteractedRef = true, pausedRef = true
    
    Carousel->>Carousel: Video ends
    Carousel->>Carousel: handleVideoEnded() -> auto-advance

Loading

@greptile-apps greptile-apps 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.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/app/dashboard/page.tsx Outdated
Comment on lines +147 to 154
// First workspace ever — show intro modal (once per session)
if (isFirstWorkspace && !hasShownFirstOpenRef.current) {
hasShownFirstOpenRef.current = true;
setOpen(true);
setMode("first-open");
setCanClose(false);
setShowFallback(false);
return;
}

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.

hasShownFirstOpenRef persists across workspace changes - if user navigates from workspace A (with 2 total) to workspace B (user's first ever), modal won't show for B because ref is already true from session

urjitc and others added 2 commits February 8, 2026 02:50
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/onboarding/WorkspaceInstructionModal.tsx (2)

371-373: ⚠️ Potential issue | 🟡 Minor

whitespace-nowrap may clip longer descriptions on narrower viewports.

Several step descriptions (e.g., "Upload a PDF and have the AI automatically create summaries and study guides.") are fairly long. With whitespace-nowrap on a container maxed at 1100 px, text will overflow or be clipped on smaller screens or when the modal is padded.

Consider removing whitespace-nowrap or replacing it with text-wrap / text-balance to allow graceful wrapping.

Proposed fix
-             <p className="text-center whitespace-nowrap text-sm text-sidebar-foreground/70">
+             <p className="text-center text-sm text-sidebar-foreground/70">

250-259: ⚠️ Potential issue | 🟡 Minor

Modal lacks a focus trap — keyboard users can tab behind the overlay.

The dialog sets aria-modal="true" but doesn't trap focus. When the modal is open, pressing Tab lets focus escape to elements behind the backdrop. This is an accessibility gap for keyboard and screen-reader users.

Consider adding a focus-trap (e.g., focus-trap-react, Radix Dialog, or a manual sentinel approach) to keep focus within the modal while it's visible.

🧹 Nitpick comments (2)
src/hooks/workspace/use-workspace-instruction-modal.ts (1)

147-156: Verify the suppressed exhaustive-deps warning is safe.

The effect on Line 156 excludes open and mode from the dependency array but references them on Line 143. This is intentional to avoid re-triggering when the effect itself sets open/mode, but it means the open && mode === "autogen" early-return guard (Line 143) won't re-evaluate if those values change from outside this effect.

Since open and mode are only mutated inside this same effect and the autogen completion effect, this appears safe today. Just ensure future changes don't introduce other paths that set open/mode independently, or the guard could go stale.

src/components/onboarding/WorkspaceInstructionModal.tsx (1)

260-267: Clicking the modal body pauses auto-advance but doesn't stop video playback.

The outer onClick calls pause() (which sets pausedRef = true and clears the fallback timer) and onUserInteracted?.(). However, the currently playing video continues — and when it ends, handleVideoEnded (Line 152) still calls transitionTo, advancing the slide regardless of the paused state. This is documented as intentional (Line 153), but it means "pause" only affects icon-only slides, not video slides. If the intent is for user clicks to fully pause progression, handleVideoEnded should also check pausedRef.

@urjitc
urjitc merged commit cdb2524 into main Feb 8, 2026
3 of 4 checks passed
@urjitc
urjitc deleted the codex/workspace-instruction-modal branch February 8, 2026 07:51
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Dev Board Feb 8, 2026
@sonarqubecloud

sonarqubecloud Bot commented Feb 8, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants