Skip to content

Feat/add writing style, new editor toolbar, and styling updates#40

Closed
will-lp1 wants to merge 17 commits intomainfrom
feat/add-writing-style
Closed

Feat/add writing style, new editor toolbar, and styling updates#40
will-lp1 wants to merge 17 commits intomainfrom
feat/add-writing-style

Conversation

@will-lp1
Copy link
Owner

@will-lp1 will-lp1 commented Jul 7, 2025

Summary by CodeRabbit

  • New Features

    • Introduced personalized writing style support: users can train the AI with a writing sample to generate a style summary and optionally apply it to chat, suggestions, and inline suggestions.
    • Added a new settings menu workflow for training, applying, retraining, or clearing a writing style profile.
    • Added a new API endpoint for analyzing and summarizing user writing style.
    • Introduced a toolbar for rich text editing in the document editor.
    • Added new UI components: Badge and Switch.
  • Improvements

    • Unified and updated color schemes and styling across the app, including editor, sidebar, and input elements.
    • Enhanced state management to persist and synchronize new AI writing style options.
    • Updated Discord invite link in the overview section.
  • Bug Fixes

    • Corrected various UI inconsistencies and improved dark mode appearance.
  • Refactor

    • Streamlined hover and border logic in several components for cleaner and more consistent styling.
    • Moved and improved the EditorToolbar component for better maintainability.
  • Chores

    • Added new dependencies for UI and editor functionality.

@coderabbitai
Copy link

coderabbitai bot commented Jul 7, 2025

Walkthrough

This update introduces personalized writing style support across chat, suggestion, and inline suggestion APIs, as well as the UI. Users can submit a writing sample to generate a style summary, which can then be applied to AI-generated content. The changes span backend prompt construction, API parameter handling, state management, and frontend settings and editor integration.

Changes

Files/Paths Change Summary
app/api/chat/route.ts, app/api/inline-suggestion/route.ts, app/api/suggestion/route.ts Extended APIs to accept writingStyleSummary and applyStyle parameters, updating prompt construction to optionally include a "PERSONAL STYLE GUIDE" block for personalized style emulation. Function signatures and parameter extraction updated accordingly.
app/api/user-style/route.ts Added new POST endpoint to generate a concise summary of a user's writing style from a provided sample, streaming the result from the language model and handling errors and minimum length validation.
components/ai-settings-menu.tsx Major enhancement: Added UI and logic for users to input a writing sample, generate a style summary, toggle style application, retrain, or clear their style profile. Integrated new state variables and asynchronous summary generation with feedback.
components/chat/chat.tsx, components/suggestion-overlay.tsx, components/document/text-editor.tsx Integrated new AI options (writingStyleSummary, applyStyle) into API requests for chat, suggestion, and inline suggestion features. Updated hooks and refs accordingly.
hooks/ai-options.ts Extended global AI options state with writingSample, writingStyleSummary, and applyStyle, including persistence, setters, and selector updates.
components/document/editor-toolbar.tsx Introduced new EditorToolbar component for ProseMirror-based editor, replacing the previous toolbar and adding formatting controls.
components/editor-toolbar.tsx Deleted old toolbar component, replaced by the new version in the document folder.
components/chat/chat-header.tsx, components/always-visible-artifact.tsx, components/sidebar/app-sidebar.tsx, components/sidebar/feedback-widget.tsx, components/sidebar/sidebar-documents.tsx, components/sidebar/sidebar-user-nav.tsx, components/ui/button.tsx, components/ui/input.tsx, components/ui/textarea.tsx, components/ui/sidebar.tsx, components/resizable-panel.tsx, components/chat/overview.tsx Various UI and styling adjustments: border and background class changes, hover effect updates, button and input styling tweaks, and removal of unused imports or comments. No logic changes.
components/ui/badge.tsx, components/ui/switch.tsx Added new reusable Badge and Switch UI components with variant-based styling and Radix UI integration.
app/globals.css Unified color variables to neutral HSL, updated editor and suggestion highlight styles, and added explicit .editor-area and .toolbar styling for consistent theming.
lib/editor/config.ts Simplified assignment formatting for diff mark class names; no logic changes.
package.json Added dependencies: @radix-ui/react-slot and prosemirror-tables.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AiSettingsMenu
    participant API_UserStyle
    participant AI_Model

    User->>AiSettingsMenu: Enter writing sample & click "Train"
    AiSettingsMenu->>API_UserStyle: POST /api/user-style {sampleText}
    API_UserStyle->>AI_Model: Generate style summary prompt
    AI_Model-->>API_UserStyle: Stream style summary
    API_UserStyle-->>AiSettingsMenu: Return summary
    AiSettingsMenu->>User: Display summary & toggle/apply options
