From 23ad742ba446a12ca35b0020ea8cf88d3533b05f Mon Sep 17 00:00:00 2001 From: Catalin Pit Date: Thu, 25 Jun 2026 12:18:14 +0300 Subject: [PATCH] feat: add branding preferences reset dialog and integrate with form --- .../branding-preferences-reset-dialog.tsx | 116 ++++++++++++++++++ .../forms/branding-preferences-form.tsx | 34 +++++ 2 files changed, 150 insertions(+) create mode 100644 apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx diff --git a/apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx b/apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx new file mode 100644 index 000000000..067e4df01 --- /dev/null +++ b/apps/remix/app/components/dialogs/branding-preferences-reset-dialog.tsx @@ -0,0 +1,116 @@ +import { Alert, AlertDescription } from '@documenso/ui/primitives/alert'; +import { Button } from '@documenso/ui/primitives/button'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@documenso/ui/primitives/dialog'; +import { Trans } from '@lingui/react/macro'; +import { useState } from 'react'; + +export type BrandingPreferencesResetDialogProps = { + hasAdvancedBranding: boolean; + isSubmitting: boolean; + onReset: () => Promise; + trigger?: React.ReactNode; +}; + +export const BrandingPreferencesResetDialog = ({ + hasAdvancedBranding, + isSubmitting, + onReset, + trigger, +}: BrandingPreferencesResetDialogProps) => { + const [open, setOpen] = useState(false); + const [isResetting, setIsResetting] = useState(false); + + const isLoading = isSubmitting || isResetting; + + const handleResetToDefaults = async () => { + setIsResetting(true); + + try { + await onReset(); + setOpen(false); + } finally { + setIsResetting(false); + } + }; + + return ( + !isLoading && setOpen(value)}> + + {trigger ?? ( + + )} + + + + + + Reset branding preferences + + + + + This will reset all branding preferences to their default values and save the changes immediately. + + + + + + +

+ Once confirmed, the following will be reset: +

+ +
    +
  • + Custom branding enabled setting +
  • +
  • + Branding logo +
  • +
  • + Brand website and brand details +
  • +
  • + Brand colours, including background, foreground, primary, and border colours +
  • + + {hasAdvancedBranding && ( + <> +
  • + Border radius +
  • +
  • + Custom CSS +
  • + + )} +
+
+
+ + + + + + + + +
+
+ ); +}; diff --git a/apps/remix/app/components/forms/branding-preferences-form.tsx b/apps/remix/app/components/forms/branding-preferences-form.tsx index e420fdae7..c97b39922 100644 --- a/apps/remix/app/components/forms/branding-preferences-form.tsx +++ b/apps/remix/app/components/forms/branding-preferences-form.tsx @@ -18,6 +18,7 @@ import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; +import { BrandingPreferencesResetDialog } from '~/components/dialogs/branding-preferences-reset-dialog'; import { useOptionalCurrentTeam } from '~/providers/team'; import { useCspNonce } from '~/utils/nonce'; @@ -67,6 +68,7 @@ export function BrandingPreferencesForm({ const [previewUrl, setPreviewUrl] = useState(''); const [hasLoadedPreview, setHasLoadedPreview] = useState(false); + const [colorPickerKey, setColorPickerKey] = useState(0); const parsedColors = ZCssVarsSchema.safeParse(settings.brandingColors); const initialColors = parsedColors.success ? parsedColors.data : {}; @@ -85,6 +87,27 @@ export function BrandingPreferencesForm({ const isBrandingEnabled = form.watch('brandingEnabled'); + const handleResetToDefaults = async () => { + const data: TBrandingPreferencesFormSchema = { + brandingEnabled: canInherit ? null : false, + brandingLogo: null, + brandingUrl: '', + brandingCompanyDetails: '', + brandingColors: {}, + brandingCss: '', + }; + + await onFormSubmit(data); + + if (previewUrl.startsWith('blob:')) { + URL.revokeObjectURL(previewUrl); + } + + setPreviewUrl(''); + setColorPickerKey((key) => key + 1); + form.reset(data); + }; + useEffect(() => { if (settings.brandingLogo) { const file = JSON.parse(settings.brandingLogo); @@ -346,6 +369,7 @@ export function BrandingPreferencesForm({ Update +