Compare commits

...

4 Commits

Author SHA1 Message Date
ephraimduncan 5a0f438ee6 Merge branch 'main' into feat/prefetch-intent-navigation-links
# Conflicts:
#	apps/remix/app/components/general/app-header.tsx
#	apps/remix/app/components/general/app-nav-desktop.tsx
#	apps/remix/app/components/general/app-nav-mobile.tsx
#	apps/remix/app/components/general/folder/folder-card.tsx
#	apps/remix/app/components/general/folder/folder-grid.tsx
#	apps/remix/app/components/general/menu-switcher.tsx
#	apps/remix/app/components/general/org-menu-switcher.tsx
#	apps/remix/app/components/general/settings-nav-mobile.tsx
#	apps/remix/app/components/tables/admin-claims-table.tsx
#	apps/remix/app/components/tables/admin-dashboard-users-table.tsx
#	apps/remix/app/components/tables/admin-organisations-table.tsx
#	apps/remix/app/components/tables/documents-table-action-button.tsx
#	apps/remix/app/components/tables/organisation-email-domains-table.tsx
#	apps/remix/app/components/tables/templates-table-action-dropdown.tsx
#	apps/remix/app/components/tables/user-billing-organisations-table.tsx
#	apps/remix/app/routes/_authenticated+/admin+/documents._index.tsx
#	apps/remix/app/routes/_authenticated+/admin+/email-domains._index.tsx
#	apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx
#	apps/remix/app/routes/_authenticated+/dashboard.tsx
#	apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.webhooks._index.tsx
#	apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.$id._index.tsx
#	packages/email/template-components/template-document-reminder.tsx
#	packages/ui/primitives/tooltip.tsx
2026-05-08 11:17:51 +00:00
ephraimduncan e0cdddc59c chore: restore translation files from main
These .po files were accidentally reverted during the merge commit.
Restoring them to match main since translations are autogenerated.
2026-04-20 00:40:29 +00:00
ephraimduncan 862b2a78ea Merge branch 'main' into feat/prefetch-intent-navigation-links 2026-04-20 00:20:51 +00:00
ephraimduncan 807ad95354 perf: add prefetch="intent" to navigation Link components
Enables React Router's intent-based prefetching on Link components
across the app, preloading route data and modules on hover/focus
for faster perceived navigation.
2026-03-16 10:02:32 +00:00
49 changed files with 140 additions and 109 deletions
@@ -58,6 +58,7 @@ export const Header = ({ className, ...props }: HeaderProps) => {
>
<div className="mx-auto flex w-full max-w-screen-xl items-center justify-between gap-x-4 px-4 md:justify-normal md:px-8">
<Link
prefetch="intent"
to={getRootHref(params)}
className="hidden rounded-md ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 md:inline"
>
@@ -67,7 +68,7 @@ export const Header = ({ className, ...props }: HeaderProps) => {
<AppNavDesktop setIsCommandMenuOpen={setIsCommandMenuOpen} />
<Button asChild variant="outline" className="relative hidden h-10 w-10 rounded-lg md:flex">
<Link to="/inbox" className="relative block h-10 w-10">
<Link prefetch="intent" to="/inbox" className="relative block h-10 w-10">
<InboxIcon className="h-5 w-5 flex-shrink-0 text-muted-foreground transition-colors hover:text-foreground" />
{unreadCountData && unreadCountData.count > 0 && (
@@ -70,6 +70,7 @@ export const AppNavDesktop = ({ className, setIsCommandMenuOpen, ...props }: App
>
{menuNavigationLinks.map(({ href, label }) => (
<Link
prefetch="intent"
key={href}
to={href}
className={cn(
@@ -80,13 +80,14 @@ export const AppNavMobile = ({ isMenuOpen, onMenuOpenChange }: AppNavMobileProps
return (
<Sheet open={isMenuOpen} onOpenChange={onMenuOpenChange}>
<SheetContent className="flex w-full max-w-[350px] flex-col">
<Link to="/" onClick={handleMenuItemClick}>
<Link prefetch="intent" to="/" onClick={handleMenuItemClick}>
<img src={LogoImage} alt="Documenso Logo" className="dark:invert" width={170} height={25} />
</Link>
<div className="mt-8 flex w-full flex-col items-start gap-y-4">
{menuNavigationLinks.map(({ href, text }) => (
<Link
prefetch="intent"
key={href}
className="flex items-center gap-2 font-semibold text-2xl text-foreground hover:text-foreground/80"
to={href}
@@ -63,7 +63,7 @@ export const DocumentPageViewButton = ({ envelope }: DocumentPageViewButtonProps
))
.with({ isComplete: false }, () => (
<Button className="w-full" asChild>
<Link to={formatPath}>
<Link prefetch="intent" to={formatPath}>
<Trans>Edit</Trans>
</Link>
</Button>
@@ -82,7 +82,7 @@ export const DocumentPageViewDropdown = ({ envelope }: DocumentPageViewDropdownP
{(isOwner || isCurrentTeamDocument) && !isComplete && (
<DropdownMenuItem asChild>
<Link to={`${documentsPath}/${envelope.id}/edit`}>
<Link prefetch="intent" to={`${documentsPath}/${envelope.id}/edit`}>
<Edit className="mr-2 h-4 w-4" />
<Trans>Edit</Trans>
</Link>
@@ -113,7 +113,7 @@ export const DocumentPageViewDropdown = ({ envelope }: DocumentPageViewDropdownP
/>
<DropdownMenuItem asChild>
<Link to={`${documentsPath}/${envelope.id}/logs`}>
<Link prefetch="intent" to={`${documentsPath}/${envelope.id}/logs`}>
<ScrollTextIcon className="mr-2 h-4 w-4" />
<Trans>Audit Logs</Trans>
</Link>
@@ -74,7 +74,7 @@ export default function EnvelopeEditorHeader() {
{editorConfig.embedded?.customBrandingLogo ? (
<img src={`/api/branding/logo/team/${envelope.teamId}`} alt="Logo" className="h-6 w-auto" />
) : (
<Link to="/">
<Link prefetch="intent" to="/">
<BrandingLogo className="h-6 w-auto" />
</Link>
)}
@@ -504,7 +504,7 @@ export const EnvelopeEditor = () => {
})}
asChild
>
<Link to={relativePath.basePath}>
<Link prefetch="intent" to={relativePath.basePath}>
<ArrowLeftIcon className="h-4 w-4 flex-shrink-0" />
{!minimizeLeftSidebar && (
@@ -54,7 +54,7 @@ export const FolderCard = ({ folder, onMove, onSettings, onDelete }: FolderCardP
};
return (
<Link to={formatPath()} data-folder-id={folder.id} data-folder-name={folder.name}>
<Link prefetch="intent" to={formatPath()} data-folder-id={folder.id} data-folder-name={folder.name}>
<Card className="h-full border border-border transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex min-w-0 items-center gap-3">
@@ -70,7 +70,7 @@ export const FolderGrid = ({ type, parentId }: FolderGridProps) => {
className="flex flex-1 items-center font-medium text-muted-foreground text-sm hover:text-muted-foreground/80"
data-testid="folder-grid-breadcrumbs"
>
<Link to={formatRootPath()} className="flex items-center">
<Link prefetch="intent" to={formatRootPath()} className="flex items-center">
<HomeIcon className="mr-2 h-4 w-4" />
<Trans>Home</Trans>
</Link>
@@ -85,7 +85,7 @@ export const FolderGrid = ({ type, parentId }: FolderGridProps) => {
foldersData?.breadcrumbs.map((folder) => (
<div key={folder.id} className="flex items-center">
<span className="px-3">/</span>
<Link to={formatBreadCrumbPath(folder.id)} className="flex items-center">
<Link prefetch="intent" to={formatBreadCrumbPath(folder.id)} className="flex items-center">
<FolderIcon className="mr-2 h-4 w-4" />
<span>{folder.name}</span>
</Link>
@@ -188,6 +188,7 @@ export const FolderGrid = ({ type, parentId }: FolderGridProps) => {
{unpinnedFolders.length > 12 && (
<div className="mt-2 flex items-center justify-center">
<Link
prefetch="intent"
className="font-medium text-muted-foreground text-sm hover:text-foreground"
to={formatViewAllFoldersPath()}
>
@@ -59,7 +59,11 @@ export const MenuSwitcher = () => {
<DropdownMenuContent className={cn('z-[60] ml-6 w-full min-w-[12rem] md:ml-0')} align="end" forceMount>
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/settings/organisations?action=add-organisation" className="flex items-center justify-between">
<Link
prefetch="intent"
to="/settings/organisations?action=add-organisation"
className="flex items-center justify-between"
>
<Trans>Create Organisation</Trans>
<Plus className="ml-2 h-4 w-4" />
</Link>
@@ -68,20 +72,20 @@ export const MenuSwitcher = () => {
{isUserAdmin && (
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/admin">
<Link prefetch="intent" to="/admin">
<Trans>Admin panel</Trans>
</Link>
</DropdownMenuItem>
)}
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/inbox">
<Link prefetch="intent" to="/inbox">
<Trans>Personal Inbox</Trans>
</Link>
</DropdownMenuItem>
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/settings/profile">
<Link prefetch="intent" to="/settings/profile">
<Trans>User settings</Trans>
</Link>
</DropdownMenuItem>
@@ -147,7 +147,7 @@ export const OrgMenuSwitcher = () => {
)}
asChild
>
<Link to={`/o/${org.url}`} className="flex items-center space-x-2 pr-8">
<Link prefetch="intent" to={`/o/${org.url}`} className="flex items-center space-x-2 pr-8">
<span
className={cn('min-w-0 flex-1 truncate', {
'font-semibold': org.id === selectedOrg?.id,
@@ -161,6 +161,7 @@ export const OrgMenuSwitcher = () => {
{canExecuteOrganisationAction('MANAGE_ORGANISATION', org.currentOrganisationRole) && (
<div className="absolute top-0 right-0 bottom-0 flex items-center justify-center">
<Link
prefetch="intent"
to={`/o/${org.url}/settings`}
className="mr-2 rounded-sm border p-1 text-muted-foreground transition-opacity duration-200 group-hover:opacity-100 md:opacity-0"
>
@@ -172,7 +173,7 @@ export const OrgMenuSwitcher = () => {
))}
<Button variant="ghost" className="w-full justify-start" asChild>
<Link to="/settings/organisations?action=add-organisation">
<Link prefetch="intent" to="/settings/organisations?action=add-organisation">
<Plus className="mr-2 h-4 w-4" />
<Trans>Create Organisation</Trans>
</Link>
@@ -200,7 +201,7 @@ export const OrgMenuSwitcher = () => {
)}
asChild
>
<Link to={`/t/${team.url}`} className="flex items-center space-x-2 pr-8">
<Link prefetch="intent" to={`/t/${team.url}`} className="flex items-center space-x-2 pr-8">
<span
className={cn('min-w-0 flex-1 truncate', {
'font-semibold': team.id === currentTeam?.id,
@@ -214,6 +215,7 @@ export const OrgMenuSwitcher = () => {
{canExecuteTeamAction('MANAGE_TEAM', team.currentTeamRole) && (
<div className="absolute top-0 right-0 bottom-0 flex items-center justify-center">
<Link
prefetch="intent"
to={`/t/${team.url}/settings`}
className="mr-2 rounded-sm border p-1 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100"
>
@@ -231,7 +233,7 @@ export const OrgMenuSwitcher = () => {
{displayedOrg && (
<Button variant="ghost" className="w-full justify-start" asChild>
<Link to={`/o/${displayedOrg.url}/settings/teams?action=add-team`}>
<Link prefetch="intent" to={`/o/${displayedOrg.url}/settings/teams?action=add-team`}>
<Plus className="mr-2 h-4 w-4" />
<Trans>Create Team</Trans>
</Link>
@@ -252,7 +254,7 @@ export const OrgMenuSwitcher = () => {
<div className="flex-1 overflow-y-auto p-1.5">
{isUserAdmin && (
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/admin">
<Link prefetch="intent" to="/admin">
<Trans>Admin panel</Trans>
</Link>
</DropdownMenuItem>
@@ -261,7 +263,7 @@ export const OrgMenuSwitcher = () => {
{currentOrganisation &&
canExecuteOrganisationAction('MANAGE_ORGANISATION', currentOrganisation.currentOrganisationRole) && (
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to={`/o/${currentOrganisation.url}/settings`}>
<Link prefetch="intent" to={`/o/${currentOrganisation.url}/settings`}>
<Trans>Organisation settings</Trans>
</Link>
</DropdownMenuItem>
@@ -269,20 +271,20 @@ export const OrgMenuSwitcher = () => {
{currentTeam && canExecuteTeamAction('MANAGE_TEAM', currentTeam.currentTeamRole) && (
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to={`/t/${currentTeam.url}/settings`}>
<Link prefetch="intent" to={`/t/${currentTeam.url}/settings`}>
<Trans>Team settings</Trans>
</Link>
</DropdownMenuItem>
)}
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/inbox">
<Link prefetch="intent" to="/inbox">
<Trans>Personal Inbox</Trans>
</Link>
</DropdownMenuItem>
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link to="/settings/profile">
<Link prefetch="intent" to="/settings/profile">
<Trans>Account</Trans>
</Link>
</DropdownMenuItem>
@@ -297,6 +299,7 @@ export const OrgMenuSwitcher = () => {
{currentOrganisation && (
<DropdownMenuItem className="px-4 py-2 text-muted-foreground" asChild>
<Link
prefetch="intent"
to={{
pathname: `/o/${currentOrganisation.url}/support`,
search: currentTeam ? `?team=${currentTeam.id}` : '',
@@ -23,7 +23,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
return (
<div className={cn('flex flex-col gap-y-2', className)} {...props}>
<Link to="/settings/profile">
<Link prefetch="intent" to="/settings/profile">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/profile') && 'bg-secondary')}
@@ -35,14 +35,14 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
{isPersonalLayoutMode && (
<>
<Link to="/settings/document">
<Link prefetch="intent" to="/settings/document">
<Button variant="ghost" className={cn('w-full justify-start')}>
<Settings2Icon className="mr-2 h-5 w-5" />
<Trans>Preferences</Trans>
</Button>
</Link>
<Link className="w-full pl-8" to="/settings/document">
<Link prefetch="intent" className="w-full pl-8" to="/settings/document">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/document') && 'bg-secondary')}
@@ -51,7 +51,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Button>
</Link>
<Link className="w-full pl-8" to="/settings/branding">
<Link prefetch="intent" className="w-full pl-8" to="/settings/branding">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/branding') && 'bg-secondary')}
@@ -60,7 +60,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Button>
</Link>
<Link className="w-full pl-8" to="/settings/email">
<Link prefetch="intent" className="w-full pl-8" to="/settings/email">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/email') && 'bg-secondary')}
@@ -69,7 +69,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Button>
</Link>
<Link to="/settings/public-profile">
<Link prefetch="intent" to="/settings/public-profile">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/public-profile') && 'bg-secondary')}
@@ -79,7 +79,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Button>
</Link>
<Link to="/settings/tokens">
<Link prefetch="intent" to="/settings/tokens">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/tokens') && 'bg-secondary')}
@@ -89,7 +89,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Button>
</Link>
<Link to="/settings/webhooks">
<Link prefetch="intent" to="/settings/webhooks">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/webhooks') && 'bg-secondary')}
@@ -101,7 +101,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</>
)}
<Link to="/settings/organisations">
<Link prefetch="intent" to="/settings/organisations">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/organisations') && 'bg-secondary')}
@@ -112,7 +112,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Link>
{IS_BILLING_ENABLED() && hasManageableBillingOrgs && (
<Link to={isPersonalLayoutMode ? '/settings/billing-personal' : `/settings/billing`}>
<Link prefetch="intent" to={isPersonalLayoutMode ? '/settings/billing-personal' : `/settings/billing`}>
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/billing') && 'bg-secondary')}
@@ -123,7 +123,7 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
</Link>
)}
<Link to="/settings/security">
<Link prefetch="intent" to="/settings/security">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/security') && 'bg-secondary')}
@@ -34,7 +34,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
return (
<div className={cn('flex flex-wrap items-center justify-start gap-x-2 gap-y-4', className)} {...props}>
<Link to="/settings/profile">
<Link prefetch="intent" to="/settings/profile">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/profile') && 'bg-secondary')}
@@ -46,7 +46,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
{isPersonalLayoutMode && (
<>
<Link to="/settings/document">
<Link prefetch="intent" to="/settings/document">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/document') && 'bg-secondary')}
@@ -56,7 +56,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Button>
</Link>
<Link to="/settings/branding">
<Link prefetch="intent" to="/settings/branding">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/branding') && 'bg-secondary')}
@@ -66,7 +66,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Button>
</Link>
<Link to="/settings/email">
<Link prefetch="intent" to="/settings/email">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/email') && 'bg-secondary')}
@@ -76,7 +76,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Button>
</Link>
<Link to="/settings/public-profile">
<Link prefetch="intent" to="/settings/public-profile">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/public-profile') && 'bg-secondary')}
@@ -86,7 +86,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Button>
</Link>
<Link to="/settings/tokens">
<Link prefetch="intent" to="/settings/tokens">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/tokens') && 'bg-secondary')}
@@ -96,7 +96,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Button>
</Link>
<Link to="/settings/webhooks">
<Link prefetch="intent" to="/settings/webhooks">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/webhooks') && 'bg-secondary')}
@@ -108,7 +108,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</>
)}
<Link to="/settings/organisations">
<Link prefetch="intent" to="/settings/organisations">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/organisations') && 'bg-secondary')}
@@ -119,7 +119,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Link>
{IS_BILLING_ENABLED() && hasManageableBillingOrgs && (
<Link to={isPersonalLayoutMode ? '/settings/billing-personal' : `/settings/billing`}>
<Link prefetch="intent" to={isPersonalLayoutMode ? '/settings/billing-personal' : `/settings/billing`}>
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/billing') && 'bg-secondary')}
@@ -130,7 +130,7 @@ export const SettingsMobileNav = ({ className, ...props }: SettingsMobileNavProp
</Link>
)}
<Link to="/settings/security">
<Link prefetch="intent" to="/settings/security">
<Button
variant="ghost"
className={cn('w-full justify-start', pathname?.startsWith('/settings/security') && 'bg-secondary')}
@@ -6,7 +6,7 @@ import { Link } from 'react-router';
export default function DocumentEditSkeleton() {
return (
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
<Link to="/" className="flex grow-0 items-center text-documenso-700 hover:opacity-80">
<Link prefetch="intent" to="/" className="flex grow-0 items-center text-documenso-700 hover:opacity-80">
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
<Trans>Documents</Trans>
</Link>
@@ -71,7 +71,11 @@ export const AdminClaimsTable = ({ licenseFlags }: AdminClaimsTableProps) => {
{
header: t`Name`,
accessorKey: 'name',
cell: ({ row }) => <Link to={`/admin/organisations?query=claim:${row.original.id}`}>{row.original.name}</Link>,
cell: ({ row }) => (
<Link prefetch="intent" to={`/admin/organisations?query=claim:${row.original.id}`}>
{row.original.name}
</Link>
),
},
{
header: t`Allowed teams`,
@@ -71,7 +71,7 @@ export const AdminDashboardUsersTable = ({ users, totalPages, perPage, page }: A
cell: ({ row }) => {
return (
<Button className="w-24" asChild>
<Link to={`/admin/users/${row.original.id}`}>
<Link prefetch="intent" to={`/admin/users/${row.original.id}`}>
<Edit className="mr-2 -ml-1 h-4 w-4" />
<Trans>Edit</Trans>
</Link>
@@ -82,7 +82,11 @@ export const AdminOrganisationsTable = ({
{
header: t`Organisation`,
accessorKey: 'name',
cell: ({ row }) => <Link to={`/admin/organisations/${row.original.id}`}>{row.original.name}</Link>,
cell: ({ row }) => (
<Link prefetch="intent" to={`/admin/organisations/${row.original.id}`}>
{row.original.name}
</Link>
),
},
{
header: t`Created At`,
@@ -92,7 +96,11 @@ export const AdminOrganisationsTable = ({
{
header: t`Owner`,
accessorKey: 'owner',
cell: ({ row }) => <Link to={`/admin/users/${row.original.owner.id}`}>{row.original.owner.name}</Link>,
cell: ({ row }) => (
<Link prefetch="intent" to={`/admin/users/${row.original.owner.id}`}>
{row.original.owner.name}
</Link>
),
},
{
id: 'role',
@@ -152,14 +160,14 @@ export const AdminOrganisationsTable = ({
</DropdownMenuLabel>
<DropdownMenuItem asChild>
<Link to={`/admin/organisations/${row.original.id}`}>
<Link prefetch="intent" to={`/admin/organisations/${row.original.id}`}>
<SettingsIcon className="mr-2 h-4 w-4" />
<Trans>Manage</Trans>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to={`/admin/users/${row.original.owner.id}`}>
<Link prefetch="intent" to={`/admin/users/${row.original.owner.id}`}>
<UserIcon className="mr-2 h-4 w-4" />
<Trans>View owner</Trans>
</Link>
@@ -58,7 +58,7 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr
})
.with(isOwner ? { isDraft: true, isOwner: true } : { isDraft: true, isCurrentTeamDocument: true }, () => (
<Button className="w-32" asChild>
<Link to={formatPath}>
<Link prefetch="intent" to={formatPath}>
<Edit className="mr-2 -ml-1 h-4 w-4" />
<Trans>Edit</Trans>
</Link>
@@ -131,7 +131,7 @@ export const DocumentsTableActionDropdown = ({ row, onMoveDocument }: DocumentsT
)}
<DropdownMenuItem disabled={!canManageDocument || isComplete} asChild>
<Link to={formatPath}>
<Link prefetch="intent" to={formatPath}>
<Edit className="mr-2 h-4 w-4" />
<Trans>Edit</Trans>
</Link>
@@ -102,7 +102,9 @@ export const OrganisationEmailDomainsDataTable = () => {
cell: ({ row }) => (
<div className="flex justify-end space-x-2">
<Button asChild variant="outline">
<Link to={`/o/${organisation.url}/settings/email-domains/${row.original.id}`}>Manage</Link>
<Link prefetch="intent" to={`/o/${organisation.url}/settings/email-domains/${row.original.id}`}>
Manage
</Link>
</Button>
<OrganisationEmailDomainDeleteDialog
@@ -80,7 +80,7 @@ export const OrganisationGroupsDataTable = () => {
cell: ({ row }) => (
<div className="flex justify-end space-x-2">
<Button asChild variant="outline">
<Link to={`/o/${organisation.url}/settings/groups/${row.original.id}`}>
<Link prefetch="intent" to={`/o/${organisation.url}/settings/groups/${row.original.id}`}>
<Trans>Manage</Trans>
</Link>
</Button>
@@ -76,7 +76,7 @@ export const OrganisationTeamsTable = () => {
cell: ({ row }) => (
<div className="flex justify-end space-x-2">
<Button variant="outline" asChild>
<Link to={`/t/${row.original.url}/settings`}>
<Link prefetch="intent" to={`/t/${row.original.url}/settings`}>
<Trans>Manage</Trans>
</Link>
</Button>
@@ -78,7 +78,7 @@ export const TemplatesTableActionDropdown = ({
{canMutate && (
<>
<DropdownMenuItem asChild>
<Link to={formatPath}>
<Link prefetch="intent" to={formatPath}>
<Edit className="mr-2 h-4 w-4" />
<Trans>Edit</Trans>
</Link>
@@ -74,7 +74,7 @@ export const UserBillingOrganisationsTable = () => {
id: 'actions',
cell: ({ row }) => (
<Button asChild variant="outline">
<Link to={`/o/${row.original.url}/settings/billing`}>
<Link prefetch="intent" to={`/o/${row.original.url}/settings/billing`}>
<Trans>Manage Billing</Trans>
</Link>
</Button>
@@ -92,7 +92,7 @@ export const UserOrganisationsTable = () => {
<div className="flex justify-end space-x-2">
{canExecuteOrganisationAction('MANAGE_ORGANISATION', row.original.currentOrganisationRole) && (
<Button variant="outline" asChild>
<Link to={`/o/${row.original.url}/settings`}>
<Link prefetch="intent" to={`/o/${row.original.url}/settings`}>
<Trans>Manage</Trans>
</Link>
</Button>
@@ -95,7 +95,7 @@ export default function Layout({ loaderData, params, matches }: Route.ComponentP
}}
primaryButton={
<Button asChild>
<Link to="/">
<Link prefetch="intent" to="/">
<Trans>Go home</Trans>
</Link>
</Button>
@@ -64,7 +64,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/stats') && 'bg-secondary')}
asChild
>
<Link to="/admin/stats">
<Link prefetch="intent" to="/admin/stats">
<BarChart3 className="mr-2 h-5 w-5" />
<Trans>Stats</Trans>
</Link>
@@ -75,7 +75,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/organisations') && 'bg-secondary')}
asChild
>
<Link to="/admin/organisations">
<Link prefetch="intent" to="/admin/organisations">
<Building2Icon className="mr-2 h-5 w-5" />
<Trans>Organisations</Trans>
</Link>
@@ -86,7 +86,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/claims') && 'bg-secondary')}
asChild
>
<Link to="/admin/claims">
<Link prefetch="intent" to="/admin/claims">
<Wallet2 className="mr-2 h-5 w-5" />
<Trans>Claims</Trans>
</Link>
@@ -97,7 +97,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/users') && 'bg-secondary')}
asChild
>
<Link to="/admin/users">
<Link prefetch="intent" to="/admin/users">
<Users className="mr-2 h-5 w-5" />
<Trans>Users</Trans>
</Link>
@@ -108,7 +108,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/documents') && 'bg-secondary')}
asChild
>
<Link to="/admin/documents">
<Link prefetch="intent" to="/admin/documents">
<FileStack className="mr-2 h-5 w-5" />
<Trans>Documents</Trans>
</Link>
@@ -122,7 +122,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
)}
asChild
>
<Link to="/admin/unsealed-documents">
<Link prefetch="intent" to="/admin/unsealed-documents">
<AlertTriangleIcon className="mr-2 h-5 w-5" />
<Trans>Unsealed Documents</Trans>
</Link>
@@ -133,7 +133,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/email-domains') && 'bg-secondary')}
asChild
>
<Link to="/admin/email-domains">
<Link prefetch="intent" to="/admin/email-domains">
<MailIcon className="mr-2 h-5 w-5" />
<Trans>Email Domains</Trans>
</Link>
@@ -147,7 +147,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
)}
asChild
>
<Link to="/admin/organisation-insights">
<Link prefetch="intent" to="/admin/organisation-insights">
<Trophy className="mr-2 h-5 w-5" />
<Trans>Organisation Insights</Trans>
</Link>
@@ -158,7 +158,7 @@ export default function AdminLayout({ loaderData }: Route.ComponentProps) {
className={cn('justify-start md:w-full', pathname?.startsWith('/admin/site-settings') && 'bg-secondary')}
asChild
>
<Link to="/admin/site-settings">
<Link prefetch="intent" to="/admin/site-settings">
<Settings className="mr-2 h-5 w-5" />
<Trans>Site Settings</Trans>
</Link>
@@ -154,7 +154,7 @@ export default function AdminDocumentDetailsPage({ loaderData }: Route.Component
</TooltipProvider>
<Button variant="outline" asChild>
<Link to={`/admin/users/${envelope.userId}`}>
<Link prefetch="intent" to={`/admin/users/${envelope.userId}`}>
<Trans>Go to owner</Trans>
</Link>
</Button>
@@ -61,6 +61,7 @@ export default function AdminDocumentsPage() {
cell: ({ row }) => {
return (
<Link
prefetch="intent"
to={`/admin/documents/${row.original.envelopeId}`}
className="block max-w-[5rem] truncate font-medium hover:underline md:max-w-[10rem]"
>
@@ -85,7 +86,7 @@ export default function AdminDocumentsPage() {
return (
<Tooltip delayDuration={200}>
<TooltipTrigger>
<Link to={`/admin/users/${row.original.user.id}`}>
<Link prefetch="intent" to={`/admin/users/${row.original.user.id}`}>
<Avatar className="h-12 w-12 border-2 border-white border-solid dark:border-border">
<AvatarFallback className="text-muted-foreground text-xs">{avatarFallbackText}</AvatarFallback>
</Avatar>
@@ -58,6 +58,7 @@ export default function AdminEmailDomainsPage() {
accessorKey: 'domain',
cell: ({ row }) => (
<Link
prefetch="intent"
to={`/admin/email-domains/${row.original.id}`}
className="block max-w-[10rem] truncate font-medium hover:underline md:max-w-[15rem]"
>
@@ -69,7 +70,11 @@ export default function AdminEmailDomainsPage() {
header: _(msg`Organisation`),
accessorKey: 'organisation',
cell: ({ row }) => (
<Link to={`/admin/organisations/${row.original.organisation.id}`} className="hover:underline">
<Link
prefetch="intent"
to={`/admin/organisations/${row.original.organisation.id}`}
className="hover:underline"
>
{row.original.organisation.name}
</Link>
),
@@ -112,7 +117,7 @@ export default function AdminEmailDomainsPage() {
header: _(msg`Actions`),
cell: ({ row }) => (
<Button asChild variant="outline" size="sm">
<Link to={`/admin/email-domains/${row.original.id}`}>
<Link prefetch="intent" to={`/admin/email-domains/${row.original.id}`}>
<Trans>View</Trans>
</Link>
</Button>
@@ -48,7 +48,7 @@ export default function OrganisationInsights({ loaderData }: Route.ComponentProp
<div className="flex items-center justify-between">
<h2 className="font-semibold text-4xl">{organisationName}</h2>
<Button variant="outline" asChild>
<Link to={`/admin/organisations/${organisationId}`}>
<Link prefetch="intent" to={`/admin/organisations/${organisationId}`}>
<Trans>Manage organisation</Trans>
</Link>
</Button>
@@ -132,7 +132,7 @@ export default function OrganisationGroupSettingsPage({ params, loaderData }: Ro
header: t`Member`,
cell: ({ row }) => (
<div className="space-y-1">
<Link className="font-medium hover:underline" to={`/admin/users/${row.original.user.id}`}>
<Link prefetch="intent" className="font-medium hover:underline" to={`/admin/users/${row.original.user.id}`}>
{row.original.user.name ?? row.original.user.email}
</Link>
{row.original.user.name && (
@@ -236,7 +236,7 @@ export default function OrganisationGroupSettingsPage({ params, loaderData }: Ro
}}
primaryButton={
<Button asChild>
<Link to={`/admin/organisations`}>
<Link prefetch="intent" to={`/admin/organisations`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -250,7 +250,7 @@ export default function OrganisationGroupSettingsPage({ params, loaderData }: Ro
<div>
<SettingsHeader title={t`Manage organisation`} subtitle={t`Manage the ${organisation.name} organisation`}>
<Button variant="outline" asChild>
<Link to={`/admin/organisation-insights/${organisationId}`}>
<Link prefetch="intent" to={`/admin/organisation-insights/${organisationId}`}>
<Trans>View insights</Trans>
</Link>
</Button>
@@ -57,7 +57,7 @@ export default function UserPage({ params }: { params: { id: number } }) {
}}
primaryButton={
<Button asChild>
<Link to={`/admin/users`}>
<Link prefetch="intent" to={`/admin/users`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -74,7 +74,7 @@ export default function DashboardPage() {
</div>
<Button asChild className="mt-4" variant="outline">
<Link to="/settings/organisations?action=add-organisation">
<Link prefetch="intent" to="/settings/organisations?action=add-organisation">
<Trans>Create organisation</Trans>
</Link>
</Button>
@@ -102,7 +102,7 @@ export default function DashboardPage() {
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{organisations.map((org) => (
<div key={org.id} className="group relative">
<Link to={`/o/${org.url}`}>
<Link prefetch="intent" to={`/o/${org.url}`}>
<Card className="h-full border pr-6 transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
@@ -143,7 +143,7 @@ export default function DashboardPage() {
{canExecuteOrganisationAction('MANAGE_ORGANISATION', org.currentOrganisationRole) && (
<div className="absolute top-4 right-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<Link to={`/o/${org.url}/settings`}>
<Link prefetch="intent" to={`/o/${org.url}/settings`}>
<SettingsIcon className="h-4 w-4" />
</Link>
</div>
@@ -176,7 +176,7 @@ export default function DashboardPage() {
<div className="flex gap-4">
{teams.map((team) => (
<div key={team.id} className="group relative">
<Link to={`/t/${team.url}`}>
<Link prefetch="intent" to={`/t/${team.url}`}>
<Card className="w-[350px] shrink-0 border transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
@@ -212,7 +212,7 @@ export default function DashboardPage() {
{canExecuteTeamAction('MANAGE_TEAM', team.currentTeamRole) && (
<div className="absolute top-4 right-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-hover:opacity-100">
<Link to={`/t/${team.url}/settings`}>
<Link prefetch="intent" to={`/t/${team.url}/settings`}>
<SettingsIcon className="h-4 w-4" />
</Link>
</div>
@@ -115,7 +115,7 @@ export default function OrganisationSettingsTeamsPage() {
</div>
<Button asChild>
<Link to={`/o/${organisation.url}/settings`}>
<Link prefetch="intent" to={`/o/${organisation.url}/settings`}>
<Trans>Manage Organisation</Trans>
</Link>
</Button>
@@ -123,7 +123,7 @@ export default function OrganisationSettingsTeamsPage() {
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{organisation.teams.map((team) => (
<Link to={`/t/${team.url}`} key={team.id}>
<Link prefetch="intent" to={`/t/${team.url}`} key={team.id}>
<Card className="h-full border border-border transition-all hover:bg-muted/50">
<CardContent className="p-4">
<div className="flex items-center gap-3">
@@ -178,19 +178,19 @@ const TeamDropdownMenu = ({ team }: { team: TGetOrganisationSessionResponse[0]['
</DropdownMenuTrigger>
<DropdownMenuContent align="end" onClick={(e) => e.stopPropagation()}>
<DropdownMenuItem asChild>
<Link to={`/t/${team.url}`}>
<Link prefetch="intent" to={`/t/${team.url}`}>
<ArrowRight className="mr-2 h-4 w-4" />
<Trans>Go to team</Trans>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to={`/t/${team.url}/settings`}>
<Link prefetch="intent" to={`/t/${team.url}/settings`}>
<SettingsIcon className="mr-2 h-4 w-4" />
<Trans>Settings</Trans>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to={`/t/${team.url}/settings/members`}>
<Link prefetch="intent" to={`/t/${team.url}/settings/members`}>
<UsersIcon className="mr-2 h-4 w-4" />
<Trans>Members</Trans>
</Link>
@@ -122,7 +122,7 @@ export default function SettingsLayout() {
}}
primaryButton={
<Button asChild>
<Link to={`/o/${organisation.url}`}>
<Link prefetch="intent" to={`/o/${organisation.url}`}>
<Trans>Go Back</Trans>
</Link>
</Button>
@@ -118,7 +118,7 @@ export default function OrganisationEmailDomainSettingsPage({ params }: Route.Co
}}
primaryButton={
<Button asChild>
<Link to={`/o/${organisation.url}/settings/email-domains`}>
<Link prefetch="intent" to={`/o/${organisation.url}/settings/email-domains`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -83,7 +83,7 @@ export default function OrganisationGroupSettingsPage({ params }: Route.Componen
}}
primaryButton={
<Button asChild>
<Link to={`/o/${organisation.url}/settings/groups`}>
<Link prefetch="intent" to={`/o/${organisation.url}/settings/groups`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -126,7 +126,7 @@ export default function SettingsSecurity({ loaderData }: Route.ComponentProps) {
</div>
<Button asChild variant="outline" className="bg-background">
<Link to="/settings/security/passkeys">
<Link prefetch="intent" to="/settings/security/passkeys">
<Trans>Manage passkeys</Trans>
</Link>
</Button>
@@ -144,7 +144,7 @@ export default function SettingsSecurity({ loaderData }: Route.ComponentProps) {
</div>
<Button asChild variant="outline" className="bg-background">
<Link to="/settings/security/activity">
<Link prefetch="intent" to="/settings/security/activity">
<Trans>View activity</Trans>
</Link>
</Button>
@@ -162,7 +162,7 @@ export default function SettingsSecurity({ loaderData }: Route.ComponentProps) {
</div>
<Button asChild variant="outline" className="bg-background">
<Link to="/settings/security/sessions">
<Link prefetch="intent" to="/settings/security/sessions">
<Trans>Manage sessions</Trans>
</Link>
</Button>
@@ -180,7 +180,7 @@ export default function SettingsSecurity({ loaderData }: Route.ComponentProps) {
</div>
<Button asChild variant="outline" className="bg-background">
<Link to="/settings/security/linked-accounts">
<Link prefetch="intent" to="/settings/security/linked-accounts">
<Trans>Manage linked accounts</Trans>
</Link>
</Button>
@@ -57,7 +57,7 @@ export default function Layout() {
}}
primaryButton={
<Button asChild>
<Link to="/settings/teams">
<Link prefetch="intent" to="/settings/teams">
<Trans>View teams</Trans>
</Link>
</Button>
@@ -93,7 +93,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
}}
primaryButton={
<Button asChild>
<Link to={`/t/${team.url}/documents`}>
<Link prefetch="intent" to={`/t/${team.url}/documents`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -112,7 +112,7 @@ export default function DocumentPage({ params }: Route.ComponentProps) {
<DocumentRecipientLinkCopyDialog recipients={envelope.recipients} />
)}
<Link to={documentRootPath} className="flex items-center text-documenso-700 hover:opacity-80">
<Link prefetch="intent" to={documentRootPath} className="flex items-center text-documenso-700 hover:opacity-80">
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
<Trans>Documents</Trans>
</Link>
@@ -83,7 +83,7 @@ export function ErrorBoundary({ error, params }: Route.ErrorBoundaryProps) {
secondaryButton={null}
primaryButton={
<Button asChild className="w-32">
<Link to={`/t/${params.teamUrl}/documents`}>
<Link prefetch="intent" to={`/t/${params.teamUrl}/documents`}>
<ChevronLeftIcon className="mr-2 h-4 w-4" />
<Trans>Go Back</Trans>
</Link>
@@ -86,7 +86,7 @@ export default function EnvelopeEditorPage({ params }: Route.ComponentProps) {
}}
primaryButton={
<Button asChild>
<Link to={`/t/${team.url}/documents`}>
<Link prefetch="intent" to={`/t/${team.url}/documents`}>
<Trans>Go home</Trans>
</Link>
</Button>
@@ -107,7 +107,7 @@ export default function TeamsSettingsLayout() {
}}
primaryButton={
<Button asChild>
<Link to={`/t/${team.url}`}>
<Link prefetch="intent" to={`/t/${team.url}`}>
<Trans>Go Back</Trans>
</Link>
</Button>
@@ -203,7 +203,7 @@ export default function WebhookPage({ params }: Route.ComponentProps) {
}}
primaryButton={
<Button asChild>
<Link to={`/t/${team.url}/settings/webhooks`}>
<Link prefetch="intent" to={`/t/${team.url}/settings/webhooks`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -48,7 +48,7 @@ export default function WebhookPage() {
{
header: t`Webhook`,
cell: ({ row }) => (
<Link to={`/t/${team.url}/settings/webhooks/${row.original.id}`}>
<Link prefetch="intent" to={`/t/${team.url}/settings/webhooks/${row.original.id}`}>
<p className="text-muted-foreground text-xs">{row.original.id}</p>
<p className="max-w-sm truncate font-semibold text-foreground text-xs" title={row.original.webhookUrl}>
{row.original.webhookUrl}
@@ -159,7 +159,7 @@ const WebhookTableActionDropdown = ({ webhook }: { webhook: Webhook }) => {
</DropdownMenuLabel>
<DropdownMenuItem asChild>
<Link to={`/t/${team.url}/settings/webhooks/${webhook.id}`}>
<Link prefetch="intent" to={`/t/${team.url}/settings/webhooks/${webhook.id}`}>
<ScrollTextIcon className="mr-2 h-4 w-4" />
<Trans>Logs</Trans>
</Link>
@@ -77,7 +77,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
}}
primaryButton={
<Button asChild>
<Link to={`/t/${team.url}/templates`}>
<Link prefetch="intent" to={`/t/${team.url}/templates`}>
<Trans>Go back</Trans>
</Link>
</Button>
@@ -118,7 +118,7 @@ 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">
<div className="flex flex-row justify-between">
<Link to={templateRootPath} className="flex items-center text-documenso-700 hover:opacity-80">
<Link prefetch="intent" 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>
@@ -139,7 +139,7 @@ export default function TemplatePage({ params }: Route.ComponentProps) {
/>
<Button asChild size="sm">
<Link to={`${templateRootPath}/${envelope.id}/edit`}>
<Link prefetch="intent" to={`${templateRootPath}/${envelope.id}/edit`}>
<LucideEdit className="mr-1.5 h-3.5 w-3.5" />
<Trans>Edit Template</Trans>
</Link>
@@ -101,7 +101,7 @@ export function ErrorBoundary({ error, params }: Route.ErrorBoundaryProps) {
secondaryButton={null}
primaryButton={
<Button asChild className="w-32">
<Link to={`/t/${params.teamUrl}/templates`}>
<Link prefetch="intent" to={`/t/${params.teamUrl}/templates`}>
<ChevronLeftIcon className="mr-2 h-4 w-4" />
<Trans>Go Back</Trans>
</Link>
+1 -1
View File
@@ -61,7 +61,7 @@ export function AutoSizedText({ children, className, maxHeight, useRem = false }
return;
}
let newFontSize: number;
let newFontSize = fontSize.current;
const targetHeight = maxHeight && maxHeight < parentDimensions.height ? maxHeight : parentDimensions.height;