Loading
sequenceDiagram
    participant User
    participant Editor/Chat/Suggestion
    participant API
    participant AI_Model

    User->>Editor/Chat/Suggestion: Request suggestion/chat
    Editor/Chat/Suggestion->>API: POST/GET with aiOptions {writingStyleSummary, applyStyle}
    API->>AI_Model: Build prompt (with optional PERSONAL STYLE GUIDE)
    AI_Model-->>API: Generate completion
    API-->>Editor/Chat/Suggestion: Return suggestion/chat
    Editor/Chat/Suggestion->>User: Display result in user style (if enabled)
Loading

Possibly related PRs

  • will-lp1/snowleopard#30: Simplifies the inline suggestion API by removing documentId and userId parameters; both PRs modify the same API file but address different concerns.

Poem

A rabbit with a writer’s soul
Now helps you set your style goal.
Give it a sample, let it learn,
Your tone and quirks it will discern.
With toggles, badges, switches bright—
Your words now hop with custom light!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0fe5f4 and 735e9c2.

📒 Files selected for processing (1)
  • apps/snow-leopard/components/document/editor-toolbar.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/snow-leopard/components/document/editor-toolbar.tsx
✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@vercel
Copy link

vercel bot commented Jul 7, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
cursorforwriting-wkur ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 7, 2025 6:24pm

Copy link

@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: 5

🧹 Nitpick comments (5)
apps/snow-leopard/app/api/user-style/route.ts (2)

11-16: Enhance input validation for better security.

Consider validating that sampleText contains actual text content rather than just checking length. Malicious users could submit 200+ characters of whitespace or special characters.

