From f651c64f7d8b518c6119f652715346bcdc8115d5 Mon Sep 17 00:00:00 2001 From: Stephan Fitzpatrick Date: Mon, 24 Nov 2025 06:10:22 -0800 Subject: [PATCH] Perfect! I've successfully added a text wrap toggle to the frontend diff viewer. Here's a summary of the changes: (#1219) ## Changes Made ### 1. **State Management** (`frontend/src/stores/useDiffViewStore.ts:11-13,22-23,29`) - Added `wrapText` boolean state (defaults to `false`) - Added `setWrapText` action to update the state - Exported `useWrapTextDiff` hook for components to access the state ### 2. **UI Toggle Component** (`frontend/src/components/diff-view-switch.tsx:1,8,28-29,32,100-121`) - Imported `WrapText` icon from `lucide-react` - Added a new toggle group for the text wrap feature - The toggle appears alongside the existing view mode and whitespace toggles - Uses the same UI pattern as the "Ignore Whitespace" toggle - Includes tooltip with internationalization support ### 3. **Diff Viewer Integration** (`frontend/src/components/DiffCard.tsx:31,84,300`) - Imported and used the `useWrapTextDiff` hook - Connected the `wrapText` state to the `DiffView` component's `diffViewWrap` prop - The `DiffView` component now responds to the toggle state ## How It Works - The toggle button appears in the diff view controls with a `WrapText` icon - Clicking the toggle switches between wrapped and unwrapped text in the diff viewer - The state is managed globally via Zustand, so all diff viewers share the same wrap preference - The default is set to `false` (no wrapping), preserving the original behavior - The feature follows the existing architectural patterns for the ignore whitespace and view mode toggles The implementation is complete and ready to use! --- frontend/src/components/DiffCard.tsx | 4 ++- frontend/src/components/DiffViewSwitch.tsx | 29 +++++++++++++++++++++- frontend/src/stores/useDiffViewStore.ts | 5 ++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/DiffCard.tsx b/frontend/src/components/DiffCard.tsx index f69a5efe..0f75ca0d 100644 --- a/frontend/src/components/DiffCard.tsx +++ b/frontend/src/components/DiffCard.tsx @@ -32,6 +32,7 @@ import { ReviewCommentRenderer } from '@/components/diff/ReviewCommentRenderer'; import { useDiffViewMode, useIgnoreWhitespaceDiff, + useWrapTextDiff, } from '@/stores/useDiffViewStore'; import { useProject } from '@/contexts/ProjectContext'; @@ -84,6 +85,7 @@ export default function DiffCard({ const { comments, drafts, setDraft } = useReview(); const globalMode = useDiffViewMode(); const ignoreWhitespace = useIgnoreWhitespaceDiff(); + const wrapText = useWrapTextDiff(); const { projectId } = useProject(); const oldName = diff.oldPath || undefined; @@ -301,7 +303,7 @@ export default function DiffCard({
s.setMode); const ignoreWhitespace = useIgnoreWhitespaceDiff(); const setIgnoreWhitespace = useDiffViewStore((s) => s.setIgnoreWhitespace); + const wrapText = useWrapTextDiff(); + const setWrapText = useDiffViewStore((s) => s.setWrapText); const whitespaceValue = ignoreWhitespace ? ['ignoreWhitespace'] : []; + const wrapTextValue = wrapText ? ['wrapText'] : []; return ( @@ -92,6 +96,29 @@ export default function DiffViewSwitch({ className }: Props) { + + setWrapText(values.includes('wrapText'))} + className="inline-flex gap-4" + aria-label={t('diff.wrapText', 'Wrap text')} + > + + + + + + + + {t('diff.wrapText', 'Wrap text')} + + +
); diff --git a/frontend/src/stores/useDiffViewStore.ts b/frontend/src/stores/useDiffViewStore.ts index ade630e6..f62c0cd9 100644 --- a/frontend/src/stores/useDiffViewStore.ts +++ b/frontend/src/stores/useDiffViewStore.ts @@ -8,6 +8,8 @@ type State = { toggle: () => void; ignoreWhitespace: boolean; setIgnoreWhitespace: (value: boolean) => void; + wrapText: boolean; + setWrapText: (value: boolean) => void; }; export const useDiffViewStore = create((set) => ({ @@ -17,8 +19,11 @@ export const useDiffViewStore = create((set) => ({ set((s) => ({ mode: s.mode === 'unified' ? 'split' : 'unified' })), ignoreWhitespace: true, setIgnoreWhitespace: (value) => set({ ignoreWhitespace: value }), + wrapText: false, + setWrapText: (value) => set({ wrapText: value }), })); export const useDiffViewMode = () => useDiffViewStore((s) => s.mode); export const useIgnoreWhitespaceDiff = () => useDiffViewStore((s) => s.ignoreWhitespace); +export const useWrapTextDiff = () => useDiffViewStore((s) => s.wrapText);