feat(editor): opt-in diff preview before save (#855)

* feat(editor): add useComposeDiffPreviewEnabled hook

* feat(editor): add ComposeDiffPreviewDialog component

* fix(editor): replace HTML entity with Unicode arrow in ComposeDiffPreviewDialog

* feat(editor): add diff preview toggle to Appearance settings

Added a new 'Diff preview before save' toggle in the Display section of the Appearance settings panel. Users can now enable or disable the side-by-side diff view before compose and env file edits are saved to disk.

* feat(editor): wire diff preview dialog into compose save flow

* fix(editor): snapshot diff content at open time and fix event name

- Fix useComposeDiffPreviewEnabled and useDeployFeedbackEnabled to use
  the canonical SENCHO_SETTINGS_CHANGED constant from @/lib/events
  instead of the hardcoded string literal (wrong value)
- Snapshot language, original, modified, and fileName into diffPreview
  state at click time to prevent tab-switching from corrupting dialog
  content mid-review
- Remove React.MouseEvent from diffPreview state; pass a no-op stub to
  deployStack in the confirm path (preventDefault/stopPropagation are
  no-ops on an already-settled event anyway)
- Add diff-modal screenshot and document the feature in editor.mdx and
  settings.mdx

* docs(editor): add settings-toggle screenshot for diff preview feature
This commit is contained in:
Anso
2026-04-30 22:01:17 -04:00
committed by GitHub
parent 3e01daf76f
commit a25acbec7c
9 changed files with 290 additions and 5 deletions
@@ -3,6 +3,7 @@ import { Checkbox } from '@/components/ui/checkbox';
import { useDensity } from '@/hooks/use-density';
import type { Density } from '@/hooks/use-density';
import { useDeployFeedbackEnabled } from '@/hooks/use-deploy-feedback-enabled';
import { useComposeDiffPreviewEnabled } from '@/hooks/use-compose-diff-preview-enabled';
import { SettingsSection } from './SettingsSection';
import { SettingsField } from './SettingsField';
@@ -19,6 +20,7 @@ const DENSITY_DESCRIPTIONS: Record<Density, string> = {
export function AppearanceSection() {
const [density, setDensity] = useDensity();
const [isEnabled, setEnabled] = useDeployFeedbackEnabled();
const [diffPreviewEnabled, setDiffPreviewEnabled] = useComposeDiffPreviewEnabled();
return (
<div className="flex flex-col gap-10">
@@ -55,6 +57,25 @@ export function AppearanceSection() {
</label>
</div>
</SettingsField>
<SettingsField
label="Diff preview before save"
helper="Show a side-by-side diff of compose and env edits before they reach disk."
>
<div className="flex items-center gap-2">
<Checkbox
id="compose-diff-preview"
checked={diffPreviewEnabled}
onCheckedChange={(v) => setDiffPreviewEnabled(v === true)}
/>
<label
htmlFor="compose-diff-preview"
className="text-sm text-stat-value cursor-pointer select-none"
>
{diffPreviewEnabled ? 'Enabled' : 'Disabled'}
</label>
</div>
</SettingsField>
</SettingsSection>
<p className="font-mono text-[10px] leading-3 uppercase tracking-[0.18em] text-stat-subtitle/70">