From a60d02898e7c9394c3bcb69255a6f9372e8e2f9f Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Mon, 18 May 2026 20:07:53 -0400 Subject: [PATCH] fix: Hide position submenu for alphabetically-sorted collections (#12377) When a collection is sorted alphabetically the document position is auto-determined, so the "New document" submenu (Before/After/Nested) is replaced by a direct "New document" action that creates a nested document. --- app/actions/definitions/documents.tsx | 78 ++++++++++++++++++++++----- app/hooks/useDocumentMenuAction.tsx | 2 + 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/app/actions/definitions/documents.tsx b/app/actions/definitions/documents.tsx index 4a4fe5fcf1..091903661f 100644 --- a/app/actions/definitions/documents.tsx +++ b/app/actions/definitions/documents.tsx @@ -269,10 +269,14 @@ const createDocumentBefore = createInternalLinkAction({ return false; } const document = stores.documents.get(activeDocumentId); - return ( - !!document?.collectionId && - stores.policies.abilities(currentTeamId).createDocument - ); + if (!document?.collectionId) { + return false; + } + const collection = stores.collections.get(document.collectionId); + if (collection?.sort.field === "title") { + return false; + } + return stores.policies.abilities(currentTeamId).createDocument; }, to: ({ activeDocumentId, stores, sidebarContext }) => { const document = activeDocumentId @@ -307,10 +311,14 @@ const createDocumentAfter = createInternalLinkAction({ return false; } const document = stores.documents.get(activeDocumentId); - return ( - !!document?.collectionId && - stores.policies.abilities(currentTeamId).createDocument - ); + if (!document?.collectionId) { + return false; + } + const collection = stores.collections.get(document.collectionId); + if (collection?.sort.field === "title") { + return false; + } + return stores.policies.abilities(currentTeamId).createDocument; }, to: ({ activeDocumentId, stores, sidebarContext }) => { const document = activeDocumentId @@ -335,6 +343,18 @@ const createDocumentAfter = createInternalLinkAction({ }, }); +function isAlphabeticallySorted( + stores: ActionContext["stores"], + activeDocumentId: string +): boolean { + const document = stores.documents.get(activeDocumentId); + if (!document?.collectionId) { + return false; + } + const collection = stores.collections.get(document.collectionId); + return collection?.sort.field === "title"; +} + export const createNewDocument = createActionWithChildren({ name: ({ t }) => t("New document"), analyticsName: "New document", @@ -342,17 +362,48 @@ export const createNewDocument = createActionWithChildren({ icon: , keywords: "create", visible: ({ currentTeamId, activeDocumentId, stores }) => { - if (!activeDocumentId) { + if (!activeDocumentId || !currentTeamId) { return false; } - - return ( - !!currentTeamId && stores.policies.abilities(currentTeamId).createDocument - ); + if (!stores.policies.abilities(currentTeamId).createDocument) { + return false; + } + return !isAlphabeticallySorted(stores, activeDocumentId); }, children: [createDocumentBefore, createDocumentAfter, createNestedDocument], }); +export const createNewDocumentInAlphabeticalCollection = + createInternalLinkAction({ + name: ({ t }) => t("New document"), + analyticsName: "New document", + section: ActiveDocumentSection, + icon: , + keywords: "create", + visible: ({ currentTeamId, activeDocumentId, stores }) => { + if (!activeDocumentId || !currentTeamId) { + return false; + } + if (!stores.policies.abilities(currentTeamId).createDocument) { + return false; + } + if (!stores.policies.abilities(activeDocumentId).createChildDocument) { + return false; + } + return isAlphabeticallySorted(stores, activeDocumentId); + }, + to: ({ activeDocumentId, sidebarContext }) => { + const [pathname, search] = + newNestedDocumentPath(activeDocumentId).split("?"); + + return { + pathname, + search, + state: { sidebarContext }, + }; + }, + }); + export const starDocument = createAction({ name: ({ t }) => t("Star"), analyticsName: "Star document", @@ -1528,6 +1579,7 @@ export const rootDocumentActions = [ createDocument, createDraftDocument, createNewDocument, + createNewDocumentInAlphabeticalCollection, createNestedDocument, createTemplateFromDocument, deleteDocument, diff --git a/app/hooks/useDocumentMenuAction.tsx b/app/hooks/useDocumentMenuAction.tsx index 559e764b2b..c6de673d1a 100644 --- a/app/hooks/useDocumentMenuAction.tsx +++ b/app/hooks/useDocumentMenuAction.tsx @@ -12,6 +12,7 @@ import { editDocument, shareDocument, createNewDocument, + createNewDocumentInAlphabeticalCollection, importDocument, createTemplateFromDocument, duplicateDocument, @@ -103,6 +104,7 @@ export function useDocumentMenuAction({ applyTemplateFactory({ actions: templateMenuActions }), importDocument, createNewDocument, + createNewDocumentInAlphabeticalCollection, pinDocument, ActionSeparator, openDocumentComments,