Skip to content

Comments

writing-style: Switch to Tiptap editor and preserve line breaks#1182

Merged
elie222 merged 3 commits intomainfrom
feat/writing-style-rich-text-editor
Jan 4, 2026
Merged

writing-style: Switch to Tiptap editor and preserve line breaks#1182
elie222 merged 3 commits intomainfrom
feat/writing-style-rich-text-editor

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Jan 3, 2026

User description

Switches the writing style input from a plain textarea to a Tiptap rich text editor to allow better visual formatting. Also adds a prop to Tiptap to optionally preserve line breaks on paste to prevent paragraphs from collapsing.

  • Switched WritingStyleSetting to use Tiptap via Controller
  • Added preservePastedLineBreaks prop to Tiptap component
  • Configured Markdown extension in Tiptap to handle line breaks and list markers when enabled

Generated description

Below is a concise technical summary of the changes proposed in this PR:

graph LR
WritingStyleDialog_("WritingStyleDialog"):::modified
Tiptap_("Tiptap"):::modified
onSubmit_("onSubmit"):::added
SAVE_WRITING_STYLE_ACTION_("SAVE_WRITING_STYLE_ACTION"):::modified
TIPTAP_("TIPTAP"):::modified
MARKDOWN_("MARKDOWN"):::modified
WritingStyleDialog_ -- "Now provides markdown output, placeholder, and preserved pasted breaks." --> Tiptap_
Tiptap_ -- "Emits markdown or HTML via onChange depending on output prop." --> WritingStyleDialog_
WritingStyleDialog_ -- "Adds onSubmit to call execute with form data." --> onSubmit_
onSubmit_ -- "Sends markdown writingStyle payload to save action." --> SAVE_WRITING_STYLE_ACTION_
Tiptap_ -- "Adds placeholder extension and configurable markdown/html output." --> TIPTAP_
Tiptap_ -- "Conditionally configures Markdown to transform pasted text and output." --> MARKDOWN_
classDef added stroke:#15AA7A
classDef removed stroke:#CD5270
classDef modified stroke:#EDAC4C
linkStyle default stroke:#CBD5E1,font-size:13px
Loading

Integrate the Tiptap rich text editor component into the WritingStyleSetting to replace the previous plain text input. Enhance the Tiptap component to preserve line breaks when pasting content and to output markdown.

TopicDetails
Tiptap Editor Integration Integrate the Tiptap rich text editor into the WritingStyleSetting component, replacing the standard Input field. This involves using react-hook-form's Controller to manage the editor's state and outputting content as markdown.
Modified files (2)
  • apps/web/components/editor/Tiptap.tsx
  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
Latest Contributors(1)
UserCommitDate
elie222adjust-placeholderJanuary 03, 2026
Preserve Line Breaks Add a preservePastedLineBreaks prop to the Tiptap component, configuring the Markdown extension to handle line breaks and list markers correctly when enabled. This ensures that pasted content retains its original formatting.
Modified files (2)
  • apps/web/components/editor/Tiptap.tsx
  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
Latest Contributors(1)
UserCommitDate
elie222adjust-placeholderJanuary 03, 2026
This pull request is reviewed by Baz. Review like a pro on (Baz).

@vercel
Copy link

vercel bot commented Jan 3, 2026

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

Project Deployment Review Updated (UTC)
inbox-zero Ready Ready Preview Jan 4, 2026 0:37am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 3, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

These changes integrate the Tiptap rich text editor into the WritingStyle setting form, replacing plain textarea input with markdown editor capabilities, and extend Tiptap with support for preserving pasted line breaks through configurable markdown transformation options.

Changes

Cohort / File(s) Summary
WritingStyleSetting Form Integration
apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
Refactored form field handling to use Controller wrapper around Tiptap editor instance; added useRef to hold editor reference for markdown extraction; introduced onSubmit handler that reads markdown content from editor ref; added error display for writingStyle field and adjusted button spacing.
Tiptap Editor Configuration
apps/web/components/editor/Tiptap.tsx
Added new optional prop preservePastedLineBreaks (default: false) with conditional Markdown extension configuration; when enabled, applies strict markdown parsing with line break preservation and text transformation on paste/copy operations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • baz-reviewer

Poem

🐰 A scribe's pen meets the editor's dance,
Tiptap now preserves each line's chance,
Controller guides the markdown flow,
Writing styles bloom and brightly glow! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main changes: switching the writing style input from a textarea to a Tiptap editor and adding line break preservation functionality.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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

Comment @coderabbitai help to get the list of available commands and usage tips.

@macroscopeapp
Copy link
Contributor

macroscopeapp bot commented Jan 3, 2026

Switch the assistant writing style dialog to a Tiptap editor that preserves pasted line breaks and submits markdown content in WritingStyleDialog.tsx and extend editor/Tiptap to support markdown output and placeholders in Tiptap.tsx

Replace the Input field with a Tiptap editor for writingStyle using react-hook-form Controller, emit markdown on change, preserve pasted line breaks, and show an inline validation error; extend editor/Tiptap to support output="markdown", placeholder, and preservePastedLineBreaks.

📍Where to Start

