Skip to content

onboarding and polish for v0.12#2411

Merged
sawka merged 10 commits intomainfrom
sawka/onboarding-v12
Oct 9, 2025
Merged

onboarding and polish for v0.12#2411
sawka merged 10 commits intomainfrom
sawka/onboarding-v12

Conversation

@sawka
Copy link
Member

@sawka sawka commented Oct 9, 2025

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 9, 2025

Walkthrough

Increases minimum app window size and expands AI panel max width while making the AI panel initially closed. Adds an inputAtom to WaveAIModel and migrates AI panel input handling to that atom; refactors AIPanel and AIPanelInput to use model methods and extracted UI subcomponents (drag overlay, block mask, keycaps, error/welcome messaging). Updates focus utility to accept an optional target. Replaces QuickTips UI (removes its SCSS), adjusts modal padding/class assembly and TOS modal compact behavior, adds CSS variable --color-highlightbg, removes some starter layout blocks, threads meta into tab creation, adds isMacOS() util, and introduces a CLI --magnified flag for editconfig.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description Check ⚠️ Warning There is no pull request description provided, so reviewers lack any context or summary of the changes, causing the description check to fail for being unrelated to the actual code modifications. Please add a concise description outlining the purpose and key changes of this pull request to help reviewers understand its intent and scope.
Title Check ❓ Inconclusive The title “onboarding and polish for v0.12” is too generic and does not clearly convey the primary changes in the pull request, making it difficult for reviewers to understand the main focus of the update. Please update the title to succinctly summarize the most significant changes, for example “Refactor AI panel components and adjust layout constraints for v0.12 onboarding.”
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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 sawka/onboarding-v12

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
frontend/app/aipanel/aipanel.tsx (1)

4-4: Add missing AI message type imports.

AIMessagePart (used in the new submit flow) and AIMessage (for realMessageRef) are referenced later in this file but never imported, so the build fails with “Cannot find name …”. Please pull those types in alongside WaveUIMessagePart so the file type-checks.

-import { WaveUIMessagePart } from "@/app/aipanel/aitypes";
+import { WaveUIMessagePart, type AIMessage, type AIMessagePart } from "@/app/aipanel/aitypes";
🧹 Nitpick comments (6)
frontend/app/element/quicktips.tsx (2)

7-13: Consider using semantic <kbd> element.

The component renders keyboard shortcuts correctly, but using a <kbd> element instead of a <div> would be more semantic and provide better accessibility.

Apply this diff to use semantic HTML:

-const KeyCap = ({ children }: { children: React.ReactNode }) => {
-    return (
-        <div className="inline-block px-1.5 py-0.5 mx-0.5 font-mono text-[0.85em] text-gray-300 bg-highlightbg rounded-[4px] border border-gray-700 whitespace-nowrap">
-            {children}
-        </div>
-    );
-};
+const KeyCap = ({ children }: { children: React.ReactNode }) => {
+    return (
+        <kbd className="inline-block px-1.5 py-0.5 mx-0.5 font-mono text-[0.85em] text-gray-300 bg-highlightbg rounded-[4px] border border-gray-700 whitespace-nowrap">
+            {children}
+        </kbd>
+    );
+};

15-21: Brittle SVG selectors create tight coupling.

