fix: envelope editor mobile view

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Catalin Pit
2026-08-12 12:43:58 +03:00
co-authored by Cursor
parent 617f8cc204
commit 01b02db201
9 changed files with 402 additions and 262 deletions
@@ -1,3 +1,4 @@
import { useIsMobileViewport } from '@documenso/lib/client-only/hooks/use-media-query';
import type { EnvelopeEditorStep } from '@documenso/lib/client-only/providers/envelope-editor-provider';
import { useCurrentEnvelopeEditor } from '@documenso/lib/client-only/providers/envelope-editor-provider';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
@@ -89,6 +90,8 @@ export const EnvelopeEditor = () => {
const [searchParams, setSearchParams] = useSearchParams();
const isMobileViewport = useIsMobileViewport();
const {
general: { minimizeLeftSidebar, allowUploadAndRecipientStep, allowAddFieldsStep, allowPreviewStep },
actions: {
@@ -101,6 +104,10 @@ export const EnvelopeEditor = () => {
},
} = editorConfig;
// Fall back to the icon-only sidebar on small viewports since the full
// sidebar would consume most of the screen.
const isSidebarMinimized = minimizeLeftSidebar || isMobileViewport;
const envelopeEditorSteps = useMemo(() => {
const steps: EnvelopeEditorStepData[] = [];
@@ -175,19 +182,19 @@ export const EnvelopeEditor = () => {
const currentStepData = envelopeEditorSteps.find((step) => step.id === searchParamsStep) || envelopeEditorSteps[0];
return (
<div className="h-screen w-screen bg-envelope-editor-background">
<div className="h-[100dvh] w-full bg-envelope-editor-background">
<EnvelopeEditorHeader />
{/* Main Content Area */}
<div className="flex h-[calc(100vh-4rem)] w-screen">
<div className="flex h-[calc(100dvh-4rem)] w-full">
{/* Left Section - Step Navigation */}
<div
className={cn('flex w-80 flex-shrink-0 flex-col overflow-y-auto border-border border-r bg-background py-4', {
'w-14': minimizeLeftSidebar,
'w-14': isSidebarMinimized,
})}
>
{/* Left section step selector. */}
{minimizeLeftSidebar ? (
{isSidebarMinimized ? (
<div className="flex justify-center px-4">
<div className="relative flex h-10 w-10 items-center justify-center">
<svg className="size-10 -rotate-90" viewBox="0 0 40 40" aria-hidden>
@@ -254,8 +261,8 @@ export const EnvelopeEditor = () => {
<div
className={cn('space-y-3', {
'px-4': !minimizeLeftSidebar,
'mt-4 flex flex-col items-center': minimizeLeftSidebar,
'px-4': !isSidebarMinimized,
'mt-4 flex flex-col items-center': isSidebarMinimized,
})}
>
{envelopeEditorSteps.map((step) => {
@@ -274,7 +281,7 @@ export const EnvelopeEditor = () => {
: 'border border-gray-200 hover:bg-gray-50 dark:border-gray-400/20 dark:hover:bg-gray-400/10'
}`,
{
'p-3': !minimizeLeftSidebar,
'p-3': !isSidebarMinimized,
},
)}
onClick={() => void navigateToStep(step.id as EnvelopeEditorStep)}
@@ -290,7 +297,7 @@ export const EnvelopeEditor = () => {
<Icon className={`h-4 w-4 ${isActive ? 'text-green-600' : 'text-gray-600'}`} />
</div>
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<div>
<div
className={`font-medium text-sm ${
@@ -312,17 +319,17 @@ export const EnvelopeEditor = () => {
<Separator
className={cn('my-6', {
'mx-auto mb-4 w-4/5': minimizeLeftSidebar,
'mx-auto mb-4 w-4/5': isSidebarMinimized,
})}
/>
{/* Quick Actions. */}
<div
className={cn('space-y-3 px-4 [&_.lucide]:text-muted-foreground', {
'px-2': minimizeLeftSidebar,
'px-2': isSidebarMinimized,
})}
>
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<h4 className="font-semibold text-foreground text-sm">
<Trans>Quick Actions</Trans>
</h4>
@@ -334,7 +341,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Settings`)}>
<SettingsIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
{isDocument ? <Trans>Document Settings</Trans> : <Trans>Template Settings</Trans>}
</span>
@@ -352,7 +359,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Send Envelope`)}>
<SendIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
<Trans>Send Document</Trans>
</span>
@@ -367,7 +374,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Resend Envelope`)}>
<SendIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
<Trans>Resend Document</Trans>
</span>
@@ -389,7 +396,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Direct Link`)}>
<LinkIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
<Trans>Direct Link</Trans>
</span>
@@ -407,7 +414,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Duplicate Envelope`)}>
<CopyPlusIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
{isDocument ? <Trans>Duplicate Document</Trans> : <Trans>Duplicate Template</Trans>}
</span>
@@ -424,7 +431,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Save as Template`)}>
<FileOutputIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
<Trans>Save as Template</Trans>
</span>
@@ -444,7 +451,7 @@ export const EnvelopeEditor = () => {
<Button variant="ghost" size="sm" className="w-full justify-start" title={t(msg`Download PDF`)}>
<DownloadCloudIcon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
<Trans>Download PDF</Trans>
</span>
@@ -472,7 +479,7 @@ export const EnvelopeEditor = () => {
>
<Trash2Icon className="h-4 w-4" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
{isDocument ? <Trans>Delete Document</Trans> : <Trans>Delete Template</Trans>}
</span>
@@ -494,20 +501,20 @@ export const EnvelopeEditor = () => {
{!editorConfig.embedded && (
<div
className={cn('mt-auto px-4', {
'px-2': minimizeLeftSidebar,
'px-2': isSidebarMinimized,
})}
>
<Button
variant="ghost"
className={cn('w-full justify-start', {
'flex items-center justify-center': minimizeLeftSidebar,
'flex items-center justify-center': isSidebarMinimized,
})}
asChild
>
<Link to={relativePath.basePath}>
<ArrowLeftIcon className="h-4 w-4 flex-shrink-0" />
{!minimizeLeftSidebar && (
{!isSidebarMinimized && (
<span className="ml-2">
{isDocument ? <Trans>Return to documents</Trans> : <Trans>Return to templates</Trans>}
</span>