fix: remove envelope title cropping (#2739)

This commit is contained in:
David Nguyen
2026-04-28 16:01:19 +10:00
committed by GitHub
parent 61338af216
commit 2f4c3893a3
7 changed files with 67 additions and 63 deletions
@@ -114,7 +114,7 @@ export const TemplateBulkSendDialog = ({
<Dialog>
<DialogTrigger asChild>
{trigger ?? (
<Button variant="outline">
<Button variant="outline" className="shrink-0" size="sm">
<Upload className="mr-2 h-4 w-4" />
<Trans>Bulk Send via CSV</Trans>
</Button>
@@ -55,6 +55,7 @@ type TemplateDirectLinkDialogProps = {
directLink?: Pick<TemplateDirectLink, 'token' | 'enabled'> | null;
recipients: TRecipientLite[];
trigger?: React.ReactNode;
triggerSizeVariant?: 'default' | 'sm' | 'lg';
onCreateSuccess?: () => Promise<void> | void;
onDeleteSuccess?: () => Promise<void> | void;
};
@@ -66,6 +67,7 @@ export const TemplateDirectLinkDialog = ({
directLink,
recipients,
trigger,
triggerSizeVariant = 'sm',
onCreateSuccess,
onDeleteSuccess,
}: TemplateDirectLinkDialogProps) => {
@@ -208,7 +210,7 @@ export const TemplateDirectLinkDialog = ({
<Dialog open={open} onOpenChange={(value) => !isLoading && setOpen(value)}>
<DialogTrigger asChild>
{trigger || (
<Button variant="outline" className="px-3">
<Button variant="outline" className="shrink-0 px-3" size={triggerSizeVariant}>
<LinkIcon className="mr-1.5 h-3.5 w-3.5" />
{directLink ? <Trans>Manage Direct Link</Trans> : <Trans>Create Direct Link</Trans>}
@@ -74,8 +74,8 @@ export default function EnvelopeEditorHeader() {
return (
<nav className="w-full border-b border-border bg-background px-4 py-3 md:px-6">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className="flex items-center justify-between gap-4">
<div className="flex min-w-0 flex-1 items-center space-x-4">
{editorConfig.embedded?.customBrandingLogo ? (
<img
src={`/api/branding/logo/team/${envelope.teamId}`}
@@ -87,9 +87,9 @@ export default function EnvelopeEditorHeader() {
<BrandingLogo className="h-6 w-auto" />
</Link>
)}
<Separator orientation="vertical" className="h-6" />
<Separator orientation="vertical" className="h-6 shrink-0" />
<div className="flex items-center space-x-2">
<div className="flex min-w-0 items-center space-x-2">
<EnvelopeItemTitleInput
dataTestId="envelope-title-input"
disabled={!envelopeItemPermissions.canTitleBeChanged || !allowConfigureEnvelopeTitle}
@@ -107,19 +107,19 @@ export default function EnvelopeEditorHeader() {
{envelope.type === EnvelopeType.TEMPLATE && (
<>
{envelope.templateType === TemplateType.PRIVATE && (
<Badge variant="secondary">
<Badge variant="secondary" className="shrink-0">
<LockIcon className="mr-2 h-4 w-4 text-blue-600 dark:text-blue-300" />
<Trans>Private Template</Trans>
</Badge>
)}
{envelope.templateType === TemplateType.ORGANISATION && (
<Badge variant="orange">
<Badge variant="orange" className="shrink-0">
<Building2Icon className="mr-2 size-4" />
<Trans>Organisation Template</Trans>
</Badge>
)}
{envelope.templateType === TemplateType.PUBLIC && (
<Badge variant="default">
<Badge variant="default" className="shrink-0">
<Globe2Icon className="mr-2 h-4 w-4 text-green-500 dark:text-green-300" />
<Trans>Public Template</Trans>
</Badge>
@@ -127,7 +127,7 @@ export default function EnvelopeEditorHeader() {
{envelope.directLink?.token && (
<TemplateDirectLinkBadge
className="py-1"
className="shrink-0 py-1"
token={envelope.directLink.token}
enabled={envelope.directLink.enabled}
/>
@@ -138,22 +138,22 @@ export default function EnvelopeEditorHeader() {
{envelope.type === EnvelopeType.DOCUMENT &&
match(envelope.status)
.with(DocumentStatus.DRAFT, () => (
<Badge variant="warning">
<Badge variant="warning" className="shrink-0">
<Trans>Draft</Trans>
</Badge>
))
.with(DocumentStatus.PENDING, () => (
<Badge variant="secondary">
<Badge variant="secondary" className="shrink-0">
<Trans>Pending</Trans>
</Badge>
))
.with(DocumentStatus.COMPLETED, () => (
<Badge variant="default">
<Badge variant="default" className="shrink-0">
<Trans>Completed</Trans>
</Badge>
))
.with(DocumentStatus.REJECTED, () => (
<Badge variant="destructive">
<Badge variant="destructive" className="shrink-0">
<Trans>Rejected</Trans>
</Badge>
))
@@ -161,7 +161,7 @@ export default function EnvelopeEditorHeader() {
{autosaveError && (
<>
<Badge variant="destructive">
<Badge variant="destructive" className="shrink-0">
<AlertTriangleIcon className="mr-2 h-4 w-4" />
<Trans>Sync failed, changes not saved</Trans>
</Badge>
@@ -171,7 +171,7 @@ export default function EnvelopeEditorHeader() {
window.location.reload();
}}
>
<Badge variant="destructive">
<Badge variant="destructive" className="shrink-0">
<RefreshCwIcon className="mr-2 h-4 w-4" />
<Trans>Reload</Trans>
</Badge>
@@ -181,7 +181,7 @@ export default function EnvelopeEditorHeader() {
</div>
</div>
<div className="flex items-center space-x-2">
<div className="flex shrink-0 items-center space-x-2">
{allowAttachments &&
(isEmbedded ? (
<EmbeddedEditorAttachmentPopover buttonSize="sm" />
@@ -3,6 +3,9 @@ import { useEffect, useRef, useState } from 'react';
import { ZDocumentTitleSchema } from '@documenso/trpc/server/document-router/schema';
import { cn } from '@documenso/ui/lib/utils';
const MIN_INPUT_WIDTH = 100;
const INPUT_WIDTH_PADDING = 16;
export type EnvelopeItemTitleInputProps = {
value: string;
onChange: (value: string) => void;
@@ -27,11 +30,12 @@ export const EnvelopeItemTitleInput = ({
const inputRef = useRef<HTMLInputElement>(null);
const measureRef = useRef<HTMLSpanElement>(null);
// Update input width based on content
useEffect(() => {
if (measureRef.current) {
const width = measureRef.current.offsetWidth;
setInputWidth(Math.max(width + 16, 100)); // Add padding and minimum width
const nextInputWidth = Math.max(width + INPUT_WIDTH_PADDING, MIN_INPUT_WIDTH);
setInputWidth(nextInputWidth);
}
}, [envelopeItemTitle]);
@@ -55,7 +59,7 @@ export const EnvelopeItemTitleInput = ({
};
return (
<div className="relative">
<div className="relative min-w-0 max-w-full shrink">
{/* Hidden span to measure text width */}
<span
ref={measureRef}
@@ -73,9 +77,9 @@ export const EnvelopeItemTitleInput = ({
value={envelopeItemTitle}
onChange={(e) => handleTitleChange(e.target.value)}
disabled={disabled}
style={{ width: `${inputWidth}px` }}
style={{ width: `${inputWidth}px`, maxWidth: '100%' }}
className={cn(
'rounded-sm border-0 bg-transparent p-1 text-sm font-medium text-foreground outline-none hover:outline hover:outline-1 hover:outline-muted-foreground focus:outline focus:outline-1 focus:outline-muted-foreground',
'max-w-full rounded-sm border-0 bg-transparent p-1 text-sm font-medium text-foreground outline-none hover:outline hover:outline-1 hover:outline-muted-foreground focus:outline focus:outline-1 focus:outline-muted-foreground',
className,
{
'outline-red-500': isError,
@@ -525,7 +525,7 @@ export const EnvelopeEditorUploadPage = () => {
snapshot.isDragging ? 'shadow-md' : ''
}`}
>
<div className="flex items-center space-x-3">
<div className="flex min-w-0 items-center space-x-3">
{uploadConfig?.allowConfigureOrder && (
<div
{...provided.dragHandleProps}
@@ -536,7 +536,7 @@ export const EnvelopeEditorUploadPage = () => {
</div>
)}
<div>
<div className="min-w-0">
{localFile.envelopeItemId !== null ? (
<EnvelopeItemTitleInput
disabled={
@@ -564,7 +564,7 @@ export const EnvelopeEditorUploadPage = () => {
</div>
</div>
</div>
<div className="flex items-center space-x-2">
<div className="flex shrink-0 items-center space-x-2">
{localFile.isUploading && (
<div className="flex h-6 w-10 items-center justify-center">
<Loader2Icon className="h-4 w-4 animate-spin text-muted-foreground" />
@@ -108,12 +108,9 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
<Trans>Documents</Trans>
</Link>
<div className="flex flex-row justify-between truncate">
<div>
<h1
className="mt-4 block max-w-[20rem] truncate text-2xl font-semibold md:max-w-[30rem] md:text-3xl"
title={envelope.title}
>
<div className="flex flex-row justify-between gap-4">
<div className="min-w-0">
<h1 className="mt-4 block text-2xl font-semibold md:text-3xl" title={envelope.title}>
{envelope.title}
</h1>
@@ -121,44 +121,23 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
return (
<div className="mx-auto -mt-4 w-full max-w-screen-xl px-4 md:px-8">
<Link to={templateRootPath} className="flex items-center text-documenso-700 hover:opacity-80">
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
<Trans>Templates</Trans>
</Link>
<div className="flex flex-row justify-between">
<Link
to={templateRootPath}
className="flex items-center text-documenso-700 hover:opacity-80"
>
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
<Trans>Templates</Trans>
</Link>
<div className="flex flex-row justify-between truncate">
<div>
<h1
className="mt-4 block max-w-[20rem] truncate text-2xl font-semibold md:max-w-[30rem] md:text-3xl"
title={envelope.title}
>
{envelope.title}
</h1>
<div className="mt-2.5 flex items-center">
<TemplateType
inheritColor
className="text-muted-foreground"
type={envelope.templateType}
/>
{envelope.directLink?.token && (
<TemplateDirectLinkBadge
className="ml-4"
token={envelope.directLink.token}
enabled={envelope.directLink.enabled}
/>
)}
</div>
</div>
<div className="mt-2 flex flex-row space-x-4 sm:mt-0 sm:self-end">
<div className="flex shrink-0 flex-row space-x-4">
{isOwnTeamTemplate && (
<>
<TemplateDirectLinkDialog
templateId={mapSecondaryIdToTemplateId(envelope.secondaryId)}
directLink={envelope.directLink}
recipients={envelope.recipients}
triggerSizeVariant="sm"
/>
<TemplateBulkSendDialog
@@ -166,7 +145,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
recipients={envelope.recipients}
/>
<Button className="w-full" asChild>
<Button asChild size="sm">
<Link to={`${templateRootPath}/${envelope.id}/edit`}>
<LucideEdit className="mr-1.5 h-3.5 w-3.5" />
<Trans>Edit Template</Trans>
@@ -177,6 +156,28 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
</div>
</div>
<div className="min-w-0">
<h1 className="mt-4 block text-2xl font-semibold md:text-3xl" title={envelope.title}>
{envelope.title}
</h1>
<div className="mt-2.5 flex items-center">
<TemplateType
inheritColor
className="text-muted-foreground"
type={envelope.templateType}
/>
{envelope.directLink?.token && (
<TemplateDirectLinkBadge
className="ml-4"
token={envelope.directLink.token}
enabled={envelope.directLink.enabled}
/>
)}
</div>
</div>
<div className="mt-6 grid w-full grid-cols-12 gap-8">
{envelope.internalVersion === 2 ? (
<div className="relative col-span-12 lg:col-span-6 xl:col-span-7">