The complex selectors [&_svg_#arrow1]:fill-primary and [&_svg_#arrow2]:fill-primary target specific SVG element IDs, creating tight coupling with the SVG structure. If the SVG markup changes (e.g., ID renaming, structure changes), these styles will break silently.

Consider one of these approaches:

  1. Use CSS variables/classes on the SVG itself rather than reaching into its structure from the parent.
  2. Document the expected SVG structure if this coupling is intentional.
  3. Use more generic selectors like [&_svg]:fill-primary if all SVG paths should have the same color.

Example for approach 1:

const IconBox = ({ children }: { children: React.ReactNode }) => {
    return (
        <div className="icon-box bg-highlightbg p-0.5 text-secondary text-xs rounded-[2px] mr-[5px] self-start [&_svg]:relative [&_svg]:top-[3px] [&_svg]:left-[1px] [&_svg]:h-[13px]">
            {children}
        </div>
    );
};

Then apply the fill color directly in the SVG component or via a fill-primary class.

frontend/app/modals/tos.tsx (1)

171-185: Consider debouncing the resize handler.

The updateModalHeight function mixes declarative React patterns with imperative DOM manipulation. While functional, consider these improvements:

  1. Debounce the resize handler to prevent excessive re-renders during window resizing
  2. Use React state for height management instead of direct DOM manipulation via modalRef.current.style.height

Example debounced resize handler:

import { debounce } from "@/util/util"; // or lodash

useEffect(() => {
    const debouncedUpdate = debounce(updateModalHeight, 150);
    debouncedUpdate();
    window.addEventListener("resize", debouncedUpdate);
    return () => {
        window.removeEventListener("resize", debouncedUpdate);
    };
}, []);
frontend/app/aipanel/aipanelinput.tsx (3)

38-38: Extract magic number into a named constant.

The max height calculation 6 * 24 (144px) is a magic number that represents 6 lines at 24px each. Consider extracting this into a named constant for clarity and maintainability.

+const MAX_TEXTAREA_HEIGHT = 6 * 24; // 6 lines at 24px each
+
 export const AIPanelInput = memo(({ onSubmit, status, model }: AIPanelInputProps) => {
     // ...
     const resizeTextarea = useCallback(() => {
         const textarea = textareaRef.current;
         if (!textarea) return;
 
         textarea.style.height = "auto";
         const scrollHeight = textarea.scrollHeight;
-        const maxHeight = 6 * 24;
+        const maxHeight = MAX_TEXTAREA_HEIGHT;
         textarea.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
     }, []);

42-52: Consider adding cleanup for ref registration.

The effect registers an input ref with the model but doesn't provide a cleanup function. If the component unmounts or the model instance changes, the model might retain a stale reference. Consider adding cleanup to prevent potential memory leaks.

 useEffect(() => {
     const inputRefObject: React.RefObject<AIPanelInputRef> = {
         current: {
             focus: () => {
                 textareaRef.current?.focus();
             },
             resize: resizeTextarea,
         },
     };
     model.registerInputRef(inputRefObject);
+    
+    return () => {
+        // Clear the ref when component unmounts
+        model.registerInputRef({ current: null });
+    };
 }, [model, resizeTextarea]);

57-57: Improve type safety by properly typing the event parameter.

The cast to any circumvents type checking. Since onSubmit expects a React.FormEvent, you can cast more precisely or adjust the event handling.

-onSubmit(e as any);
+onSubmit(e as unknown as React.FormEvent);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd0e75a and 64410d5.

📒 Files selected for processing (15)
  • emain/emain-window.ts (1 hunks)
  • frontend/app/aipanel/aipanel.tsx (5 hunks)
  • frontend/app/aipanel/aipanelinput.tsx (2 hunks)
  • frontend/app/aipanel/aipanelmessages.tsx (1 hunks)
  • frontend/app/aipanel/waveai-focus-utils.ts (1 hunks)
  • frontend/app/aipanel/waveai-model.tsx (1 hunks)
  • frontend/app/element/quicktips.scss (0 hunks)
  • frontend/app/element/quicktips.tsx (1 hunks)
  • frontend/app/modals/modal.scss (0 hunks)
  • frontend/app/modals/modal.tsx (2 hunks)
  • frontend/app/modals/tos.tsx (3 hunks)
  • frontend/app/workspace/workspace-layout-model.ts (2 hunks)
  • frontend/tailwindsetup.css (1 hunks)
  • pkg/wcore/layout.go (0 hunks)
  • pkg/wcore/workspace.go (3 hunks)
💤 Files with no reviewable changes (3)
  • pkg/wcore/layout.go
  • frontend/app/modals/modal.scss
  • frontend/app/element/quicktips.scss
🧰 Additional context used
🧬 Code graph analysis (4)
frontend/app/element/quicktips.tsx (2)
frontend/util/platformutil.ts (2)
  • PLATFORM (2-2)
  • PlatformMacOS (1-1)
frontend/app/element/magnify.tsx (1)
  • MagnifyIcon (12-18)
frontend/app/aipanel/aipanelinput.tsx (2)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasFocusWithin (15-42)
frontend/app/aipanel/ai-utils.ts (3)
  • isAcceptableFile (4-42)
  • validateFileSize (147-182)
  • formatFileSizeError (184-187)
frontend/app/aipanel/aipanel.tsx (2)
frontend/app/aipanel/waveai-model.tsx (1)
  • clearChat (128-138)
frontend/app/aipanel/aipanelmessages.tsx (1)
  • AIPanelMessages (15-63)
pkg/wcore/workspace.go (2)
pkg/waveobj/metamap.go (1)
  • MetaMapType (8-8)
pkg/waveobj/wtype.go (2)
  • Tab (183-190)
  • Tab (192-194)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build for TestDriver.ai
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (15)
frontend/tailwindsetup.css (1)

34-34: Highlight background variable looks good

New token slots cleanly into the theme map and keeps parity with existing hover styling. No issues spotted.

emain/emain-window.ts (1)

29-30: LGTM! Consider verifying on smaller displays.

The increased minimum window dimensions (800x500) are reasonable for a modern desktop application and align with the broader UI improvements in this PR. The change will gracefully handle existing windows by enforcing the new minimums at startup.

Consider testing on smaller displays (e.g., 1366x768 or lower) to ensure the app remains comfortably usable at these minimum dimensions and that no critical UI elements are cut off or inaccessible.

frontend/app/element/quicktips.tsx (1)

23-174: LGTM! Clean refactoring with new features.

The refactoring successfully:

  • Consolidates keybinding rendering with the new KeyCap component
  • Restructures the layout using Tailwind flex utilities
  • Adds new keybindings for Wave AI panel (Cmd+Shift+a) and focus (Ctrl+Shift+0)
  • Removes the external SCSS dependency in favor of inline styles

The logic is preserved and the new structure is more maintainable with consistent component usage.

frontend/app/modals/modal.tsx (2)

5-5: LGTM!

The cn utility import is appropriate for the class composition refactor below.


99-99: Good refactor to Tailwind utilities.

The change from template string to cn utility with explicit padding classes aligns with the move away from SCSS-based styling. The cn utility properly handles Tailwind class merging and conflicts.

frontend/app/modals/tos.tsx (7)

13-13: LGTM!

Removing the unused getApi import and keeping only atoms is correct.


20-20: LGTM!

The addition of the isCompact prop enables responsive layout adjustments based on window height.


44-127: Well-structured responsive layout.

The restructuring with flex containers and OverlayScrollbarsComponent provides proper scrollable content handling, and the isCompact-based dynamic spacing creates a good responsive experience.


131-131: LGTM!

Consistent with ModalPage1's signature change.


139-164: LGTM!

The restructuring follows the same pattern as ModalPage1, maintaining consistency across both pages.


187-202: LGTM!

Both useEffect hooks are properly structured with correct cleanup functions to prevent memory leaks.


217-223: LGTM!

The dynamic padding classes and modal structure provide good responsive behavior, adjusting padding based on the available window height.

pkg/wcore/workspace.go (2)

211-216: LGTM!

The conditional metadata initialization is correct. The initial launch tab receives "waveai:panelopen": true to open the AI panel, while other tabs have nil metadata. The boolean value and nil map handling are both valid in Go.


217-217: Approve createTabObj meta parameter update
The new meta argument is correctly threaded through the sole call in pkg/wcore/workspace.go, and no other callers were found.

frontend/app/aipanel/aipanelinput.tsx (1)

24-172: LGTM! Well-structured refactoring from prop-based to atom-based state management.

The component has been successfully refactored to use internal state via model.inputAtom instead of external props. The new structure with memoization, internal ref registration, and dedicated focus management handlers is clean and maintainable. The file upload validation logic is thorough, and the auto-resize behavior is properly implemented with appropriate effect dependencies.

};
}, []);