-    if (typeof sampleText !== 'string' || sampleText.trim().length < 200) {
+    if (typeof sampleText !== 'string' || sampleText.trim().length < 200 || !/\w/.test(sampleText)) {
       return NextResponse.json(
-        { error: 'Please provide at least ~200 characters of sample text.' },
+        { error: 'Please provide at least ~200 characters of meaningful text content.' },
         { status: 400 }
       );
     }

20-26: Consider adding input limits for cost control.

The endpoint doesn't limit the maximum input size, which could lead to high API costs for very large text samples.

    if (typeof sampleText !== 'string' || sampleText.trim().length < 200) {
+    if (sampleText.trim().length > 10000) {
+      return NextResponse.json(
+        { error: 'Sample text is too long. Please provide less than 10,000 characters.' },
+        { status: 400 }
+      );
+    }
apps/snow-leopard/app/api/chat/route.ts (1)

67-70: Use template literal for better readability.

The string concatenation should be replaced with a template literal as suggested by static analysis.

-    const styleBlock = `PERSONAL STYLE GUIDE\n• Emulate the author\'s tone, rhythm, sentence structure, vocabulary choice, and punctuation habits.\n• Do NOT copy phrases or introduce topics from the reference text.\n• Only transform wording to match style; keep semantic content from the current conversation.\nStyle description: ${writingStyleSummary}`;
-    basePrompt = styleBlock + "\n\n" + basePrompt;
+    const styleBlock = `PERSONAL STYLE GUIDE\n• Emulate the author's tone, rhythm, sentence structure, vocabulary choice, and punctuation habits.\n• Do NOT copy phrases or introduce topics from the reference text.\n• Only transform wording to match style; keep semantic content from the current conversation.\nStyle description: ${writingStyleSummary}`;
+    basePrompt = `${styleBlock}\n\n${basePrompt}`;
apps/snow-leopard/app/api/suggestion/route.ts (1)

17-17: Remove redundant type annotation.

As suggested by static analysis, the type annotation is redundant since it's inferred from the default value.

-  applyStyle: boolean = true
+  applyStyle = true
apps/snow-leopard/app/api/inline-suggestion/route.ts (1)

12-12: Remove redundant type annotations.

The type annotations for applyStyle are inferred from the default values.

-  applyStyle: boolean = true
+  applyStyle = true

Also applies to: 158-158

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dae5043 and b0fe5f4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (28)
  • apps/snow-leopard/app/api/chat/route.ts (4 hunks)
  • apps/snow-leopard/app/api/inline-suggestion/route.ts (6 hunks)
  • apps/snow-leopard/app/api/suggestion/route.ts (6 hunks)
  • apps/snow-leopard/app/api/user-style/route.ts (1 hunks)
  • apps/snow-leopard/app/globals.css (4 hunks)
  • apps/snow-leopard/components/ai-settings-menu.tsx (4 hunks)
  • apps/snow-leopard/components/always-visible-artifact.tsx (3 hunks)
  • apps/snow-leopard/components/chat/chat-header.tsx (3 hunks)
  • apps/snow-leopard/components/chat/chat.tsx (3 hunks)
  • apps/snow-leopard/components/chat/overview.tsx (1 hunks)
  • apps/snow-leopard/components/document/editor-toolbar.tsx (1 hunks)
  • apps/snow-leopard/components/document/text-editor.tsx (5 hunks)
  • apps/snow-leopard/components/editor-toolbar.tsx (0 hunks)
  • apps/snow-leopard/components/resizable-panel.tsx (4 hunks)
  • apps/snow-leopard/components/sidebar/app-sidebar.tsx (2 hunks)
  • apps/snow-leopard/components/sidebar/feedback-widget.tsx (1 hunks)
  • apps/snow-leopard/components/sidebar/sidebar-documents.tsx (1 hunks)
  • apps/snow-leopard/components/sidebar/sidebar-user-nav.tsx (1 hunks)
  • apps/snow-leopard/components/suggestion-overlay.tsx (3 hunks)
  • apps/snow-leopard/components/ui/badge.tsx (1 hunks)
  • apps/snow-leopard/components/ui/button.tsx (1 hunks)
  • apps/snow-leopard/components/ui/input.tsx (1 hunks)
  • apps/snow-leopard/components/ui/sidebar.tsx (2 hunks)
  • apps/snow-leopard/components/ui/switch.tsx (1 hunks)
  • apps/snow-leopard/components/ui/textarea.tsx (1 hunks)
  • apps/snow-leopard/hooks/ai-options.ts (5 hunks)
  • apps/snow-leopard/lib/editor/config.ts (1 hunks)
  • apps/snow-leopard/package.json (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/snow-leopard/components/editor-toolbar.tsx
🧰 Additional context used
🧬 Code Graph Analysis (8)
apps/snow-leopard/components/chat/chat.tsx (1)
apps/snow-leopard/hooks/ai-options.ts (1)
  • useAiOptionsValue (93-100)
apps/snow-leopard/components/sidebar/sidebar-user-nav.tsx (1)
apps/snow-leopard/components/ui/sidebar.tsx (1)
  • SidebarMenuButton (828-828)
apps/snow-leopard/components/resizable-panel.tsx (1)
apps/snow-leopard/lib/utils.ts (1)
  • cn (15-17)
apps/snow-leopard/components/document/text-editor.tsx (1)
apps/snow-leopard/hooks/ai-options.ts (1)
  • useAiOptionsValue (93-100)
apps/snow-leopard/components/ui/badge.tsx (1)
apps/snow-leopard/lib/utils.ts (1)
  • cn (15-17)
apps/snow-leopard/components/ui/switch.tsx (1)
apps/snow-leopard/lib/utils.ts (1)
  • cn (15-17)
apps/snow-leopard/components/document/editor-toolbar.tsx (7)
apps/snow-leopard/lib/editor/config.ts (1)
  • documentSchema (31-37)
apps/snow-leopard/lib/editor/editor-state.ts (1)
  • getActiveEditorView (19-21)
apps/snow-leopard/lib/utils.ts (1)
  • cn (15-17)
apps/snow-leopard/components/ui/tooltip.tsx (3)
  • Tooltip (30-30)
  • TooltipTrigger (30-30)
  • TooltipContent (30-30)
apps/snow-leopard/components/ui/button.tsx (1)
  • Button (56-56)
apps/snow-leopard/components/ui/dropdown-menu.tsx (4)
  • DropdownMenu (185-185)
  • DropdownMenuTrigger (186-186)
  • DropdownMenuContent (187-187)
  • DropdownMenuItem (188-188)
apps/snow-leopard/components/ui/separator.tsx (1)
  • Separator (31-31)
apps/snow-leopard/components/suggestion-overlay.tsx (1)
apps/snow-leopard/hooks/ai-options.ts (1)
  • useAiOptionsValue (93-100)
🪛 Biome (1.9.4)
apps/snow-leopard/app/api/chat/route.ts

[error] 69-70: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

apps/snow-leopard/app/api/suggestion/route.ts

[error] 17-17: This type annotation is trivially inferred from its initialization.

Safe fix: Remove the type annotation.

(lint/style/noInferrableTypes)

apps/snow-leopard/app/api/inline-suggestion/route.ts

[error] 12-12: This type annotation is trivially inferred from its initialization.

Safe fix: Remove the type annotation.

(lint/style/noInferrableTypes)


[error] 158-158: This type annotation is trivially inferred from its initialization.

Safe fix: Remove the type annotation.

(lint/style/noInferrableTypes)

🔇 Additional comments (47)
apps/snow-leopard/components/chat/overview.tsx (1)

39-39: Discord Invite Link Verified

The new Discord invite link (https://discord.gg/TwG73aHE) returns an HTTP 301 redirect, matching the behavior of the previous link. It appears valid and intentional. No further changes required.

apps/snow-leopard/components/sidebar/app-sidebar.tsx (2)

30-30: LGTM: Consistent styling update.

Removing the border-none class allows the default border styling to be applied, which aligns with the broader UI styling updates across the sidebar components.


39-39: LGTM: Improved hover consistency.

The change from hover:bg-muted to hover:bg-accent creates better consistency with the design system and aligns with similar changes across other sidebar components.

apps/snow-leopard/components/ui/sidebar.tsx (1)

339-339: LGTM: Improved border positioning.

Moving the border-r class from the outer fixed container to the inner sidebar content div provides better visual separation and is more semantically appropriate, as the border now belongs to the actual content container.

Also applies to: 351-351

apps/snow-leopard/components/ui/switch.tsx (1)

1-30: LGTM: Well-implemented Switch component.

This is a solid implementation of a Switch component using Radix UI primitives. The code follows React best practices:

  • Proper use of forwardRef for ref forwarding
  • Correct TypeScript types for props and refs
  • Good use of the cn utility for class composition
  • Comprehensive styling with proper focus, disabled, and state variants
  • Proper display name assignment for debugging

The component is ready for use across the application.

apps/snow-leopard/components/resizable-panel.tsx (2)

114-132: LGTM: Excellent refactoring to use CSS group hover.

The refactoring from explicit React state (isHovering) to CSS group hover pseudo-classes is a great improvement that:

  • Reduces component state complexity and eliminates unnecessary re-renders
  • Improves performance by handling hover effects purely in CSS
  • Makes the code more maintainable and aligns with modern CSS practices
  • Maintains the same visual behavior while simplifying the implementation

The resize handle styling and transitions look well-implemented.


138-152: LGTM: Improved transition consistency.

The changes to use transition-all instead of specific transition properties and the streamlined JSX structure improve consistency and maintainability while preserving the same functionality.

apps/snow-leopard/components/ui/badge.tsx (1)

1-37: LGTM! Well-implemented Badge component.

The Badge component follows excellent patterns with proper variant configuration, TypeScript interfaces, and consistent styling. The implementation correctly uses the cn utility for class composition and extends HTML div attributes appropriately.

apps/snow-leopard/components/ui/button.tsx (1)

15-16: No missing borders on the outline button
The combination of border (which applies a 1px solid border on all sides) and border-r (which merely reasserts the right-side width) still produces a full border around the button. This pattern is already used in other components, for example:

  • apps/snow-leopard/components/ui/input.tsx uses border border-r
  • apps/snow-leopard/components/ui/textarea.tsx uses border border-r

No change is needed here—the outline variant is correctly styled.

Likely an incorrect or invalid review comment.

apps/snow-leopard/lib/editor/config.ts (2)

19-19: Good formatting improvement.

Consolidating the multi-line class string to a single line improves readability while maintaining the same functionality.


22-22: Good formatting improvement.

Consolidating the multi-line class string to a single line improves readability while maintaining the same functionality.

apps/snow-leopard/package.json (2)

12-12: Appropriate dependency addition.

The @radix-ui/react-slot package is correctly added to support the new UI components mentioned in the PR.


18-18: Appropriate dependency addition.

The prosemirror-tables package aligns with the editor toolbar enhancements mentioned in the PR objectives.

apps/snow-leopard/components/sidebar/sidebar-documents.tsx (1)

606-606: Ignore the border‐r concern on the search input.

The border class already applies a full 1px border on all sides; the additional border-r is effectively redundant and used consistently across our inputs (see ui/input.tsx and ui/textarea.tsx). No change is needed here.

Likely an incorrect or invalid review comment.

apps/snow-leopard/components/chat/chat.tsx (1)

19-19: LGTM! Clean integration of AI writing style options.

The implementation correctly integrates the writing style customization by:

  • Importing the useAiOptionsValue hook
  • Extracting the required writingStyleSummary and applyStyle values
  • Passing them to the chat API through the aiOptions field

This follows the established pattern and aligns with the hook implementation in apps/snow-leopard/hooks/ai-options.ts.

Also applies to: 39-39, 88-91

apps/snow-leopard/components/sidebar/sidebar-user-nav.tsx (1)

191-191: LGTM! Consistent styling update for sidebar components.

The styling change appropriately transitions from background-based highlighting to border-focused accents while maintaining proper text color handling for different states (text-accent-foreground and data-[state=open]:text-sidebar-accent-foreground).

apps/snow-leopard/components/ui/textarea.tsx (1)

12-12: Consistent styling change but same accessibility concern as Input component.

The change maintains consistency with the Input component by applying the same border and focus styling updates. However, the removal of focus-visible classes raises the same accessibility concerns regarding keyboard navigation focus indicators.

Please ensure this is part of a coordinated accessibility-aware design system update where alternative focus indication methods are being implemented.

apps/snow-leopard/components/always-visible-artifact.tsx (2)

293-293: LGTM! Simplified border styling approach.

The removal of explicit dark mode border color classes (border-zinc-200 dark:border-zinc-700) in favor of generic border-b simplifies the styling and likely relies on CSS custom properties for consistent theming.

Also applies to: 333-333


386-386: LGTM! Consistent dark mode styling update.

The background and text color changes (bg-background text-foreground dark:bg-black dark:text-white) align with the broader UI theme refinements mentioned in the summary, moving toward a more neutral color scheme with explicit text color handling.

apps/snow-leopard/components/suggestion-overlay.tsx (3)

65-65: LGTM! Proper integration of writing style options.

The destructuring correctly includes the new writingStyleSummary and applyStyle options from the AI options state.


303-308: Well-implemented conditional parameter handling.

The logic correctly adds writing style parameters to the API request only when applyStyle is enabled, and includes the summary only when both conditions are met. This prevents unnecessary API overhead when the feature is disabled.


379-379: Correct dependency array update.

The addition of writingStyleSummary and applyStyle to the dependency array ensures the handleSubmitPrompt callback updates when these AI options change, maintaining proper React hook behavior.

apps/snow-leopard/components/chat/chat-header.tsx (3)

67-67: Good styling consistency improvement.

The addition of border-r border-border to the header maintains visual consistency with other components that have received similar border treatments.


72-73: Approve button variant and styling updates.

The change to variant="outline" and the comprehensive styling update improves visual consistency. The flexbox centering and border styling align well with the overall UI refresh.


104-104: Consistent button variant update.

The change from variant="ghost" to variant="outline" maintains consistency with other button updates in this component.

apps/snow-leopard/components/document/text-editor.tsx (6)

39-39: Correct import path update.

The updated import path reflects the reorganization of the EditorToolbar component to @/components/document/editor-toolbar.


113-113: Proper integration of writing style options.

The destructuring of writingStyleSummary and applyStyle from useAiOptionsValue and creation of corresponding refs follows the established pattern used for other AI options in this component.

Also applies to: 116-117


124-129: Correct ref synchronization with state.

The useEffect hooks properly synchronize the refs with the current state values, ensuring async operations use the latest values.


230-231: Well-integrated AI options in API request.

The addition of writingStyleSummary and applyStyle to the aiOptions object maintains consistency with how other AI options are passed to the inline suggestion API.


816-816: Improved editor container styling.

The updated className adds proper background, text color, and prose styling that enhances the editor's visual appearance and consistency.


960-964: Good layout constraint styling.

The CSS rules properly constrain the editor area and toolbar to a maximum width of 720px and center them horizontally, improving readability and layout consistency.

apps/snow-leopard/hooks/ai-options.ts (4)

12-14: Properly typed interface extensions.

The additions to AiOptionsState correctly define the new properties with appropriate types:

  • writingSample: string for user input
  • writingStyleSummary: string for processed style summary
  • applyStyle: boolean for feature toggle
  • Corresponding setter functions follow the established naming pattern

Also applies to: 17-19


33-35: Sensible default values and implementations.

The default values are well-chosen:

  • Empty strings for text fields allow for optional usage
  • applyStyle: true enables the feature by default when a style summary exists
  • Setter implementations follow the established Zustand pattern

Also applies to: 39-41


50-52: Robust storage synchronization.

The syncFromStorage method properly handles the new properties with:

  • Safe property access using optional chaining
  • Type checking before setting values
  • Appropriate fallback values matching the defaults

Also applies to: 58-61


74-76: Complete persistence and selector integration.

The new properties are correctly included in:

  • The partialize function for localStorage persistence
  • The useAiOptionsValue selector hook for component consumption
    This ensures the writing style features are fully integrated into the state management system.

Also applies to: 97-99

apps/snow-leopard/app/api/chat/route.ts (1)

198-199: Ensure consistent default value handling.

The applyStyle parameter defaults to true when extracted from aiOptions, which is good for user experience, but ensure this is documented and consistent across all APIs.

apps/snow-leopard/app/globals.css (3)

12-71: Excellent color system unification.

The migration from blue-based (240° hue) to neutral (0° hue) color palette creates a more professional and consistent design system. The HSL values are well-chosen for accessibility and visual hierarchy.


84-90: Good addition of explicit editor theming.

The .editor-area styling provides proper background and text color support for both light and dark modes, ensuring consistent theming across the editor components.


115-119: Improved CodeMirror integration.

Using inherit for background and none !important for outline creates better integration with the design system while maintaining editor functionality.

apps/snow-leopard/components/document/editor-toolbar.tsx (3)

38-43: Solid command execution pattern.

The runCommand utility function properly handles ProseMirror command execution with focus management, which is essential for editor UX.


85-110: Excellent accessibility implementation.

The ButtonWithTooltip component properly implements ARIA labels and tooltip functionality, making the toolbar accessible to screen readers and keyboard users.


112-179: Well-structured toolbar layout.

The toolbar implementation follows good design patterns with proper grouping of related functions (text styles, lists, formatting) and visual separators.

apps/snow-leopard/app/api/suggestion/route.ts (2)

198-201: Consistent style guide implementation.

The style guide block implementation matches the pattern used in the chat API, ensuring consistent behavior across different AI endpoints.


118-119: Proper parameter extraction from query string.

The extraction of writingStyleSummary and applyStyle from URL search parameters is handled correctly with appropriate fallbacks.

apps/snow-leopard/components/ai-settings-menu.tsx (2)

42-73: Well-implemented API handler with proper error handling.

The function correctly manages loading states, validates input, and handles both network and API errors appropriately.


169-169: Good use of Math.min to prevent progress overflow.

The progress calculation correctly caps at 100% while providing visual feedback for the minimum character requirement.

apps/snow-leopard/app/api/inline-suggestion/route.ts (1)

169-172: Well-designed style guide prompt construction.

The implementation correctly:

  • Checks both applyStyle flag and writingStyleSummary existence
  • Provides clear instructions to emulate style without copying content
  • Maintains the original prompt structure

type={type}
className={cn(
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'flex h-10 w-full rounded-md border border-r bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify accessibility impact of removing focus-visible styles.

The removal of focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 classes eliminates keyboard focus indicators, which could negatively impact accessibility for users who rely on keyboard navigation.

Please ensure this change is intentional and consistent with your design system's accessibility requirements. Consider alternative focus indication methods if the ring styles are being replaced.


🏁 Script executed:

#!/bin/bash
# Description: Check if focus-visible styles are being consistently removed across UI components
# Expected: Similar changes in textarea.tsx and other form components

echo "Checking for focus-visible class usage across UI components..."
fd -e tsx -e ts . apps/snow-leopard/components/ui/ --exec rg -l "focus-visible" {}
echo ""
echo "Checking for border-input to border-r changes..."
fd -e tsx -e ts . apps/snow-leopard/components/ui/ --exec rg -l "border-r" {}

Length of output: 986


🏁 Script executed:

#!/bin/bash
echo "Checking for focus-visible:ring usage across UI components..."
fd -e tsx -e ts . apps/snow-leopard/components/ui/ --exec rg -l "focus-visible:ring" {}

echo ""
echo "Checking for focus-visible:ring-offset usage across UI components..."
fd -e tsx -e ts . apps/snow-leopard/components/ui/ --exec rg -l "focus-visible:ring-offset" {}

Length of output: 965


Ensure consistent, accessible focus indicators on inputs

The input.tsx and textarea.tsx components have dropped the
focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
styles, while other form controls still include them. This leads to inconsistent focus indicators and may harm keyboard accessibility.

Files needing attention:

  • apps/snow-leopard/components/ui/input.tsx
  • apps/snow-leopard/components/ui/textarea.tsx

Please either:

  • Restore the ring-based focus styles, or
  • Provide an alternative, equally visible focus indicator that aligns with your design system’s accessibility guidelines.
🤖 Prompt for AI Agents
In apps/snow-leopard/components/ui/input.tsx at line 11, the input element is
missing the focus-visible:ring-2 focus-visible:ring-ring
focus-visible:ring-offset-2 styles that provide consistent and accessible focus
indicators. To fix this, add these ring-based focus styles back to the input's
className string to ensure keyboard users have a clear visual focus indicator
consistent with other form controls.

<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className="group data-[state=open]:bg-sidebar-accent bg-background data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-muted/50 transition-colors duration-200">
<SidebarMenuButton className="group data-[state=open]: border border-r text-accent-foreground data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-accent/50 transition-colors duration-200">
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Verify the CSS class syntax.

There appears to be a syntax issue in the className. The data-[state=open]: prefix seems incomplete - it should likely be data-[state=open]:text-sidebar-accent-foreground without the space after the colon.

Apply this fix:

-<SidebarMenuButton className="group data-[state=open]: border border-r text-accent-foreground data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-accent/50 transition-colors duration-200">
+<SidebarMenuButton className="group border border-r text-accent-foreground data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-accent/50 transition-colors duration-200">
📝 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
<SidebarMenuButton className="group data-[state=open]: border border-r text-accent-foreground data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-accent/50 transition-colors duration-200">
<SidebarMenuButton className="group border border-r text-accent-foreground data-[state=open]:text-sidebar-accent-foreground h-10 hover:bg-accent/50 transition-colors duration-200">
🤖 Prompt for AI Agents
In apps/snow-leopard/components/sidebar/feedback-widget.tsx at line 99, the
className string contains a syntax error with the data attribute selector.
Remove the space after the colon in `data-[state=open]:
text-sidebar-accent-foreground` so it reads
`data-[state=open]:text-sidebar-accent-foreground` to ensure proper CSS class
application.

);
}

const analysisPrompt = `You are a literary style analyst. Summarize the distinctive writing style of the author in 2-3 concise sentences, focusing on tone, vocabulary, sentence structure, and any notable quirks. Do not mention the author in third person; instead, describe the style directly (e.g., "Uses short, punchy sentences and casual slang."). Text to analyse is delimited by triple quotes.\n\n"""${sampleText}"""`;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential prompt injection vulnerability.

The sampleText is directly interpolated into the prompt without sanitization. Consider sanitizing the input to prevent prompt injection attacks.

-    const analysisPrompt = `You are a literary style analyst. Summarize the distinctive writing style of the author in 2-3 concise sentences, focusing on tone, vocabulary, sentence structure, and any notable quirks. Do not mention the author in third person; instead, describe the style directly (e.g., "Uses short, punchy sentences and casual slang."). Text to analyse is delimited by triple quotes.\n\n"""${sampleText}"""`;
+    const sanitizedText = sampleText.replace(/"""/g, '"""');
+    const analysisPrompt = `You are a literary style analyst. Summarize the distinctive writing style of the author in 2-3 concise sentences, focusing on tone, vocabulary, sentence structure, and any notable quirks. Do not mention the author in third person; instead, describe the style directly (e.g., "Uses short, punchy sentences and casual slang."). Text to analyse is delimited by triple quotes.\n\n"""${sanitizedText}"""`;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/snow-leopard/app/api/user-style/route.ts at line 18, the sampleText is
directly interpolated into the prompt string, which can lead to prompt injection
vulnerabilities. To fix this, sanitize or escape any special characters in
sampleText that could break out of the triple quotes or manipulate the prompt,
ensuring the input cannot alter the intended prompt structure or inject
malicious instructions.

<p className="text-[11px] text-muted-foreground leading-tight">
Leave blank for default behavior. Your instructions shape the
AI&apos;s responses.
Your instructions guide the AI`&apos;`s tone and behavior.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect escape sequence in template literal.

The apostrophe in the template literal is incorrectly escaped with backticks.

-                Your instructions guide the AI`&apos;`s tone and behavior.
+                Your instructions guide the AI's tone and behavior.
📝 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
Your instructions guide the AI`&apos;`s tone and behavior.
Your instructions guide the AI's tone and behavior.
🤖 Prompt for AI Agents
In apps/snow-leopard/components/ai-settings-menu.tsx at line 151, the apostrophe
in the template literal is incorrectly escaped using backticks. Replace the
backtick escape sequence with a proper apostrophe escape sequence or use a
standard apostrophe character to fix the incorrect escape.

Comment on lines +75 to +85
const handleClearProfile = () => {
setWritingStyleSummary("");
setWritingSample("");
setGenerationError(null);
};

const startRetrain = () => {
setWritingStyleSummary("");
setWritingSample("");
setGenerationError(null);
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Eliminate code duplication between handleClearProfile and startRetrain.

Both functions perform identical operations. Consider refactoring to use a single function.

-  const handleClearProfile = () => {
-    setWritingStyleSummary("");
-    setWritingSample("");
-    setGenerationError(null);
-  };
-
-  const startRetrain = () => {
-    setWritingStyleSummary("");
-    setWritingSample("");
-    setGenerationError(null);
-  };
+  const resetWritingStyle = () => {
+    setWritingStyleSummary("");
+    setWritingSample("");
+    setGenerationError(null);
+  };

Then update the button onClick handlers:

-onClick={startRetrain}
+onClick={resetWritingStyle}
-onClick={handleClearProfile}
+onClick={resetWritingStyle}
🤖 Prompt for AI Agents
In apps/snow-leopard/components/ai-settings-menu.tsx around lines 75 to 85, the
functions handleClearProfile and startRetrain contain duplicated code that
resets writingStyleSummary, writingSample, and generationError. Refactor by
creating a single reusable function that performs these state resets, then have
both handleClearProfile and startRetrain call this new function. Finally, update
the button onClick handlers to use the refactored functions accordingly.

@will-lp1 will-lp1 closed this Jul 7, 2025
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