From a46f668e712ffa6ff1afcce6307c3c5104994c33 Mon Sep 17 00:00:00 2001 From: ephraimduncan Date: Tue, 7 Jul 2026 08:01:15 +0000 Subject: [PATCH] feat(ui): redesign recipient field hover card --- .../envelope-recipient-field-tooltip.tsx | 136 ++++++++++-------- 1 file changed, 80 insertions(+), 56 deletions(-) diff --git a/packages/ui/components/document/envelope-recipient-field-tooltip.tsx b/packages/ui/components/document/envelope-recipient-field-tooltip.tsx index b9a79586e..3e94a203f 100644 --- a/packages/ui/components/document/envelope-recipient-field-tooltip.tsx +++ b/packages/ui/components/document/envelope-recipient-field-tooltip.tsx @@ -2,16 +2,27 @@ import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-c import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; import { Trans, useLingui } from '@lingui/react/macro'; import type { Field, Recipient } from '@prisma/client'; -import { SigningStatus } from '@prisma/client'; -import { ClockIcon, EyeOffIcon, LockIcon } from 'lucide-react'; -import { useCallback, useEffect, useState } from 'react'; +import { FieldType, SigningStatus } from '@prisma/client'; +import { + CalendarDaysIcon, + CheckSquareIcon, + ChevronDownIcon, + ContactIcon, + DiscIcon, + EyeOffIcon, + HashIcon, + LockIcon, + MailIcon, + TypeIcon, + UserIcon, +} from 'lucide-react'; +import { type ElementType, useCallback, useEffect, useState } from 'react'; import { isTemplateRecipientEmailPlaceholder } from '../../../lib/constants/template'; import { extractInitials } from '../../../lib/utils/recipient-formatter'; import { SignatureIcon } from '../../icons/signature'; import { cn } from '../../lib/utils'; import { Avatar, AvatarFallback } from '../../primitives/avatar'; -import { Badge } from '../../primitives/badge'; import { FRIENDLY_FIELD_TYPE } from '../../primitives/document-flow/types'; import { PopoverHover } from '../../primitives/popover'; @@ -27,16 +38,18 @@ interface EnvelopeRecipientFieldTooltipProps { showRecipientColors?: boolean; } -const getRecipientDisplayText = (recipient: { name: string; email: string }) => { - if (recipient.name && !isTemplateRecipientEmailPlaceholder(recipient.email)) { - return `${recipient.name} (${recipient.email})`; - } - - if (recipient.name && isTemplateRecipientEmailPlaceholder(recipient.email)) { - return recipient.name; - } - - return recipient.email; +const FIELD_TYPE_ICONS: Record = { + [FieldType.SIGNATURE]: SignatureIcon, + [FieldType.FREE_SIGNATURE]: SignatureIcon, + [FieldType.INITIALS]: ContactIcon, + [FieldType.TEXT]: TypeIcon, + [FieldType.DATE]: CalendarDaysIcon, + [FieldType.EMAIL]: MailIcon, + [FieldType.NAME]: UserIcon, + [FieldType.NUMBER]: HashIcon, + [FieldType.RADIO]: DiscIcon, + [FieldType.CHECKBOX]: CheckSquareIcon, + [FieldType.DROPDOWN]: ChevronDownIcon, }; /** @@ -50,6 +63,8 @@ export function EnvelopeRecipientFieldTooltip({ }: EnvelopeRecipientFieldTooltipProps) { const { t } = useLingui(); + const FieldIcon = FIELD_TYPE_ICONS[field.type]; + const [hideField, setHideField] = useState(!showRecipientTooltip); const [coords, setCoords] = useState({ @@ -138,54 +153,63 @@ export function EnvelopeRecipientFieldTooltip({ } contentProps={{ - className: 'relative flex mb-4 w-fit flex-col p-4 text-sm', + className: 'flex w-64 flex-col overflow-hidden p-0 text-sm', + sideOffset: 6, }} > - {showFieldStatus && ( - - {field?.fieldMeta?.readOnly ? ( - <> - - Read Only - - ) : field.recipient.signingStatus === SigningStatus.SIGNED ? ( - <> - - Signed - - ) : ( - <> - - Pending - - )} - - )} +
+ -

- +

{t(FRIENDLY_FIELD_TYPE[field.type])} field - -

+

-

{getRecipientDisplayText(field.recipient)}

+ {showFieldStatus && ( +
+ {field?.fieldMeta?.readOnly ? ( + <> + + + Read Only + + + ) : field.recipient.signingStatus === SigningStatus.SIGNED ? ( + <> + + + Signed + + + ) : ( + <> + + + Pending + + + )} +
+ )} +
- +
+
+

{field.recipient.name || field.recipient.email}

+ + {!isTemplateRecipientEmailPlaceholder(field.recipient.email) && field.recipient.name && ( +

{field.recipient.email}

+ )} +
+ + +
);