fix: update legal links on recipient routes (#3419)

This commit is contained in:
Lucas Smith
2026-10-03 17:04:35 +10:00
committed by GitHub
parent 8a41a3bf61
commit 5311457b4b
4 changed files with 75 additions and 56 deletions
@@ -31,6 +31,7 @@ import { SignFieldTextDialog } from '~/components/dialogs/sign-field-text-dialog
import { useEmbedSigningContext } from '~/components/embed/embed-signing-context';
import { EnvelopeSignerPageRenderer } from '~/components/general/envelope-signing/envelope-signer-page-renderer';
import { EnvelopePdfViewer } from '~/components/general/pdf-viewer/envelope-pdf-viewer';
import { PublicLegalLinks } from '~/components/general/public-legal-links';
import { BrandingLogo } from '../branding-logo';
import { DocumentSigningAttachmentsPopover } from '../document-signing/document-signing-attachments-popover';
@@ -231,6 +232,8 @@ export const DocumentSigningPageViewV2 = () => {
</Button>
</div>
)}
{!isEmbed && <PublicLegalLinks className="mt-4 justify-start px-4 pt-4" />}
</div>
</div>
</div>
@@ -17,7 +17,7 @@ import { match } from 'ts-pattern';
import { EnvelopeDownloadDialog } from '~/components/dialogs/envelope-download-dialog';
import { useEmbedSigningContext } from '~/components/embed/embed-signing-context';
import { BrandingLogo } from '~/components/general/branding-logo';
import { PublicLegalLinks } from '~/components/general/public-legal-links';
import { PublicLegalLinksDropdownMenuItems } from '~/components/general/public-legal-links';
import { BrandingLogoIcon } from '../branding-logo-icon';
import { DocumentSigningRejectDialog } from '../document-signing/document-signing-reject-dialog';
@@ -69,10 +69,8 @@ export const EnvelopeSignerHeader = () => {
</div>
{/* Right side - Desktop content */}
<div className="hidden items-center space-x-4 lg:flex">
<PublicLegalLinks />
<p className="flex-shrink-0 text-muted-foreground text-sm">
<div className="hidden items-center space-x-2 lg:flex">
<p className="mr-2 flex-shrink-0 text-muted-foreground text-sm">
<Plural one="1 Field Remaining" other="# Fields Remaining" value={recipientFieldsRemaining.length} />
</p>
@@ -90,7 +88,10 @@ export const EnvelopeSignerHeader = () => {
const MobileDropdownMenu = () => {
const { envelope, recipient } = useRequiredEnvelopeSigningContext();
const { allowDocumentRejection } = useEmbedSigningContext() || {};
const embedSigningContext = useEmbedSigningContext();
const isEmbedSigning = embedSigningContext !== null;
const { allowDocumentRejection } = embedSigningContext || {};
return (
<DropdownMenu>
@@ -130,6 +131,8 @@ const MobileDropdownMenu = () => {
}
/>
)}
{!isEmbedSigning && <PublicLegalLinksDropdownMenuItems />}
</DropdownMenuContent>
</DropdownMenu>
);
@@ -4,7 +4,9 @@ import {
NEXT_PUBLIC_TERMS_OF_SERVICE_URL,
} from '@documenso/lib/constants/app';
import { cn } from '@documenso/ui/lib/utils';
import { Trans } from '@lingui/react/macro';
import { DropdownMenuItem, DropdownMenuSeparator } from '@documenso/ui/primitives/dropdown-menu';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Link } from 'react-router';
export type PublicLegalLinksProps = {
@@ -12,49 +14,70 @@ export type PublicLegalLinksProps = {
};
export const PublicLegalLinks = ({ className }: PublicLegalLinksProps) => {
const termsUrl = NEXT_PUBLIC_TERMS_OF_SERVICE_URL();
const privacyUrl = NEXT_PUBLIC_PRIVACY_POLICY_URL();
const imprintUrl = NEXT_PUBLIC_IMPRINT_URL();
const { _ } = useLingui();
const links = getPublicLegalLinks();
if (links.length === 0) {
return null;
}
return (
<div
className={cn(
'flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-xs text-muted-foreground',
'flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-muted-foreground text-xs',
className,
)}
>
{termsUrl && (
{links.map((link) => (
<Link
to={termsUrl}
key={link.href}
to={link.href}
target="_blank"
rel="noopener noreferrer"
className="duration-200 hover:text-foreground hover:underline"
>
<Trans>Terms of Service</Trans>
{_(link.label)}
</Link>
)}
{privacyUrl && (
<Link
to={privacyUrl}
target="_blank"
rel="noopener noreferrer"
className="duration-200 hover:text-foreground hover:underline"
>
<Trans>Privacy Policy</Trans>
</Link>
)}
{imprintUrl && (
<Link
to={imprintUrl}
target="_blank"
rel="noopener noreferrer"
className="duration-200 hover:text-foreground hover:underline"
>
<Trans>Imprint</Trans>
</Link>
)}
))}
</div>
);
};
export const PublicLegalLinksDropdownMenuItems = () => {
const { _ } = useLingui();
const links = getPublicLegalLinks();
if (links.length === 0) {
return null;
}
return (
<>
<DropdownMenuSeparator />
{links.map((link) => (
<DropdownMenuItem key={link.href} asChild className="text-muted-foreground text-xs">
<Link to={link.href} target="_blank" rel="noopener noreferrer">
{_(link.label)}
</Link>
</DropdownMenuItem>
))}
</>
);
};
const getPublicLegalLinks = () => {
const termsUrl = NEXT_PUBLIC_TERMS_OF_SERVICE_URL();
const privacyUrl = NEXT_PUBLIC_PRIVACY_POLICY_URL();
const imprintUrl = NEXT_PUBLIC_IMPRINT_URL();
const links = [
termsUrl ? { label: msg`Terms of Service`, href: termsUrl } : null,
privacyUrl ? { label: msg`Privacy Policy`, href: privacyUrl } : null,
imprintUrl ? { label: msg`Imprint`, href: imprintUrl } : null,
];
return links.filter((link) => link !== null);
};
+9 -19
View File
@@ -10,8 +10,6 @@ import { useEffect } from 'react';
import { isRouteErrorResponse, Link, Outlet } from 'react-router';
import { Header as AuthenticatedHeader } from '~/components/general/app-header';
import { GenericErrorLayout } from '~/components/general/generic-error-layout';
import { PublicLegalLinks } from '~/components/general/public-legal-links';
import type { Route } from './+types/_layout';
export function meta() {
@@ -37,24 +35,16 @@ export default function RecipientLayout({ matches }: Route.ComponentProps) {
);
return (
<div className="flex min-h-screen flex-col justify-between">
<div>
{!hideHeader && sessionData?.user && <AuthenticatedHeader />}
<div className="min-h-screen">
{!hideHeader && sessionData?.user && <AuthenticatedHeader />}
<main
className={cn({
'mt-8 mb-8 px-4 md:mt-12 md:mb-12 md:px-8': !hideHeader,
})}
>
<Outlet />
</main>
</div>
{!hideHeader && (
<footer className="py-4">
<PublicLegalLinks />
</footer>
)}
<main
className={cn({
'mt-8 mb-8 px-4 md:mt-12 md:mb-12 md:px-8': !hideHeader,
})}
>
<Outlet />
</main>
</div>
);
}