Start with the WritingStyleDialog form setup and Tiptap integration in WritingStyleSetting.tsx, then review the Tiptap props and onUpdate behavior in Tiptap.tsx.


Macroscope summarized 1ae47e4.

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

♻️ Duplicate comments (1)
apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx (1)

130-134: Error display won't function correctly without form state connection.

While the error display implementation is correct, it won't show validation errors because the form state is not being updated as the user types. This is related to the issue flagged in the onSubmit handler.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d3ac0a and 7de31a4.

📒 Files selected for processing (2)
  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)

**/*.{ts,tsx}: For API GET requests to server, use the swr package
Use result?.serverError with toastError from @/components/Toast for error handling in async operations

**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls

**/*.{ts,tsx}: For early access feature flags, create hooks using the naming convention use[FeatureName]Enabled that return a boolean from useFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming convention use[FeatureName]Variant that define variant types, use useFeatureFlagVariantKey() with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g., inbox-cleaner, pricing-options-2)
Always define types for A/B test variant flags (e.g., type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting

**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the ! postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Use as const instead of literal types and type annotations
Use either T[] or Array<T> consistently
Initialize each enum member value explicitly
Use export type for types
Use `impo...

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/app/(app)/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)

apps/web/app/(app)/**/*.{ts,tsx}: Components for the page are either put in page.tsx, or in the apps/web/app/(app)/PAGE_NAME folder
If we're in a deeply nested component we will use swr to fetch via API
If you need to use onClick in a component, that component is a client component and file must start with use client

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)

Always import Prisma enums from @/generated/prisma/enums instead of @/generated/prisma/client to avoid Next.js bundling errors in client components

Import Prisma using the project's centralized utility: import prisma from '@/utils/prisma'

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Import specific lodash functions rather than entire lodash library to minimize bundle size (e.g., import groupBy from 'lodash/groupBy')

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Do not export types/interfaces that are only used within the same file. Export later if needed

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Use next/image package for images
For API GET requests to server, use the swr package with hooks like useSWR to fetch data
For text inputs, use the Input component with registerProps for form integration and error handling

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.{tsx,ts,css}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

Implement responsive design with Tailwind CSS using a mobile-first approach

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

**/*.tsx: Use the LoadingContent component to handle loading states instead of manual loading state management
For text areas, use the Input component with type='text', autosizeTextarea prop set to true, and registerProps for form integration

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use accessKey attribute on any HTML element
Don't set aria-hidden="true" on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like <marquee> or <blink>
Only use the scope prop on <th> elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assign tabIndex to non-interactive HTML elements
Don't use positive integers for tabIndex property
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include a title element for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
Assign tabIndex to non-interactive HTML elements with aria-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include a type attribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden)
Always include a lang attribute on the html element
Always include a title attribute for iframe elements
Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress
Accompany onMouseOver/onMouseOut with onFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{jsx,tsx}: Don't use unnecessary fragments
Don't pass children as props
Don't use the return value of React.render
Make sure all dependencies are correctly specified in React hooks
Make sure all React hooks are called from the top level of component functions
Don't forget key props in iterators and collection literals
Don't define React components inside other components
Don't use event handlers on non-interactive elements
Don't assign to React component props
Don't use both children and dangerouslySetInnerHTML props on the same element
Don't use dangerous JSX props
Don't use Array index in keys
Don't insert comments as text nodes
Don't assign JSX properties multiple times
Don't add extra closing tags for components without children
Use <>...</> instead of <Fragment>...</Fragment>
Watch out for possible "wrong" semicolons inside JSX elements
Make sure void (self-closing) elements don't have children
Don't use target="_blank" without rel="noopener"
Don't use <img> elements in Next.js projects
Don't use <head> elements in Next.js projects

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
!(pages/_document).{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

Don't use the next/head module in pages/_document.js on Next.js projects

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)

**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g., import groupBy from 'lodash/groupBy')

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx,js,jsx}: Use @/ path aliases for imports from project root
Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments
Add helper functions to the bottom of files, not the top
All imports go at the top of files, no mid-file dynamic imports

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

Follow NextJS app router structure with (app) directory

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
apps/web/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{tsx,jsx}: Follow tailwindcss patterns with prettier-plugin-tailwindcss for class sorting
Prefer functional components with hooks in React
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach in components
Follow consistent naming conventions using PascalCase for components
Use LoadingContent component for async data with loading and error states
Use React Hook Form with Zod validation for form handling
Use result?.serverError with toastError and toastSuccess for error handling in forms

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/**/*.{ts,tsx,js,jsx,json,css}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

Format code with Prettier

Files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
apps/web/components/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/fullstack-workflow.mdc)

Use LoadingContent component to consistently handle loading and error states, passing loading, error, and children props

Use PascalCase for component file names (e.g., components/Button.tsx)

Files:

  • apps/web/components/editor/Tiptap.tsx
**/{pages,routes,components}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/gmail-api.mdc)

Never call Gmail API directly from routes or components - always use wrapper functions from the utils folder

Files:

  • apps/web/components/editor/Tiptap.tsx
🧠 Learnings (14)
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.tsx : For text areas, use the `Input` component with `type='text'`, `autosizeTextarea` prop set to true, and `registerProps` for form integration

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text areas in forms, use the `Input` component with `type='text'`, `autosizeTextarea` prop, `rows`, `name`, `placeholder`, `registerProps` from react-hook-form, and `error` props

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
  • apps/web/components/editor/Tiptap.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : For text inputs, use the `Input` component with `registerProps` for form integration and error handling

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:40:15.063Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:15.063Z
Learning: Applies to **/*.{tsx,ts} : Use Shadcn UI and Tailwind for components and styling

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Use Shadcn UI and Tailwind for components and styling

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:40:13.649Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-11-25T14:40:13.649Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : For text inputs in forms, use the `Input` component with `type='email'`, `name`, `label`, `registerProps` from react-hook-form, and `error` props

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Validate form inputs before submission using React Hook Form and Zod resolver

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-12-21T12:21:37.794Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-12-21T12:21:37.794Z
Learning: Applies to apps/web/**/*.{tsx,jsx} : Use React Hook Form with Zod validation for form handling

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:36:51.389Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:51.389Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for form validation

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:36:53.147Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/form-handling.mdc:0-0
Timestamp: 2025-11-25T14:36:53.147Z
Learning: Applies to **/*Form.{ts,tsx} : Use React Hook Form with Zod for validation in form components

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:38:56.992Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:56.992Z
Learning: Components with `onClick` handlers must be client components marked with the `use client` directive

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:37:09.306Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/fullstack-workflow.mdc:0-0
Timestamp: 2025-11-25T14:37:09.306Z
Learning: Applies to apps/web/components/**/*Form*.tsx : Use React Hook Form with Zod validation (`zodResolver`) for form handling, with form components using `register`, `handleSubmit`, and error handling from the hook

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx
📚 Learning: 2025-11-25T14:38:18.874Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/page-structure.mdc:0-0
Timestamp: 2025-11-25T14:38:18.874Z
Learning: Applies to apps/web/app/(app)/**/*.tsx : If you need to use `onClick` in a component, that component must be a client component and file must start with `use client` directive

Applied to files:

  • apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.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). (4)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Baz Reviewer
  • GitHub Check: test
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
apps/web/components/editor/Tiptap.tsx (2)

23-23: LGTM: Clean prop addition with backward compatibility.

The new preservePastedLineBreaks prop is well-named and defaults to false, ensuring existing behavior is preserved.

Also applies to: 32-32


50-59: No issues found. All configuration options (transformPastedText, transformCopiedText, breaks, linkify, bulletListMarker) are supported by tiptap-markdown v0.8.10 and correctly configured.

apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx (2)

3-4: LGTM: Proper imports and ref setup.

The additions of useRef, Controller, and Tiptap imports along with the editorRef are correctly implemented for the new rich text editor integration.

Also applies to: 27-27, 65-65


115-129: Good UX: Scrollable container and rich text styling.

The Tiptap editor integration includes good UX choices:

  • Scrollable container prevents dialog overflow
  • Prose classes provide appropriate rich text styling
  • preservePastedLineBreaks is correctly enabled
  • autofocus={false} prevents unwanted focus in dialog

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx">

<violation number="1" location="apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx:125">
P1: The `Controller` is not passing `field.onChange` to the `Tiptap` component, so react-hook-form won&#39;t track edits. This means form validation will never run on the current content, and `errors.writingStyle` will always be based on the initial value rather than what the user typed.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

initialContent={field.value ?? ""}
className="prose prose-sm dark:prose-invert max-w-none"
autofocus={false}
preservePastedLineBreaks
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 3, 2026

Choose a reason for hiding this comment

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

P1: The Controller is not passing field.onChange to the Tiptap component, so react-hook-form won't track edits. This means form validation will never run on the current content, and errors.writingStyle will always be based on the initial value rather than what the user typed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/app/(app)/[emailAccountId]/assistant/settings/WritingStyleSetting.tsx, line 125:

<comment>The `Controller` is not passing `field.onChange` to the `Tiptap` component, so react-hook-form won&#39;t track edits. This means form validation will never run on the current content, and `errors.writingStyle` will always be based on the initial value rather than what the user typed.</comment>

<file context>
@@ -105,24 +111,28 @@ function WritingStyleDialog({
+                  initialContent={field.value ?? &quot;&quot;}
+                  className=&quot;prose prose-sm dark:prose-invert max-w-none&quot;
+                  autofocus={false}
+                  preservePastedLineBreaks
+                /&gt;
+              &lt;/div&gt;
</file context>
Suggested change
preservePastedLineBreaks
onChange={field.onChange}
preservePastedLineBreaks

✅ Addressed in 1ae47e4

Copy link
Contributor

Choose a reason for hiding this comment

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

Commit 1ae47e4 addressed this comment by adding the missing onChange={field.onChange} prop to the Tiptap component (line 122). This allows react-hook-form to properly track edits and run validation on the current content. The onSubmit function was also simplified to use the form data directly instead of manually extracting content from the editor ref.

@elie222 elie222 merged commit 0b539df into main Jan 4, 2026
33 checks passed
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