let pageComp: React.JSX.Element = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix the type annotation.

The variable pageComp is initialized with null but the type React.JSX.Element doesn't include null. This will cause a TypeScript error.

Apply this diff:

-let pageComp: React.JSX.Element = null;
+let pageComp: React.JSX.Element | null = null;
📝 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
let pageComp: React.JSX.Element = null;
let pageComp: React.JSX.Element | null = null;
🤖 Prompt for AI Agents
In frontend/app/modals/tos.tsx around line 204, the variable pageComp is
declared as React.JSX.Element but initialized to null which is not assignable;
change the type to allow null (e.g., React.JSX.Element | null) or use a
nullable/optional type such as React.ReactNode, then keep the null initializer
or initialize appropriately so the TypeScript error is resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/util/platformutil.ts (1)

8-10: Use strict equality for consistency.

Line 9 uses loose equality (==) while line 16 in this file uses strict equality (===) for the same type of comparison. For consistency and to follow TypeScript best practices, use strict equality.

Apply this diff:

 export function isMacOS(): boolean {
-    return PLATFORM == PlatformMacOS;
+    return PLATFORM === PlatformMacOS;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64410d5 and a4172f2.

📒 Files selected for processing (2)
  • frontend/app/aipanel/aipanel.tsx (6 hunks)
  • frontend/util/platformutil.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/app/aipanel/aipanel.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Build for TestDriver.ai

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
frontend/util/platformutil.ts (1)

8-10: Use strict equality for consistency.

The function logic is correct. However, for consistency with the existing codebase (line 16 uses ===) and TypeScript best practices, prefer strict equality (===) over loose equality (==).

Apply this diff:

 export function isMacOS(): boolean {
-    return PLATFORM == PlatformMacOS;
+    return PLATFORM === PlatformMacOS;
 }
frontend/app/aipanel/aipanel.tsx (1)

84-164: Consider clarifying the Widget Context toggle location.

The welcome message provides excellent onboarding content and correctly uses platform-specific keyboard shortcuts. However, the Widget Context section (lines 105-108) explains the ON/OFF behavior without indicating where users can find or toggle this setting. Consider adding a brief mention of where to locate this control (e.g., "in settings" or "in the panel header") to improve discoverability.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64410d5 and bfef99a.

📒 Files selected for processing (3)
  • frontend/app/aipanel/aipanel.tsx (6 hunks)
  • frontend/app/aipanel/aipanelinput.tsx (2 hunks)
  • frontend/util/platformutil.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/app/aipanel/aipanelinput.tsx (3)
frontend/app/store/focusManager.ts (1)
  • focusManager (86-86)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasFocusWithin (15-42)
frontend/app/aipanel/ai-utils.ts (3)
  • isAcceptableFile (4-42)
  • validateFileSize (147-182)
  • formatFileSizeError (184-187)
frontend/app/aipanel/aipanel.tsx (5)
frontend/util/platformutil.ts (1)
  • isMacOS (8-10)
frontend/app/aipanel/waveai-model.tsx (1)
  • clearChat (128-138)
frontend/app/aipanel/aipanelmessages.tsx (1)
  • AIPanelMessages (15-63)
frontend/app/aipanel/aidroppedfiles.tsx (1)
  • AIDroppedFiles (14-60)
frontend/app/aipanel/aipanelinput.tsx (1)
  • AIPanelInput (24-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
  • GitHub Check: Build for TestDriver.ai
🔇 Additional comments (7)
frontend/app/aipanel/aipanelinput.tsx (2)

10-11: LGTM! Clean refactor to model-based state management.

The shift from prop-based to model.inputAtom-based input management aligns well with the PR's global store architecture. The jotai imports and useAtom usage are correct.

Also applies to: 24-31


42-52: LGTM! Proper ref registration and resize handling.

The effect correctly registers the input ref with the model, exposing focus and resize methods. The resize effects have proper dependencies and trigger appropriately on input changes and panel visibility.

Also applies to: 77-85

frontend/app/aipanel/aipanel.tsx (5)

28-50: LGTM! Clean component for layout mode overlay.

The AIBlockMask component is well-structured, properly memoized, and uses appropriate CSS variables for theming.


52-82: LGTM! Well-designed UI utility components.

Both AIDragOverlay and KeyCap are properly implemented with appropriate styling and memoization.


168-188: LGTM! Accessible error message component.

The AIErrorMessage component is well-implemented with proper accessibility (aria-label) and overflow handling.


297-304: LGTM! Consistent global store integration.

The input management correctly uses the global store via model.inputAtom for reading and writing input state. The focus management through model.focusInput() properly delegates to the model's registered input ref.

Also applies to: 356-361


482-503: LGTM! Clean component-based rendering.

The refactor to component-based rendering for overlays, welcome message, and errors improves code organization. The conditional rendering logic correctly shows the welcome message when there are no messages and chat is not loading.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
frontend/app/modals/tos.tsx (1)

206-206: Fix the type annotation.

The variable pageComp is initialized with null but the type React.JSX.Element doesn't include null. This will cause a TypeScript error.

Apply this diff:

-let pageComp: React.JSX.Element = null;
+let pageComp: React.JSX.Element | null = null;
🧹 Nitpick comments (1)
frontend/app/modals/tos.tsx (1)

172-176: Extract the compact mode threshold to a constant.

The height threshold value 800 is duplicated on lines 172 and 176. Extract it to a named constant to improve maintainability and make the intent clearer.

Apply this diff to extract the constant:

+const COMPACT_MODE_HEIGHT_THRESHOLD = 800;
+
 const TosModal = () => {
     const modalRef = useRef<HTMLDivElement | null>(null);
     const [pageNum, setPageNum] = useAtom(pageNumAtom);
     const clientData = useAtomValue(atoms.client);
-    const [isCompact, setIsCompact] = useState<boolean>(window.innerHeight < 800);
+    const [isCompact, setIsCompact] = useState<boolean>(window.innerHeight < COMPACT_MODE_HEIGHT_THRESHOLD);
 
     const updateModalHeight = () => {
         const windowHeight = window.innerHeight;
-        setIsCompact(windowHeight < 800);
+        setIsCompact(windowHeight < COMPACT_MODE_HEIGHT_THRESHOLD);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfef99a and 01f7d39.

📒 Files selected for processing (3)
  • cmd/wsh/cmd/wshcmd-editconfig.go (3 hunks)
  • frontend/app/element/quicktips.tsx (1 hunks)
  • frontend/app/modals/tos.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/app/element/quicktips.tsx (2)
frontend/util/platformutil.ts (2)
  • PLATFORM (2-2)
  • PlatformMacOS (1-1)
frontend/app/element/magnify.tsx (1)
  • MagnifyIcon (12-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build for TestDriver.ai
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
cmd/wsh/cmd/wshcmd-editconfig.go (3)

16-16: LGTM!

The package-level flag variable is properly declared and follows Go naming conventions.


28-28: LGTM!

The flag registration follows Cobra conventions correctly with a clear description and appropriate shorthand.


58-59: LGTM!

The flag is correctly applied to the CommandCreateBlockData. The unconditional Focused: true setting is appropriate for ensuring the config editor receives focus when opened.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/app/aipanel/aipanel.tsx (1)

29-51: Consider using a CSS variable for the header height.

The hardcoded 44px in mt-[44px] and h-[calc(100%-44px)] assumes a fixed header height. If the header size changes (e.g., responsive breakpoints), this will break.

Consider defining a CSS variable for header height or calculating it dynamically:

+const HEADER_HEIGHT = 44; // or derive from a shared constant
+
 const AIBlockMask = memo(() => {
     return (
         <div
             ...
         >
             <div
-                className="w-full mt-[44px] h-[calc(100%-44px)] flex items-center justify-center"
+                className="w-full flex items-center justify-center"
+                style={{ marginTop: `${HEADER_HEIGHT}px`, height: `calc(100% - ${HEADER_HEIGHT}px)` }}
                 ...
             >

Alternatively, use a CSS variable in your stylesheet:

:root {
  --ai-panel-header-height: 44px;
}

And reference it in the component:

-                className="w-full mt-[44px] h-[calc(100%-44px)] flex items-center justify-center"
+                style={{ marginTop: 'var(--ai-panel-header-height)', height: 'calc(100% - var(--ai-panel-header-height))' }}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 01f7d39 and d292e02.

📒 Files selected for processing (2)
  • frontend/app/aipanel/aipanel.tsx (7 hunks)
  • frontend/app/aipanel/aipanelheader.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/app/aipanel/aipanel.tsx (5)
frontend/util/platformutil.ts (1)
  • isMacOS (8-10)
frontend/app/aipanel/waveai-focus-utils.ts (1)
  • waveAIHasSelection (44-59)
frontend/app/aipanel/aipanelmessages.tsx (1)
  • AIPanelMessages (15-63)
frontend/app/aipanel/aidroppedfiles.tsx (1)
  • AIDroppedFiles (14-60)
frontend/app/aipanel/aipanelinput.tsx (1)
  • AIPanelInput (24-172)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Build for TestDriver.ai
🔇 Additional comments (8)
frontend/app/aipanel/aipanelheader.tsx (1)

5-35: LGTM! Clean simplification of the header component.

The migration from useAtom to useAtomValue is appropriate since the component only reads the widgetAccessAtom. The removal of model selection UI from the context menu simplifies the header and aligns with the broader refactor toward model-driven state management.

frontend/app/aipanel/aipanel.tsx (7)

53-68: LGTM! Well-structured drag overlay component.

The AIDragOverlay component provides clear visual feedback during drag-and-drop operations with appropriate styling and messaging.


70-83: LGTM! Reusable keyboard shortcut component.

The KeyCap component provides a clean, reusable way to display keyboard shortcuts throughout the UI.


85-167: LGTM! Comprehensive and well-structured welcome message.

The welcome message provides clear guidance on getting started with Wave AI, including:

  • Platform-specific keyboard shortcuts (using isMacOS() correctly)
  • Widget context explanation
  • File upload capabilities
  • Community links with proper security attributes (rel="noopener")

169-189: LGTM! Clean error message component.

The component provides good UX with:

  • Clear visual distinction (red color scheme, border)
  • Dismissible via close button
  • Scrollable content for long error messages
  • Proper accessibility with aria-label

298-303: LGTM! Consistent migration to global input state.

The input management has been successfully migrated from local state to the global store via model.inputAtom. The pattern is consistent across all usage sites:

  • Reading input at line 298
  • Clearing input after commands at line 303
  • Clearing input after message submission at line 357

This aligns with the broader refactor toward atom-based state management described in the AI summary.

Also applies to: 357-357


458-489: LGTM! Well-implemented context menu handler.

The context menu provides appropriate options:

  • Conditional "Copy" option when text is selected (using waveAIHasSelection())
  • "New Chat" action
  • "Hide Wave AI" action

Proper event handling with preventDefault() and stopPropagation() prevents conflicts with parent handlers.


516-540: LGTM! Clean component composition and rendering logic.

The rendering logic has been improved with:

  • Component extraction for drag overlay and block mask (lines 516-517)
  • Clear conditional rendering: welcome message when messages.length === 0 && !isLoadingChat, otherwise show messages (lines 526-534)
  • Context menu attached to both rendering paths (lines 527, 531)
  • Proper error message display using the new AIErrorMessage component (lines 535-537)
  • Consistent use of the AIPanelInput component (line 539)

The refactor improves maintainability while preserving all functionality.

@sawka sawka merged commit 7451294 into main Oct 9, 2025
8 checks passed
@sawka sawka deleted the sawka/onboarding-v12 branch October 9, 2025 23:29
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